12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- import type {DependencyList, RefObject} from 'react';
- import {useCallback, useEffect, useMemo, useState} from 'react';
- import type {CellMeasurerCacheParams, MultiGrid} from 'react-virtualized';
- import {CellMeasurerCache} from 'react-virtualized';
- type Opts = {
- /**
- * Options for the CellMeasurerCache constructor
- */
- cellMeasurer: CellMeasurerCacheParams;
- /**
- * How many columns are being rendered
- */
- columnCount: number;
- /**
- * List of other values that should trigger re-computing column sizes
- */
- deps: DependencyList;
- /**
- * There must be one column with a dynamic width, so the table can fill all available width inside the container
- */
- dynamicColumnIndex: number;
- /**
- * The <MultiGrid> elem.
- */
- gridRef: RefObject<MultiGrid>;
- };
- const globalCellMeasurerCache = new WeakMap<CellMeasurerCacheParams, CellMeasurerCache>();
- function useVirtualizedGrid({
- cellMeasurer,
- columnCount,
- deps,
- dynamicColumnIndex,
- gridRef,
- }: Opts) {
- const cache = useMemo(() => {
- if (globalCellMeasurerCache.has(cellMeasurer)) {
- return globalCellMeasurerCache.get(cellMeasurer)!;
- }
- const newCellMeasurer = new CellMeasurerCache(cellMeasurer);
- globalCellMeasurerCache.set(cellMeasurer, newCellMeasurer);
- return newCellMeasurer;
- }, [cellMeasurer]);
- const [scrollBarWidth, setScrollBarWidth] = useState(0);
- const onWrapperResize = useCallback(() => {
- // TODO: debounce?
- gridRef.current?.recomputeGridSize({columnIndex: dynamicColumnIndex});
- }, [gridRef, dynamicColumnIndex]);
- // Recompute the width of the dynamic column when deps change (ie: a search/filter is applied)
- useEffect(onWrapperResize, [onWrapperResize, deps]);
- const onScrollbarPresenceChange = useCallback(({vertical, size}) => {
- setScrollBarWidth(vertical ? size : 0);
- }, []);
- const getColumnWidth = useCallback(
- (width: number) =>
- ({index}) => {
- if (index !== dynamicColumnIndex) {
- return cache.columnWidth({index});
- }
- const columns = Array.from(new Array(columnCount));
- const fullWidth = width - scrollBarWidth;
- // Take the full width available, and remove all the static/cached widths
- // so we know how much space is available for our dynamic column.
- const colWidth = columns.reduce(
- (remainingWidth, _, i) =>
- i === dynamicColumnIndex
- ? remainingWidth
- : remainingWidth - cache.columnWidth({index: i}),
- fullWidth
- );
- return Math.max(colWidth, 200);
- },
- [cache, columnCount, dynamicColumnIndex, scrollBarWidth]
- );
- return {
- cache,
- getColumnWidth,
- onScrollbarPresenceChange,
- onWrapperResize,
- };
- }
- export default useVirtualizedGrid;
|