UNPKG

@mui/x-data-grid-premium

Version:

The Premium plan edition of the MUI X Data Grid Components.

220 lines (212 loc) 10.1 kB
"use strict"; 'use client'; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridAggregation = exports.aggregationStateInitializer = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var React = _interopRequireWildcard(require("react")); var _isObjectEmpty = require("@mui/x-internals/isObjectEmpty"); var _xDataGridPro = require("@mui/x-data-grid-pro"); var _internals = require("@mui/x-data-grid-pro/internals"); var _gridAggregationSelectors = require("./gridAggregationSelectors"); var _gridAggregationUtils = require("./gridAggregationUtils"); var _createAggregationLookup = require("./createAggregationLookup"); const aggregationStateInitializer = (state, props, apiRef) => { apiRef.current.caches.aggregation = { rulesOnLastColumnHydration: {}, rulesOnLastRowHydration: {} }; return (0, _extends2.default)({}, state, { aggregation: { model: props.aggregationModel ?? props.initialState?.aggregation?.model ?? {} } }); }; exports.aggregationStateInitializer = aggregationStateInitializer; const useGridAggregation = (apiRef, props) => { apiRef.current.registerControlState({ stateId: 'aggregation', propModel: props.aggregationModel, propOnChange: props.onAggregationModelChange, stateSelector: _gridAggregationSelectors.gridAggregationModelSelector, changeEvent: 'aggregationModelChange' }); /** * API METHODS */ const setAggregationModel = React.useCallback(model => { const currentModel = (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef); if (currentModel !== model) { apiRef.current.setState((0, _gridAggregationUtils.mergeStateWithAggregationModel)(model)); } }, [apiRef]); const abortControllerRef = React.useRef(null); const applyAggregation = React.useCallback(() => { // Abort previous if we're proceeding if (abortControllerRef.current) { abortControllerRef.current.abort(); } const abortController = new AbortController(); abortControllerRef.current = abortController; const aggregationRules = (0, _gridAggregationUtils.getAggregationRules)((0, _xDataGridPro.gridColumnLookupSelector)(apiRef), (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef), props.aggregationFunctions, !!props.dataSource); const aggregatedFields = Object.keys(aggregationRules); const currentAggregationLookup = (0, _gridAggregationSelectors.gridAggregationLookupSelector)(apiRef); const renderContext = (0, _xDataGridPro.gridRenderContextSelector)(apiRef); const visibleColumns = (0, _xDataGridPro.gridVisibleColumnFieldsSelector)(apiRef); const chunks = []; const sortedAggregatedFields = (0, _xDataGridPro.gridSortModelSelector)(apiRef).map(s => s.field).filter(field => aggregatedFields.includes(field)); const visibleAggregatedFields = visibleColumns.slice(renderContext.firstColumnIndex, renderContext.lastColumnIndex + 1).filter(field => aggregatedFields.includes(field)); const visibleAggregatedFieldsWithSort = [...visibleAggregatedFields, ...sortedAggregatedFields.filter(field => !visibleAggregatedFields.includes(field))]; const hasAggregatedSortedField = (0, _xDataGridPro.gridRowMaximumTreeDepthSelector)(apiRef) > 1 && sortedAggregatedFields.length > 0; if (visibleAggregatedFieldsWithSort.length > 0) { chunks.push(visibleAggregatedFieldsWithSort); } const otherAggregatedFields = aggregatedFields.filter(field => !visibleAggregatedFieldsWithSort.includes(field)); const chunkSize = 20; // columns per chunk for (let i = 0; i < otherAggregatedFields.length; i += chunkSize) { chunks.push(otherAggregatedFields.slice(i, i + chunkSize)); } let chunkIndex = 0; const aggregationLookup = {}; let chunkStartTime = performance.now(); const timeLimit = 1000 / 120; const processChunk = () => { if (abortController.signal.aborted) { return; } const currentChunk = chunks[chunkIndex]; if (!currentChunk) { apiRef.current.publishEvent('aggregationLookupSet'); abortControllerRef.current = null; return; } const applySorting = (0, _createAggregationLookup.shouldApplySorting)(aggregationRules, currentChunk); // createAggregationLookup now RETURNS new partial lookup const partialLookup = (0, _createAggregationLookup.createAggregationLookup)({ apiRef, getAggregationPosition: props.getAggregationPosition, aggregatedFields: currentChunk, aggregationRules, aggregationRowsScope: props.aggregationRowsScope, isDataSource: !!props.dataSource, applySorting }); for (const key of Object.keys(partialLookup)) { for (const field of Object.keys(partialLookup[key])) { aggregationLookup[key] ?? (aggregationLookup[key] = {}); aggregationLookup[key][field] = partialLookup[key][field]; } } apiRef.current.setState(state => (0, _extends2.default)({}, state, { aggregation: (0, _extends2.default)({}, state.aggregation, { lookup: (0, _extends2.default)({}, aggregationLookup) }) })); if (chunkIndex === 0 && hasAggregatedSortedField) { apiRef.current.applySorting(); } chunkIndex += 1; if (performance.now() - chunkStartTime < timeLimit) { processChunk(); return; } setTimeout(() => { chunkStartTime = performance.now(); processChunk(); }, 0); }; processChunk(); // processChunk() does nothing if there are no aggregated fields // make sure that the lookup is empty in this case if (aggregatedFields.length === 0 && !(0, _isObjectEmpty.isObjectEmpty)(currentAggregationLookup)) { apiRef.current.setState(state => (0, _extends2.default)({}, state, { aggregation: (0, _extends2.default)({}, state.aggregation, { lookup: {} }) })); } }, [apiRef, props.getAggregationPosition, props.aggregationFunctions, props.aggregationRowsScope, props.dataSource]); React.useEffect(() => { return () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); abortControllerRef.current = null; } }; }, []); const { schedule: deferredApplyAggregation } = (0, _xDataGridPro.useRunOncePerLoop)(applyAggregation); const aggregationApi = { setAggregationModel }; const aggregationPrivateApi = { applyAggregation }; (0, _xDataGridPro.useGridApiMethod)(apiRef, aggregationApi, 'public'); (0, _xDataGridPro.useGridApiMethod)(apiRef, aggregationPrivateApi, 'private'); const addGetRowsParams = React.useCallback(params => { return (0, _extends2.default)({}, params, { aggregationModel: (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef) }); }, [apiRef]); (0, _internals.useGridRegisterPipeProcessor)(apiRef, 'getRowsParams', addGetRowsParams); /** * EVENTS */ const checkAggregationRulesDiff = React.useCallback(() => { const pivotingActive = (0, _internals.gridPivotActiveSelector)(apiRef); const { rulesOnLastRowHydration, rulesOnLastColumnHydration } = apiRef.current.caches.aggregation; const aggregationRules = props.disableAggregation ? {} : (0, _gridAggregationUtils.getAggregationRules)((0, _xDataGridPro.gridColumnLookupSelector)(apiRef), (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef), props.aggregationFunctions, !!props.dataSource); // Re-apply the row hydration to add / remove the aggregation footers if ((!props.dataSource || pivotingActive) && !(0, _gridAggregationUtils.areAggregationRulesEqual)(rulesOnLastRowHydration, aggregationRules)) { apiRef.current.requestPipeProcessorsApplication('hydrateRows'); deferredApplyAggregation(); } // Re-apply the column hydration to wrap / unwrap the aggregated columns if (!(0, _gridAggregationUtils.areAggregationRulesEqual)(rulesOnLastColumnHydration, aggregationRules)) { apiRef.current.requestPipeProcessorsApplication('hydrateColumns'); } }, [apiRef, deferredApplyAggregation, props.aggregationFunctions, props.disableAggregation, props.dataSource]); (0, _xDataGridPro.useGridEvent)(apiRef, 'aggregationModelChange', checkAggregationRulesDiff); (0, _xDataGridPro.useGridEvent)(apiRef, 'columnsChange', checkAggregationRulesDiff); (0, _xDataGridPro.useGridEvent)(apiRef, 'filteredRowsSet', deferredApplyAggregation); const lastSortModel = React.useRef((0, _xDataGridPro.gridSortModelSelector)(apiRef)); (0, _xDataGridPro.useGridEvent)(apiRef, 'sortedRowsSet', () => { const sortModel = (0, _xDataGridPro.gridSortModelSelector)(apiRef); if (lastSortModel.current === sortModel) { return; } lastSortModel.current = sortModel; const aggregationRules = (0, _gridAggregationUtils.getAggregationRules)((0, _xDataGridPro.gridColumnLookupSelector)(apiRef), (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef), props.aggregationFunctions, !!props.dataSource); const aggregatedFields = Object.keys(aggregationRules); if (!aggregatedFields.length) { return; } const needsSorting = (0, _createAggregationLookup.shouldApplySorting)(aggregationRules, aggregatedFields); if (!needsSorting) { return; } deferredApplyAggregation(); }); /** * EFFECTS */ React.useEffect(() => { if (props.aggregationModel !== undefined) { apiRef.current.setAggregationModel(props.aggregationModel); } }, [apiRef, props.aggregationModel]); React.useEffect(() => { if (props.getAggregationPosition !== undefined) { deferredApplyAggregation(); } }, [deferredApplyAggregation, props.getAggregationPosition]); }; exports.useGridAggregation = useGridAggregation;