UNPKG

@mui/x-data-grid

Version:

The community edition of the data grid component (MUI X).

261 lines (214 loc) 11.5 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridRowsMeta = exports.rowsMetaStateInitializer = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _utils = require("@mui/material/utils"); var _useGridVisibleRows = require("../../utils/useGridVisibleRows"); var _useGridApiMethod = require("../../utils/useGridApiMethod"); var _useGridSelector = require("../../utils/useGridSelector"); var _densitySelector = require("../density/densitySelector"); var _gridFilterSelector = require("../filter/gridFilterSelector"); var _gridPaginationSelector = require("../pagination/gridPaginationSelector"); var _gridSortingSelector = require("../sorting/gridSortingSelector"); var _pipeProcessing = require("../../core/pipeProcessing"); var _gridRowsSelector = require("./gridRowsSelector"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const rowsMetaStateInitializer = state => (0, _extends2.default)({}, state, { rowsMeta: { currentPageTotalHeight: 0, positions: [] } }); /** * @requires useGridPageSize (method) * @requires useGridPage (method) */ exports.rowsMetaStateInitializer = rowsMetaStateInitializer; const useGridRowsMeta = (apiRef, props) => { const { getRowHeight: getRowHeightProp, getRowSpacing, getEstimatedRowHeight } = props; const rowsHeightLookup = React.useRef({}); // Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js const lastMeasuredRowIndex = React.useRef(-1); const hasRowWithAutoHeight = React.useRef(false); const rowHeightFromDensity = (0, _useGridSelector.useGridSelector)(apiRef, _densitySelector.gridDensityRowHeightSelector); const filterState = (0, _useGridSelector.useGridSelector)(apiRef, _gridFilterSelector.gridFilterStateSelector); const paginationState = (0, _useGridSelector.useGridSelector)(apiRef, _gridPaginationSelector.gridPaginationSelector); const sortingState = (0, _useGridSelector.useGridSelector)(apiRef, _gridSortingSelector.gridSortingStateSelector); const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props); const pinnedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridPinnedRowsSelector); const hydrateRowsMeta = React.useCallback(() => { var _pinnedRows$top, _pinnedRows$bottom; hasRowWithAutoHeight.current = false; const densityFactor = (0, _densitySelector.gridDensityFactorSelector)(apiRef.current.state, apiRef.current.instanceId); const calculateRowProcessedSizes = row => { if (!rowsHeightLookup.current[row.id]) { rowsHeightLookup.current[row.id] = { sizes: { baseCenter: rowHeightFromDensity }, isResized: false, autoHeight: false, needsFirstMeasurement: true // Assume all rows will need to be measured by default }; } const { isResized, needsFirstMeasurement, sizes } = rowsHeightLookup.current[row.id]; let baseRowHeight = rowHeightFromDensity; const existingBaseRowHeight = sizes.baseCenter; if (isResized) { // Do not recalculate resized row height and use the value from the lookup baseRowHeight = existingBaseRowHeight; } else if (getRowHeightProp) { const rowHeightFromUser = getRowHeightProp((0, _extends2.default)({}, row, { densityFactor })); if (rowHeightFromUser === 'auto') { if (needsFirstMeasurement) { const estimatedRowHeight = getEstimatedRowHeight ? getEstimatedRowHeight((0, _extends2.default)({}, row, { densityFactor })) : rowHeightFromDensity; // If the row was not measured yet use the estimated row height baseRowHeight = estimatedRowHeight != null ? estimatedRowHeight : rowHeightFromDensity; } else { baseRowHeight = existingBaseRowHeight; } hasRowWithAutoHeight.current = true; rowsHeightLookup.current[row.id].autoHeight = true; } else { // Default back to base rowHeight if getRowHeight returns null or undefined. baseRowHeight = rowHeightFromUser != null ? rowHeightFromUser : rowHeightFromDensity; rowsHeightLookup.current[row.id].needsFirstMeasurement = false; rowsHeightLookup.current[row.id].autoHeight = false; } } else { rowsHeightLookup.current[row.id].needsFirstMeasurement = false; } const existingBaseSizes = Object.entries(sizes).reduce((acc, [key, size]) => { if (/^base[A-Z]/.test(key)) { acc[key] = size; } return acc; }, {}); // We use an object to make simple to check if a height is already added or not const initialHeights = (0, _extends2.default)({}, existingBaseSizes, { baseCenter: baseRowHeight }); if (getRowSpacing) { var _spacing$top, _spacing$bottom; const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id); const spacing = getRowSpacing((0, _extends2.default)({}, row, { isFirstVisible: indexRelativeToCurrentPage === 0, isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1, indexRelativeToCurrentPage })); initialHeights.spacingTop = (_spacing$top = spacing.top) != null ? _spacing$top : 0; initialHeights.spacingBottom = (_spacing$bottom = spacing.bottom) != null ? _spacing$bottom : 0; } const processedSizes = apiRef.current.unstable_applyPipeProcessors('rowHeight', initialHeights, row); rowsHeightLookup.current[row.id].sizes = processedSizes; return processedSizes; }; const positions = []; const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => { positions.push(acc); let maximumBaseSize = 0; let otherSizes = 0; const processedSizes = calculateRowProcessedSizes(row); Object.entries(processedSizes).forEach(([size, value]) => { if (/^base[A-Z]/.test(size)) { maximumBaseSize = value > maximumBaseSize ? value : maximumBaseSize; } else { otherSizes += value; } }); return acc + maximumBaseSize + otherSizes; }, 0); pinnedRows == null ? void 0 : (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.forEach(row => { calculateRowProcessedSizes(row); }); pinnedRows == null ? void 0 : (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.forEach(row => { calculateRowProcessedSizes(row); }); apiRef.current.setState(state => { return (0, _extends2.default)({}, state, { rowsMeta: { currentPageTotalHeight, positions } }); }); if (!hasRowWithAutoHeight.current) { // No row has height=auto, so all rows are already measured lastMeasuredRowIndex.current = Infinity; } apiRef.current.forceUpdate(); }, [apiRef, currentPage.rows, rowHeightFromDensity, getRowHeightProp, getRowSpacing, getEstimatedRowHeight, pinnedRows]); const getRowHeight = React.useCallback(rowId => { const height = rowsHeightLookup.current[rowId]; return height ? height.sizes.baseCenter : rowHeightFromDensity; }, [rowHeightFromDensity]); const getRowInternalSizes = rowId => { var _rowsHeightLookup$cur; return (_rowsHeightLookup$cur = rowsHeightLookup.current[rowId]) == null ? void 0 : _rowsHeightLookup$cur.sizes; }; const setRowHeight = React.useCallback((id, height) => { rowsHeightLookup.current[id].sizes.baseCenter = height; rowsHeightLookup.current[id].isResized = true; rowsHeightLookup.current[id].needsFirstMeasurement = false; hydrateRowsMeta(); }, [hydrateRowsMeta]); const debouncedHydrateRowsMeta = React.useMemo(() => (0, _utils.debounce)(hydrateRowsMeta), [hydrateRowsMeta]); const storeMeasuredRowHeight = React.useCallback((id, height, position) => { if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) { return; } // Only trigger hydration if the value is different, otherwise we trigger a loop const needsHydration = rowsHeightLookup.current[id].sizes[`base${(0, _utils.capitalize)(position)}`] !== height; rowsHeightLookup.current[id].needsFirstMeasurement = false; rowsHeightLookup.current[id].sizes[`base${(0, _utils.capitalize)(position)}`] = height; if (needsHydration) { debouncedHydrateRowsMeta(); } }, [debouncedHydrateRowsMeta]); const rowHasAutoHeight = React.useCallback(id => { var _rowsHeightLookup$cur2; return ((_rowsHeightLookup$cur2 = rowsHeightLookup.current[id]) == null ? void 0 : _rowsHeightLookup$cur2.autoHeight) || false; }, []); const getLastMeasuredRowIndex = React.useCallback(() => { return lastMeasuredRowIndex.current; }, []); const setLastMeasuredRowIndex = React.useCallback(index => { if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) { lastMeasuredRowIndex.current = index; } }, []); const resetRowHeights = React.useCallback(() => { rowsHeightLookup.current = {}; hydrateRowsMeta(); }, [hydrateRowsMeta]); // The effect is used to build the rows meta data - currentPageTotalHeight and positions. // Because of variable row height this is needed for the virtualization React.useEffect(() => { hydrateRowsMeta(); }, [rowHeightFromDensity, filterState, paginationState, sortingState, hydrateRowsMeta]); (0, _pipeProcessing.useGridRegisterPipeApplier)(apiRef, 'rowHeight', hydrateRowsMeta); const rowsMetaApi = { unstable_getLastMeasuredRowIndex: getLastMeasuredRowIndex, unstable_setLastMeasuredRowIndex: setLastMeasuredRowIndex, unstable_rowHasAutoHeight: rowHasAutoHeight, unstable_getRowHeight: getRowHeight, unstable_getRowInternalSizes: getRowInternalSizes, unstable_setRowHeight: setRowHeight, unstable_storeRowHeightMeasurement: storeMeasuredRowHeight, resetRowHeights }; (0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaApi, 'GridRowsMetaApi'); }; exports.useGridRowsMeta = useGridRowsMeta;