UNPKG

@mui/x-data-grid

Version:

The Community plan edition of the Data Grid components (MUI X).

237 lines (232 loc) 10.3 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; 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 _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef")); var _utils = require("@mui/utils"); var _ResizeObserver = require("../../../utils/ResizeObserver"); var _useGridVisibleRows = require("../../utils/useGridVisibleRows"); var _utils2 = require("../../../utils/utils"); var _useGridApiMethod = require("../../utils/useGridApiMethod"); var _useGridSelector = require("../../utils/useGridSelector"); var _densitySelector = require("../density/densitySelector"); var _gridPaginationSelector = require("../pagination/gridPaginationSelector"); var _pipeProcessing = require("../../core/pipeProcessing"); var _gridRowsSelector = require("./gridRowsSelector"); var _gridDimensionsSelectors = require("../dimensions/gridDimensionsSelectors"); var _gridRowsUtils = require("./gridRowsUtils"); var _gridFocusedVirtualCellSelector = require("../virtualization/gridFocusedVirtualCellSelector"); /* eslint-disable no-underscore-dangle */ const rowsMetaStateInitializer = (state, props, apiRef) => { apiRef.current.caches.rowsMeta = { heights: new Map() }; const baseRowHeight = (0, _gridDimensionsSelectors.gridRowHeightSelector)(apiRef.current.state); const dataRowCount = (0, _gridRowsSelector.gridRowCountSelector)(apiRef); const pagination = (0, _gridPaginationSelector.gridPaginationSelector)(apiRef.current.state); const rowCount = Math.min(pagination.enabled ? pagination.paginationModel.pageSize : dataRowCount, dataRowCount); return (0, _extends2.default)({}, state, { rowsMeta: { currentPageTotalHeight: rowCount * baseRowHeight, positions: Array.from({ length: rowCount }, (_, i) => i * baseRowHeight), pinnedTopRowsTotalHeight: 0, pinnedBottomRowsTotalHeight: 0 } }); }; /** * @requires useGridPageSize (method) * @requires useGridPage (method) */ exports.rowsMetaStateInitializer = rowsMetaStateInitializer; const useGridRowsMeta = (apiRef, props) => { const { getRowHeight: getRowHeightProp, getRowSpacing, getEstimatedRowHeight } = props; const heightCache = apiRef.current.caches.rowsMeta.heights; const lastMeasuredRowIndex = React.useRef(-1); const hasRowWithAutoHeight = React.useRef(false); const isHeightMetaValid = React.useRef(false); const densityFactor = (0, _useGridSelector.useGridSelector)(apiRef, _densitySelector.gridDensityFactorSelector); const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props); const pinnedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridPinnedRowsSelector); const rowHeight = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridRowHeightSelector); const getRowHeightEntry = rowId => { let entry = heightCache.get(rowId); if (entry === undefined) { entry = { content: rowHeight, spacingTop: 0, spacingBottom: 0, detail: 0, autoHeight: false, needsFirstMeasurement: true }; heightCache.set(rowId, entry); } return entry; }; const processHeightEntry = React.useCallback(row => { // HACK: rowHeight trails behind the most up-to-date value just enough to // mess the initial rowsMeta hydration :/ const baseRowHeight = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef.current.state).rowHeight; (0, _utils2.eslintUseValue)(rowHeight); const entry = apiRef.current.getRowHeightEntry(row.id); if (!getRowHeightProp) { entry.content = baseRowHeight; entry.needsFirstMeasurement = false; } else { const rowHeightFromUser = getRowHeightProp((0, _extends2.default)({}, row, { densityFactor })); if (rowHeightFromUser === 'auto') { if (entry.needsFirstMeasurement) { const estimatedRowHeight = getEstimatedRowHeight ? getEstimatedRowHeight((0, _extends2.default)({}, row, { densityFactor })) : baseRowHeight; // If the row was not measured yet use the estimated row height entry.content = estimatedRowHeight ?? baseRowHeight; } hasRowWithAutoHeight.current = true; entry.autoHeight = true; } else { // Default back to base rowHeight if getRowHeight returns invalid value. entry.content = (0, _gridRowsUtils.getValidRowHeight)(rowHeightFromUser, baseRowHeight, _gridRowsUtils.getRowHeightWarning); entry.needsFirstMeasurement = false; entry.autoHeight = false; } } if (getRowSpacing) { const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id); const spacing = getRowSpacing((0, _extends2.default)({}, row, { isFirstVisible: indexRelativeToCurrentPage === 0, isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1, indexRelativeToCurrentPage })); entry.spacingTop = spacing.top ?? 0; entry.spacingBottom = spacing.bottom ?? 0; } else { entry.spacingTop = 0; entry.spacingBottom = 0; } apiRef.current.unstable_applyPipeProcessors('rowHeight', entry, row); return entry; }, [apiRef, currentPage.rows, getRowHeightProp, getEstimatedRowHeight, rowHeight, getRowSpacing, densityFactor]); const hydrateRowsMeta = React.useCallback(() => { hasRowWithAutoHeight.current = false; const pinnedTopRowsTotalHeight = pinnedRows.top.reduce((acc, row) => { const entry = processHeightEntry(row); return acc + entry.content + entry.spacingTop + entry.spacingBottom + entry.detail; }, 0); const pinnedBottomRowsTotalHeight = pinnedRows.bottom.reduce((acc, row) => { const entry = processHeightEntry(row); return acc + entry.content + entry.spacingTop + entry.spacingBottom + entry.detail; }, 0); const positions = []; const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => { positions.push(acc); const entry = processHeightEntry(row); const total = entry.content + entry.spacingTop + entry.spacingBottom + entry.detail; return acc + total; }, 0); if (!hasRowWithAutoHeight.current) { // No row has height=auto, so all rows are already measured lastMeasuredRowIndex.current = Infinity; } const didHeightsChange = pinnedTopRowsTotalHeight !== apiRef.current.state.rowsMeta.pinnedTopRowsTotalHeight || pinnedBottomRowsTotalHeight !== apiRef.current.state.rowsMeta.pinnedBottomRowsTotalHeight || currentPageTotalHeight !== apiRef.current.state.rowsMeta.currentPageTotalHeight; const rowsMeta = { currentPageTotalHeight, positions, pinnedTopRowsTotalHeight, pinnedBottomRowsTotalHeight }; apiRef.current.setState(state => { return (0, _extends2.default)({}, state, { rowsMeta }); }); if (didHeightsChange) { apiRef.current.updateDimensions(); } isHeightMetaValid.current = true; }, [apiRef, pinnedRows, currentPage.rows, processHeightEntry]); const getRowHeight = rowId => { return heightCache.get(rowId)?.content ?? rowHeight; }; const storeRowHeightMeasurement = (id, height) => { const entry = apiRef.current.getRowHeightEntry(id); const didChange = entry.content !== height; entry.needsFirstMeasurement = false; entry.content = height; isHeightMetaValid.current && (isHeightMetaValid.current = !didChange); }; const rowHasAutoHeight = id => { return heightCache.get(id)?.autoHeight ?? false; }; const getLastMeasuredRowIndex = () => { return lastMeasuredRowIndex.current; }; const setLastMeasuredRowIndex = index => { if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) { lastMeasuredRowIndex.current = index; } }; const resetRowHeights = () => { heightCache.clear(); hydrateRowsMeta(); }; const resizeObserver = (0, _useLazyRef.default)(() => new _ResizeObserver.ResizeObserver(entries => { for (let i = 0; i < entries.length; i += 1) { const entry = entries[i]; const height = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height; const rowId = entry.target.__mui_id; const focusedVirtualRowId = (0, _gridFocusedVirtualCellSelector.gridFocusedVirtualCellSelector)(apiRef)?.id; if (focusedVirtualRowId === rowId && height === 0) { // Focused virtual row has 0 height. // We don't want to store it to avoid scroll jumping. // https://github.com/mui/mui-x/issues/14726 return; } apiRef.current.unstable_storeRowHeightMeasurement(rowId, height); } if (!isHeightMetaValid.current) { apiRef.current.requestPipeProcessorsApplication('rowHeight'); } })).current; const observeRowHeight = (element, rowId) => { element.__mui_id = rowId; resizeObserver.observe(element); return () => resizeObserver.unobserve(element); }; (0, _pipeProcessing.useGridRegisterPipeApplier)(apiRef, 'rowHeight', 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 (0, _utils.unstable_useEnhancedEffect)(() => { hydrateRowsMeta(); }, [hydrateRowsMeta]); const rowsMetaApi = { unstable_getRowHeight: getRowHeight, unstable_setLastMeasuredRowIndex: setLastMeasuredRowIndex, unstable_storeRowHeightMeasurement: storeRowHeightMeasurement, resetRowHeights }; const rowsMetaPrivateApi = { hydrateRowsMeta, observeRowHeight, rowHasAutoHeight, getRowHeightEntry, getLastMeasuredRowIndex }; (0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaApi, 'public'); (0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaPrivateApi, 'private'); }; exports.useGridRowsMeta = useGridRowsMeta;