-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[DataGrid] Add
disableVirtualization
prop (mui#2326)
- Loading branch information
Showing
24 changed files
with
408 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
...cs/data-grid/grid-virtualization-api.json → ...s/api-docs/data-grid/grid-scroll-api.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 0 additions & 7 deletions
7
docs/src/pages/components/data-grid/virtualization/VirtualizationApiNoSnap.js
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './useGridScroll'; |
151 changes: 151 additions & 0 deletions
151
packages/grid/_modules_/grid/hooks/features/scroll/useGridScroll.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
import * as React from 'react'; | ||
import { GridCellIndexCoordinates } from '../../../models/gridCell'; | ||
import { GridApiRef } from '../../../models/api/gridApiRef'; | ||
import { useGridLogger } from '../../utils/useGridLogger'; | ||
import { | ||
gridColumnsMetaSelector, | ||
visibleGridColumnsSelector, | ||
} from '../columns/gridColumnsSelector'; | ||
import { useGridSelector } from '../core/useGridSelector'; | ||
import { GridComponentProps } from '../../../GridComponentProps'; | ||
import { gridPaginationSelector } from '../pagination/gridPaginationSelector'; | ||
import { gridRowCountSelector } from '../rows/gridRowsSelector'; | ||
import { gridDensityRowHeightSelector } from '../density/densitySelector'; | ||
import { GridScrollParams } from '../../../models/params/gridScrollParams'; | ||
import { GridScrollApi } from '../../../models/api/gridScrollApi'; | ||
import { scrollStateSelector } from '../virtualization/renderingStateSelector'; | ||
import { useGridApiMethod } from '../../root/useGridApiMethod'; | ||
import { useNativeEventListener } from '../../root/useNativeEventListener'; | ||
|
||
// Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js | ||
// Similar to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView | ||
function scrollIntoView(dimensions) { | ||
const { clientHeight, scrollTop, offsetHeight, offsetTop } = dimensions; | ||
|
||
const elementBottom = offsetTop + offsetHeight; | ||
if (elementBottom - clientHeight > scrollTop) { | ||
return elementBottom - clientHeight; | ||
} | ||
if (offsetTop < scrollTop) { | ||
return offsetTop; | ||
} | ||
return undefined; | ||
} | ||
|
||
export const useGridScroll = ( | ||
apiRef: GridApiRef, | ||
props: Pick<GridComponentProps, 'pagination'>, | ||
): void => { | ||
const logger = useGridLogger(apiRef, 'useGridScroll'); | ||
const colRef = apiRef.current.columnHeadersElementRef!; | ||
const windowRef = apiRef.current.windowRef!; | ||
|
||
const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector); | ||
const paginationState = useGridSelector(apiRef, gridPaginationSelector); | ||
const totalRowCount = useGridSelector(apiRef, gridRowCountSelector); | ||
const visibleColumns = useGridSelector(apiRef, visibleGridColumnsSelector); | ||
const columnsMeta = useGridSelector(apiRef, gridColumnsMetaSelector); | ||
|
||
const scrollToIndexes = React.useCallback<GridScrollApi['scrollToIndexes']>( | ||
(params: Partial<GridCellIndexCoordinates>) => { | ||
if (totalRowCount === 0 || visibleColumns.length === 0) { | ||
return false; | ||
} | ||
|
||
logger.debug(`Scrolling to cell at row ${params.rowIndex}, col: ${params.colIndex} `); | ||
|
||
const scrollCoordinates: any = {}; | ||
|
||
if (params.colIndex != null) { | ||
scrollCoordinates.left = scrollIntoView({ | ||
clientHeight: windowRef.current!.clientWidth, | ||
scrollTop: windowRef.current!.scrollLeft, | ||
offsetHeight: visibleColumns[params.colIndex].computedWidth, | ||
offsetTop: columnsMeta.positions[params.colIndex], | ||
}); | ||
} | ||
|
||
if (params.rowIndex != null) { | ||
const elementIndex = !props.pagination | ||
? params.rowIndex | ||
: params.rowIndex - paginationState.page * paginationState.pageSize; | ||
|
||
scrollCoordinates.top = scrollIntoView({ | ||
clientHeight: windowRef.current!.clientHeight, | ||
scrollTop: windowRef.current!.scrollTop, | ||
offsetHeight: rowHeight, | ||
offsetTop: rowHeight * elementIndex, | ||
}); | ||
} | ||
|
||
if ( | ||
typeof scrollCoordinates.left !== undefined || | ||
typeof scrollCoordinates.top !== undefined | ||
) { | ||
apiRef.current.scroll(scrollCoordinates); | ||
return true; | ||
} | ||
|
||
return false; | ||
}, | ||
[ | ||
totalRowCount, | ||
visibleColumns, | ||
logger, | ||
apiRef, | ||
props.pagination, | ||
paginationState.page, | ||
paginationState.pageSize, | ||
windowRef, | ||
columnsMeta.positions, | ||
rowHeight, | ||
], | ||
); | ||
|
||
const scroll = React.useCallback<GridScrollApi['scroll']>( | ||
(params: Partial<GridScrollParams>) => { | ||
if (windowRef.current && params.left != null && colRef.current) { | ||
colRef.current.scrollLeft = params.left; | ||
windowRef.current.scrollLeft = params.left; | ||
logger.debug(`Scrolling left: ${params.left}`); | ||
} | ||
if (windowRef.current && params.top != null) { | ||
windowRef.current.scrollTop = params.top; | ||
logger.debug(`Scrolling top: ${params.top}`); | ||
} | ||
logger.debug(`Scrolling, updating container, and viewport`); | ||
}, | ||
[windowRef, colRef, logger], | ||
); | ||
|
||
const getScrollPosition = React.useCallback<GridScrollApi['getScrollPosition']>( | ||
() => scrollStateSelector(apiRef.current.getState()), | ||
[apiRef], | ||
); | ||
|
||
const scrollApi: GridScrollApi = { | ||
scroll, | ||
scrollToIndexes, | ||
getScrollPosition, | ||
}; | ||
useGridApiMethod(apiRef, scrollApi, 'GridScrollApi'); | ||
|
||
const preventScroll = React.useCallback((event: any) => { | ||
event.target.scrollLeft = 0; | ||
event.target.scrollTop = 0; | ||
}, []); | ||
|
||
useNativeEventListener( | ||
apiRef, | ||
() => apiRef.current?.renderingZoneRef?.current?.parentElement, | ||
'scroll', | ||
preventScroll, | ||
); | ||
|
||
useNativeEventListener( | ||
apiRef, | ||
() => apiRef.current?.columnHeadersContainerElementRef?.current, | ||
'scroll', | ||
preventScroll, | ||
); | ||
}; |
2 changes: 1 addition & 1 deletion
2
packages/grid/_modules_/grid/hooks/features/virtualization/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
export * from './useGridVirtualRows'; | ||
export * from './useGridVirtualization'; | ||
export * from './renderingState'; |
81 changes: 81 additions & 0 deletions
81
packages/grid/_modules_/grid/hooks/features/virtualization/useGridNoVirtualization.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import * as React from 'react'; | ||
import { GridComponentProps } from '../../../GridComponentProps'; | ||
import { GridApiRef } from '../../../models/api/gridApiRef'; | ||
import { useNativeEventListener } from '../../root/useNativeEventListener'; | ||
import { useGridScrollFn } from '../../utils/useGridScrollFn'; | ||
import { visibleGridColumnsSelector } from '../columns/gridColumnsSelector'; | ||
import { useGridSelector } from '../core'; | ||
import { useGridState } from '../core/useGridState'; | ||
import { gridPaginationSelector } from '../pagination/gridPaginationSelector'; | ||
|
||
export const useGridNoVirtualization = ( | ||
apiRef: GridApiRef, | ||
props: Pick<GridComponentProps, 'disableVirtualization' | 'pagination' | 'paginationMode'>, | ||
): void => { | ||
const windowRef = apiRef.current.windowRef; | ||
const columnsHeaderRef = apiRef.current.columnHeadersElementRef; | ||
const renderingZoneRef = apiRef.current.renderingZoneRef; | ||
const [gridState, setGridState, forceUpdate] = useGridState(apiRef); | ||
const [scrollTo] = useGridScrollFn(apiRef, renderingZoneRef!, columnsHeaderRef!); | ||
const paginationState = useGridSelector(apiRef, gridPaginationSelector); | ||
const visibleColumns = useGridSelector(apiRef, visibleGridColumnsSelector); | ||
|
||
const syncState = React.useCallback(() => { | ||
if (!gridState.containerSizes || !windowRef?.current) { | ||
return; | ||
} | ||
|
||
let firstRowIdx = 0; | ||
const { page, pageSize } = paginationState; | ||
if (props.pagination && props.paginationMode === 'client') { | ||
firstRowIdx = pageSize * page; | ||
} | ||
const lastRowIdx = firstRowIdx + gridState.containerSizes.virtualRowsCount; | ||
const lastColIdx = visibleColumns.length > 0 ? visibleColumns.length - 1 : 0; | ||
const renderContext = { firstRowIdx, lastRowIdx, firstColIdx: 0, lastColIdx }; | ||
|
||
const scrollParams = { | ||
top: windowRef.current!.scrollTop, | ||
left: windowRef.current!.scrollLeft, | ||
}; | ||
|
||
setGridState((state) => ({ | ||
...state, | ||
rendering: { | ||
...state.rendering, | ||
virtualPage: 0, | ||
renderContext, | ||
realScroll: scrollParams, | ||
renderingZoneScroll: scrollParams, | ||
}, | ||
})); | ||
forceUpdate(); | ||
}, [ | ||
gridState.containerSizes, | ||
paginationState, | ||
props.pagination, | ||
props.paginationMode, | ||
setGridState, | ||
forceUpdate, | ||
visibleColumns.length, | ||
windowRef, | ||
]); | ||
|
||
React.useEffect(() => { | ||
if (!props.disableVirtualization) { | ||
return; | ||
} | ||
syncState(); | ||
}, [props.disableVirtualization, syncState]); | ||
|
||
const handleScroll = React.useCallback(() => { | ||
if (!props.disableVirtualization || !windowRef?.current) { | ||
return; | ||
} | ||
const { scrollLeft, scrollTop } = windowRef.current; | ||
scrollTo({ top: scrollTop, left: scrollLeft }); | ||
syncState(); | ||
}, [props.disableVirtualization, scrollTo, windowRef, syncState]); | ||
|
||
useNativeEventListener(apiRef, windowRef!, 'scroll', handleScroll, { passive: true }); | ||
}; |
Oops, something went wrong.