@mui/x-data-grid
Version:
The Community plan edition of the Data Grid components (MUI X).
237 lines (232 loc) • 10.3 kB
JavaScript
"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;