@mui/x-data-grid-premium 5.13.0 → 5.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/CHANGELOG.md +156 -6
  2. package/DataGridPremium/DataGridPremium.js +56 -0
  3. package/DataGridPremium/useDataGridPremiumComponent.js +10 -2
  4. package/DataGridPremium/useDataGridPremiumProps.js +17 -7
  5. package/components/GridAggregationColumnMenuItem.d.ts +9 -0
  6. package/components/GridAggregationColumnMenuItem.js +93 -0
  7. package/components/GridAggregationHeader.d.ts +4 -0
  8. package/components/GridAggregationHeader.js +94 -0
  9. package/components/GridExcelExportMenuItem.js +11 -4
  10. package/components/GridFooterCell.d.ts +9 -0
  11. package/components/GridFooterCell.js +51 -0
  12. package/components/GridGroupingColumnFooterCell.d.ts +4 -0
  13. package/components/GridGroupingColumnFooterCell.js +29 -0
  14. package/hooks/features/aggregation/createAggregationLookup.d.ts +10 -0
  15. package/hooks/features/aggregation/createAggregationLookup.js +128 -0
  16. package/hooks/features/aggregation/gridAggregationFunctions.d.ts +8 -0
  17. package/hooks/features/aggregation/gridAggregationFunctions.js +96 -0
  18. package/hooks/features/aggregation/gridAggregationInterfaces.d.ts +103 -0
  19. package/hooks/features/aggregation/gridAggregationInterfaces.js +1 -0
  20. package/hooks/features/aggregation/gridAggregationSelectors.d.ts +4 -0
  21. package/hooks/features/aggregation/gridAggregationSelectors.js +4 -0
  22. package/hooks/features/aggregation/gridAggregationUtils.d.ts +41 -0
  23. package/hooks/features/aggregation/gridAggregationUtils.js +188 -0
  24. package/hooks/features/aggregation/index.d.ts +4 -0
  25. package/hooks/features/aggregation/index.js +4 -0
  26. package/hooks/features/aggregation/useGridAggregation.d.ts +6 -0
  27. package/hooks/features/aggregation/useGridAggregation.js +94 -0
  28. package/hooks/features/aggregation/useGridAggregationPreProcessors.d.ts +4 -0
  29. package/hooks/features/aggregation/useGridAggregationPreProcessors.js +138 -0
  30. package/hooks/features/aggregation/wrapColumnWithAggregation.d.ts +29 -0
  31. package/hooks/features/aggregation/wrapColumnWithAggregation.js +257 -0
  32. package/hooks/features/export/serializer/excelSerializer.js +2 -1
  33. package/hooks/features/index.d.ts +1 -0
  34. package/hooks/features/index.js +1 -0
  35. package/hooks/features/rowGrouping/createGroupingColDef.js +13 -2
  36. package/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
  37. package/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
  38. package/hooks/features/rowGrouping/useGridRowGrouping.js +20 -10
  39. package/index.js +1 -1
  40. package/legacy/DataGridPremium/DataGridPremium.js +56 -0
  41. package/legacy/DataGridPremium/useDataGridPremiumComponent.js +10 -2
  42. package/legacy/DataGridPremium/useDataGridPremiumProps.js +12 -2
  43. package/legacy/components/GridAggregationColumnMenuItem.js +95 -0
  44. package/legacy/components/GridAggregationHeader.js +95 -0
  45. package/legacy/components/GridExcelExportMenuItem.js +11 -4
  46. package/legacy/components/GridFooterCell.js +63 -0
  47. package/legacy/components/GridGroupingColumnFooterCell.js +27 -0
  48. package/legacy/hooks/features/aggregation/createAggregationLookup.js +127 -0
  49. package/legacy/hooks/features/aggregation/gridAggregationFunctions.js +94 -0
  50. package/legacy/hooks/features/aggregation/gridAggregationInterfaces.js +1 -0
  51. package/legacy/hooks/features/aggregation/gridAggregationSelectors.js +10 -0
  52. package/legacy/hooks/features/aggregation/gridAggregationUtils.js +200 -0
  53. package/legacy/hooks/features/aggregation/index.js +4 -0
  54. package/legacy/hooks/features/aggregation/useGridAggregation.js +95 -0
  55. package/legacy/hooks/features/aggregation/useGridAggregationPreProcessors.js +141 -0
  56. package/legacy/hooks/features/aggregation/wrapColumnWithAggregation.js +262 -0
  57. package/legacy/hooks/features/export/serializer/excelSerializer.js +2 -1
  58. package/legacy/hooks/features/index.js +1 -0
  59. package/legacy/hooks/features/rowGrouping/createGroupingColDef.js +13 -2
  60. package/legacy/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
  61. package/legacy/hooks/features/rowGrouping/useGridRowGrouping.js +24 -10
  62. package/legacy/index.js +1 -1
  63. package/legacy/typeOverloads/index.js +1 -1
  64. package/legacy/utils/releaseInfo.js +1 -1
  65. package/models/dataGridPremiumProps.d.ts +40 -1
  66. package/models/gridApiPremium.d.ts +3 -3
  67. package/models/gridStatePremium.d.ts +3 -1
  68. package/modern/DataGridPremium/DataGridPremium.js +56 -0
  69. package/modern/DataGridPremium/useDataGridPremiumComponent.js +10 -2
  70. package/modern/DataGridPremium/useDataGridPremiumProps.js +8 -2
  71. package/modern/components/GridAggregationColumnMenuItem.js +93 -0
  72. package/modern/components/GridAggregationHeader.js +92 -0
  73. package/modern/components/GridExcelExportMenuItem.js +11 -4
  74. package/modern/components/GridFooterCell.js +51 -0
  75. package/modern/components/GridGroupingColumnFooterCell.js +29 -0
  76. package/modern/hooks/features/aggregation/createAggregationLookup.js +122 -0
  77. package/modern/hooks/features/aggregation/gridAggregationFunctions.js +96 -0
  78. package/modern/hooks/features/aggregation/gridAggregationInterfaces.js +1 -0
  79. package/modern/hooks/features/aggregation/gridAggregationSelectors.js +4 -0
  80. package/modern/hooks/features/aggregation/gridAggregationUtils.js +186 -0
  81. package/modern/hooks/features/aggregation/index.js +4 -0
  82. package/modern/hooks/features/aggregation/useGridAggregation.js +92 -0
  83. package/modern/hooks/features/aggregation/useGridAggregationPreProcessors.js +136 -0
  84. package/modern/hooks/features/aggregation/wrapColumnWithAggregation.js +251 -0
  85. package/modern/hooks/features/export/serializer/excelSerializer.js +2 -1
  86. package/modern/hooks/features/index.js +1 -0
  87. package/modern/hooks/features/rowGrouping/createGroupingColDef.js +13 -2
  88. package/modern/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
  89. package/modern/hooks/features/rowGrouping/useGridRowGrouping.js +17 -11
  90. package/modern/index.js +1 -1
  91. package/modern/typeOverloads/index.js +1 -1
  92. package/modern/utils/releaseInfo.js +1 -1
  93. package/node/DataGridPremium/DataGridPremium.js +56 -0
  94. package/node/DataGridPremium/useDataGridPremiumComponent.js +11 -1
  95. package/node/DataGridPremium/useDataGridPremiumProps.js +17 -6
  96. package/node/components/GridAggregationColumnMenuItem.js +120 -0
  97. package/node/components/GridAggregationHeader.js +115 -0
  98. package/node/components/GridExcelExportMenuItem.js +12 -4
  99. package/node/components/GridFooterCell.js +73 -0
  100. package/node/components/GridGroupingColumnFooterCell.js +46 -0
  101. package/node/hooks/features/aggregation/createAggregationLookup.js +139 -0
  102. package/node/hooks/features/aggregation/gridAggregationFunctions.js +105 -0
  103. package/node/hooks/features/aggregation/gridAggregationInterfaces.js +5 -0
  104. package/node/hooks/features/aggregation/gridAggregationSelectors.js +16 -0
  105. package/node/hooks/features/aggregation/gridAggregationUtils.js +223 -0
  106. package/node/hooks/features/aggregation/index.js +65 -0
  107. package/node/hooks/features/aggregation/useGridAggregation.js +118 -0
  108. package/node/hooks/features/aggregation/useGridAggregationPreProcessors.js +162 -0
  109. package/node/hooks/features/aggregation/wrapColumnWithAggregation.js +279 -0
  110. package/node/hooks/features/export/serializer/excelSerializer.js +2 -1
  111. package/node/hooks/features/index.js +13 -0
  112. package/node/hooks/features/rowGrouping/createGroupingColDef.js +14 -2
  113. package/node/hooks/features/rowGrouping/gridRowGroupingUtils.js +5 -1
  114. package/node/hooks/features/rowGrouping/useGridRowGrouping.js +19 -10
  115. package/node/index.js +1 -1
  116. package/node/typeOverloads/index.js +16 -1
  117. package/node/utils/releaseInfo.js +1 -1
  118. package/package.json +5 -5
  119. package/typeOverloads/index.d.ts +1 -1
  120. package/typeOverloads/index.js +1 -1
  121. package/typeOverloads/modules.d.ts +32 -2
  122. package/utils/releaseInfo.js +1 -1
@@ -0,0 +1,186 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import { capitalize } from '@mui/material';
3
+ import { addPinnedRow, isDeepEqual } from '@mui/x-data-grid-pro/internals';
4
+ export const GRID_AGGREGATION_ROOT_FOOTER_ROW_ID = 'auto-generated-group-footer-root';
5
+ export const getAggregationFooterRowIdFromGroupId = groupId => {
6
+ if (groupId == null) {
7
+ return GRID_AGGREGATION_ROOT_FOOTER_ROW_ID;
8
+ }
9
+
10
+ return `auto-generated-group-footer-${groupId}`;
11
+ };
12
+ export const canColumnHaveAggregationFunction = ({
13
+ column,
14
+ aggregationFunctionName,
15
+ aggregationFunction
16
+ }) => {
17
+ if (!column || !column.aggregable) {
18
+ return false;
19
+ }
20
+
21
+ if (!aggregationFunction) {
22
+ return false;
23
+ }
24
+
25
+ if (column.availableAggregationFunctions != null) {
26
+ return column.availableAggregationFunctions.includes(aggregationFunctionName);
27
+ }
28
+
29
+ if (!aggregationFunction.columnTypes) {
30
+ return true;
31
+ }
32
+
33
+ return aggregationFunction.columnTypes.includes(column.type);
34
+ };
35
+ export const getAvailableAggregationFunctions = ({
36
+ aggregationFunctions,
37
+ column
38
+ }) => Object.keys(aggregationFunctions).filter(aggregationFunctionName => canColumnHaveAggregationFunction({
39
+ column,
40
+ aggregationFunctionName,
41
+ aggregationFunction: aggregationFunctions[aggregationFunctionName]
42
+ }));
43
+ export const mergeStateWithAggregationModel = aggregationModel => state => _extends({}, state, {
44
+ aggregation: _extends({}, state.aggregation, {
45
+ model: aggregationModel
46
+ })
47
+ });
48
+ export const getAggregationRules = ({
49
+ columnsLookup,
50
+ aggregationModel,
51
+ aggregationFunctions
52
+ }) => {
53
+ const aggregationRules = {};
54
+ Object.entries(aggregationModel).forEach(([field, columnItem]) => {
55
+ if (columnsLookup[field] && canColumnHaveAggregationFunction({
56
+ column: columnsLookup[field],
57
+ aggregationFunctionName: columnItem,
58
+ aggregationFunction: aggregationFunctions[columnItem]
59
+ })) {
60
+ aggregationRules[field] = {
61
+ aggregationFunctionName: columnItem,
62
+ aggregationFunction: aggregationFunctions[columnItem]
63
+ };
64
+ }
65
+ });
66
+ return aggregationRules;
67
+ };
68
+ /**
69
+ * Add a footer for each group that has at least one column with an aggregated value.
70
+ */
71
+
72
+ export const addFooterRows = ({
73
+ groupingParams,
74
+ aggregationRules,
75
+ getAggregationPosition,
76
+ apiRef
77
+ }) => {
78
+ if (Object.keys(aggregationRules).length === 0) {
79
+ return groupingParams;
80
+ }
81
+
82
+ const ids = [...groupingParams.ids];
83
+
84
+ const idRowsLookup = _extends({}, groupingParams.idRowsLookup);
85
+
86
+ const tree = _extends({}, groupingParams.tree);
87
+
88
+ const addGroupFooter = groupNode => {
89
+ const groupId = groupNode?.id ?? null;
90
+
91
+ if (getAggregationPosition(groupNode) !== 'footer') {
92
+ return;
93
+ }
94
+
95
+ const footerId = getAggregationFooterRowIdFromGroupId(groupId);
96
+ ids.push(footerId);
97
+ idRowsLookup[footerId] = {};
98
+ tree[footerId] = {
99
+ id: footerId,
100
+ isAutoGenerated: true,
101
+ parent: groupId,
102
+ depth: groupNode ? groupNode.depth + 1 : 0,
103
+ groupingKey: null,
104
+ groupingField: null,
105
+ position: 'footer'
106
+ };
107
+
108
+ if (groupId != null) {
109
+ tree[groupId] = _extends({}, tree[groupId], {
110
+ footerId
111
+ });
112
+ }
113
+ }; // If the tree is flat, we don't need to loop through the rows
114
+
115
+
116
+ if (groupingParams.treeDepth > 1) {
117
+ groupingParams.ids.forEach(parentId => {
118
+ const parentNode = tree[parentId];
119
+
120
+ if (parentNode.depth === groupingParams.treeDepth - 1) {
121
+ return;
122
+ }
123
+
124
+ addGroupFooter(parentNode);
125
+ });
126
+ }
127
+
128
+ let newGroupingParams = _extends({}, groupingParams, {
129
+ tree,
130
+ idRowsLookup,
131
+ ids
132
+ });
133
+
134
+ if (getAggregationPosition(null) === 'footer') {
135
+ newGroupingParams = addPinnedRow({
136
+ groupingParams: newGroupingParams,
137
+ rowModel: {},
138
+ rowId: getAggregationFooterRowIdFromGroupId(null),
139
+ position: 'bottom',
140
+ apiRef
141
+ });
142
+ }
143
+
144
+ return _extends({}, groupingParams, newGroupingParams);
145
+ };
146
+ /**
147
+ * Compares two sets of aggregation rules to determine if they are equal or not.
148
+ */
149
+
150
+ export const hasAggregationRulesChanged = (previousValue, newValue) => {
151
+ const previousFields = Object.keys(previousValue ?? {});
152
+ const newFields = Object.keys(newValue);
153
+
154
+ if (!isDeepEqual(previousFields, newFields)) {
155
+ return true;
156
+ }
157
+
158
+ return newFields.some(field => {
159
+ const previousRule = previousValue?.[field];
160
+ const newRule = newValue[field];
161
+
162
+ if (previousRule?.aggregationFunction !== newRule?.aggregationFunction) {
163
+ return true;
164
+ }
165
+
166
+ if (previousRule?.aggregationFunctionName !== newRule?.aggregationFunctionName) {
167
+ return true;
168
+ }
169
+
170
+ return false;
171
+ });
172
+ };
173
+ export const getAggregationFunctionLabel = ({
174
+ apiRef,
175
+ aggregationRule
176
+ }) => {
177
+ if (aggregationRule.aggregationFunction.label != null) {
178
+ return aggregationRule.aggregationFunction.label;
179
+ }
180
+
181
+ try {
182
+ return apiRef.current.getLocaleText(`aggregationFunctionLabel${capitalize(aggregationRule.aggregationFunctionName)}`);
183
+ } catch (e) {
184
+ return aggregationRule.aggregationFunctionName;
185
+ }
186
+ };
@@ -0,0 +1,4 @@
1
+ export * from './gridAggregationInterfaces';
2
+ export * from './gridAggregationSelectors';
3
+ export * from './gridAggregationFunctions';
4
+ export { GRID_AGGREGATION_ROOT_FOOTER_ROW_ID, getAggregationFooterRowIdFromGroupId } from './gridAggregationUtils';
@@ -0,0 +1,92 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import { gridColumnLookupSelector, useGridApiEventHandler, useGridApiMethod } from '@mui/x-data-grid-pro';
4
+ import { gridAggregationModelSelector } from './gridAggregationSelectors';
5
+ import { getAggregationRules, mergeStateWithAggregationModel, hasAggregationRulesChanged } from './gridAggregationUtils';
6
+ import { createAggregationLookup } from './createAggregationLookup';
7
+ export const aggregationStateInitializer = (state, props, apiRef) => {
8
+ apiRef.current.unstable_caches.aggregation = {
9
+ rulesOnLastColumnHydration: {},
10
+ rulesOnLastRowHydration: {}
11
+ };
12
+ return _extends({}, state, {
13
+ aggregation: {
14
+ model: props.aggregationModel ?? props.initialState?.aggregation?.model ?? {}
15
+ }
16
+ });
17
+ };
18
+ export const useGridAggregation = (apiRef, props) => {
19
+ apiRef.current.unstable_registerControlState({
20
+ stateId: 'aggregation',
21
+ propModel: props.aggregationModel,
22
+ propOnChange: props.onAggregationModelChange,
23
+ stateSelector: gridAggregationModelSelector,
24
+ changeEvent: 'aggregationModelChange'
25
+ });
26
+ /**
27
+ * API METHODS
28
+ */
29
+
30
+ const setAggregationModel = React.useCallback(model => {
31
+ const currentModel = gridAggregationModelSelector(apiRef);
32
+
33
+ if (currentModel !== model) {
34
+ apiRef.current.setState(mergeStateWithAggregationModel(model));
35
+ apiRef.current.forceUpdate();
36
+ }
37
+ }, [apiRef]);
38
+ const applyAggregation = React.useCallback(() => {
39
+ const aggregationLookup = createAggregationLookup({
40
+ apiRef,
41
+ getAggregationPosition: props.getAggregationPosition,
42
+ aggregationFunctions: props.aggregationFunctions,
43
+ aggregationRowsScope: props.aggregationRowsScope
44
+ });
45
+ apiRef.current.setState(state => _extends({}, state, {
46
+ aggregation: _extends({}, state.aggregation, {
47
+ lookup: aggregationLookup
48
+ })
49
+ }));
50
+ }, [apiRef, props.getAggregationPosition, props.aggregationFunctions, props.aggregationRowsScope]);
51
+ const aggregationApi = {
52
+ setAggregationModel
53
+ };
54
+ useGridApiMethod(apiRef, aggregationApi, 'GridAggregationApi');
55
+ /**
56
+ * EVENTS
57
+ */
58
+
59
+ const checkAggregationRulesDiff = React.useCallback(() => {
60
+ const {
61
+ rulesOnLastRowHydration,
62
+ rulesOnLastColumnHydration
63
+ } = apiRef.current.unstable_caches.aggregation;
64
+ const aggregationRules = props.disableAggregation ? {} : getAggregationRules({
65
+ columnsLookup: gridColumnLookupSelector(apiRef),
66
+ aggregationModel: gridAggregationModelSelector(apiRef),
67
+ aggregationFunctions: props.aggregationFunctions
68
+ }); // Re-apply the row hydration to add / remove the aggregation footers
69
+
70
+ if (hasAggregationRulesChanged(rulesOnLastRowHydration, aggregationRules)) {
71
+ apiRef.current.unstable_requestPipeProcessorsApplication('hydrateRows');
72
+ applyAggregation();
73
+ } // Re-apply the column hydration to wrap / unwrap the aggregated columns
74
+
75
+
76
+ if (hasAggregationRulesChanged(rulesOnLastColumnHydration, aggregationRules)) {
77
+ apiRef.current.unstable_requestPipeProcessorsApplication('hydrateColumns');
78
+ }
79
+ }, [apiRef, applyAggregation, props.aggregationFunctions, props.disableAggregation]);
80
+ useGridApiEventHandler(apiRef, 'aggregationModelChange', checkAggregationRulesDiff);
81
+ useGridApiEventHandler(apiRef, 'columnsChange', checkAggregationRulesDiff);
82
+ useGridApiEventHandler(apiRef, 'filteredRowsSet', applyAggregation);
83
+ /**
84
+ * EFFECTS
85
+ */
86
+
87
+ React.useEffect(() => {
88
+ if (props.aggregationModel !== undefined) {
89
+ apiRef.current.setAggregationModel(props.aggregationModel);
90
+ }
91
+ }, [apiRef, props.aggregationModel]);
92
+ };
@@ -0,0 +1,136 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import MuiDivider from '@mui/material/Divider';
4
+ import { gridColumnLookupSelector } from '@mui/x-data-grid-pro';
5
+ import { useGridRegisterPipeProcessor } from '@mui/x-data-grid-pro/internals';
6
+ import { getAvailableAggregationFunctions, addFooterRows, getAggregationRules, mergeStateWithAggregationModel } from './gridAggregationUtils';
7
+ import { wrapColumnWithAggregationValue, unwrapColumnFromAggregation } from './wrapColumnWithAggregation';
8
+ import { GridAggregationColumnMenuItem } from '../../../components/GridAggregationColumnMenuItem';
9
+ import { gridAggregationModelSelector } from './gridAggregationSelectors';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+
12
+ const Divider = () => /*#__PURE__*/_jsx(MuiDivider, {
13
+ onClick: event => event.stopPropagation()
14
+ });
15
+
16
+ export const useGridAggregationPreProcessors = (apiRef, props) => {
17
+ const updateAggregatedColumns = React.useCallback(columnsState => {
18
+ const {
19
+ rulesOnLastColumnHydration
20
+ } = apiRef.current.unstable_caches.aggregation;
21
+ const aggregationRules = props.disableAggregation ? {} : getAggregationRules({
22
+ columnsLookup: columnsState.lookup,
23
+ aggregationModel: gridAggregationModelSelector(apiRef),
24
+ aggregationFunctions: props.aggregationFunctions
25
+ });
26
+ columnsState.all.forEach(field => {
27
+ const shouldHaveAggregationValue = !!aggregationRules[field];
28
+ const haveAggregationColumnValue = !!rulesOnLastColumnHydration[field];
29
+ let column = columnsState.lookup[field];
30
+
31
+ if (haveAggregationColumnValue) {
32
+ column = unwrapColumnFromAggregation({
33
+ column
34
+ });
35
+ }
36
+
37
+ if (shouldHaveAggregationValue) {
38
+ column = wrapColumnWithAggregationValue({
39
+ column,
40
+ aggregationRule: aggregationRules[field],
41
+ apiRef
42
+ });
43
+ }
44
+
45
+ columnsState.lookup[field] = column;
46
+ });
47
+ apiRef.current.unstable_caches.aggregation.rulesOnLastColumnHydration = aggregationRules;
48
+ return columnsState;
49
+ }, [apiRef, props.aggregationFunctions, props.disableAggregation]);
50
+ const addGroupFooterRows = React.useCallback(groupingParams => {
51
+ let newGroupingParams;
52
+ let rulesOnLastRowHydration;
53
+
54
+ if (props.disableAggregation) {
55
+ newGroupingParams = groupingParams;
56
+ rulesOnLastRowHydration = {};
57
+ } else {
58
+ const aggregationRules = getAggregationRules({
59
+ columnsLookup: gridColumnLookupSelector(apiRef),
60
+ aggregationModel: gridAggregationModelSelector(apiRef),
61
+ aggregationFunctions: props.aggregationFunctions
62
+ });
63
+ rulesOnLastRowHydration = aggregationRules; // If no column have an aggregation rule
64
+ // Then don't create the footer rows
65
+
66
+ if (Object.values(aggregationRules).length === 0) {
67
+ newGroupingParams = groupingParams;
68
+ } else {
69
+ newGroupingParams = addFooterRows({
70
+ groupingParams,
71
+ aggregationRules,
72
+ getAggregationPosition: props.getAggregationPosition,
73
+ apiRef
74
+ });
75
+ }
76
+ }
77
+
78
+ apiRef.current.unstable_caches.aggregation.rulesOnLastRowHydration = rulesOnLastRowHydration;
79
+ return newGroupingParams;
80
+ }, [apiRef, props.disableAggregation, props.getAggregationPosition, props.aggregationFunctions]);
81
+ const addColumnMenuButtons = React.useCallback((initialValue, column) => {
82
+ if (props.disableAggregation) {
83
+ return initialValue;
84
+ }
85
+
86
+ const availableAggregationFunctions = getAvailableAggregationFunctions({
87
+ aggregationFunctions: props.aggregationFunctions,
88
+ column
89
+ });
90
+
91
+ if (availableAggregationFunctions.length === 0) {
92
+ return initialValue;
93
+ }
94
+
95
+ return [...initialValue, /*#__PURE__*/_jsx(Divider, {}), /*#__PURE__*/_jsx(GridAggregationColumnMenuItem, {
96
+ column: column,
97
+ label: apiRef.current.getLocaleText('aggregationMenuItemHeader'),
98
+ availableAggregationFunctions: availableAggregationFunctions
99
+ })];
100
+ }, [apiRef, props.aggregationFunctions, props.disableAggregation]);
101
+ const stateExportPreProcessing = React.useCallback(prevState => {
102
+ if (props.disableAggregation) {
103
+ return prevState;
104
+ }
105
+
106
+ const aggregationModelToExport = gridAggregationModelSelector(apiRef);
107
+
108
+ if (Object.values(aggregationModelToExport).length === 0) {
109
+ return prevState;
110
+ }
111
+
112
+ return _extends({}, prevState, {
113
+ aggregation: {
114
+ model: aggregationModelToExport
115
+ }
116
+ });
117
+ }, [apiRef, props.disableAggregation]);
118
+ const stateRestorePreProcessing = React.useCallback((params, context) => {
119
+ if (props.disableAggregation) {
120
+ return params;
121
+ }
122
+
123
+ const aggregationModel = context.stateToRestore.aggregation?.model;
124
+
125
+ if (aggregationModel != null) {
126
+ apiRef.current.setState(mergeStateWithAggregationModel(aggregationModel));
127
+ }
128
+
129
+ return params;
130
+ }, [apiRef, props.disableAggregation]);
131
+ useGridRegisterPipeProcessor(apiRef, 'hydrateColumns', updateAggregatedColumns);
132
+ useGridRegisterPipeProcessor(apiRef, 'hydrateRows', addGroupFooterRows);
133
+ useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuButtons);
134
+ useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
135
+ useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
136
+ };
@@ -0,0 +1,251 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import { gridAggregationLookupSelector } from './gridAggregationSelectors';
4
+ import { GridFooterCell } from '../../../components/GridFooterCell';
5
+ import { GridAggregationHeader } from '../../../components/GridAggregationHeader';
6
+ import { jsx as _jsx } from "react/jsx-runtime";
7
+ const AGGREGATION_WRAPPABLE_PROPERTIES = ['valueGetter', 'valueFormatter', 'renderCell', 'renderHeader', 'filterOperators'];
8
+
9
+ const getAggregationValueWrappedValueGetter = ({
10
+ value: valueGetter,
11
+ getCellAggregationResult
12
+ }) => {
13
+ const wrappedValueGetter = params => {
14
+ const cellAggregationResult = getCellAggregationResult(params.id, params.field);
15
+
16
+ if (cellAggregationResult != null) {
17
+ return cellAggregationResult?.value ?? null;
18
+ }
19
+
20
+ if (valueGetter) {
21
+ return valueGetter(params);
22
+ }
23
+
24
+ return params.row[params.field];
25
+ };
26
+
27
+ return wrappedValueGetter;
28
+ };
29
+
30
+ const getAggregationValueWrappedValueFormatter = ({
31
+ value: valueFormatter,
32
+ aggregationRule,
33
+ getCellAggregationResult
34
+ }) => {
35
+ // If neither the inline aggregation function nor the footer aggregation function have a custom value formatter,
36
+ // Then we don't wrap the column value formatter
37
+ if (!aggregationRule.aggregationFunction.valueFormatter) {
38
+ return valueFormatter;
39
+ }
40
+
41
+ const wrappedValueFormatter = params => {
42
+ if (params.id != null) {
43
+ const cellAggregationResult = getCellAggregationResult(params.id, params.field);
44
+
45
+ if (cellAggregationResult != null) {
46
+ return aggregationRule.aggregationFunction.valueFormatter(params);
47
+ }
48
+ }
49
+
50
+ if (valueFormatter) {
51
+ return valueFormatter(params);
52
+ }
53
+
54
+ return params.value;
55
+ };
56
+
57
+ return wrappedValueFormatter;
58
+ };
59
+
60
+ const getAggregationValueWrappedRenderCell = ({
61
+ value: renderCell,
62
+ aggregationRule,
63
+ getCellAggregationResult
64
+ }) => {
65
+ const wrappedRenderCell = params => {
66
+ const cellAggregationResult = getCellAggregationResult(params.id, params.field);
67
+
68
+ if (cellAggregationResult != null) {
69
+ if (!renderCell) {
70
+ if (cellAggregationResult.position === 'footer') {
71
+ return /*#__PURE__*/_jsx(GridFooterCell, _extends({}, params));
72
+ }
73
+
74
+ return params.formattedValue;
75
+ }
76
+
77
+ const aggregationMeta = {
78
+ hasCellUnit: aggregationRule.aggregationFunction.hasCellUnit ?? true,
79
+ aggregationFunctionName: aggregationRule.aggregationFunctionName
80
+ };
81
+ return renderCell(_extends({}, params, {
82
+ aggregation: aggregationMeta
83
+ }));
84
+ }
85
+
86
+ if (!renderCell) {
87
+ return params.formattedValue;
88
+ }
89
+
90
+ return renderCell(params);
91
+ };
92
+
93
+ return wrappedRenderCell;
94
+ };
95
+ /**
96
+ * Skips the filtering for aggregated rows
97
+ */
98
+
99
+
100
+ const getWrappedFilterOperators = ({
101
+ value: filterOperators,
102
+ getCellAggregationResult
103
+ }) => filterOperators.map(operator => {
104
+ return _extends({}, operator, {
105
+ getApplyFilterFn: (filterItem, column) => {
106
+ const originalFn = operator.getApplyFilterFn(filterItem, column);
107
+
108
+ if (!originalFn) {
109
+ return null;
110
+ }
111
+
112
+ return params => {
113
+ if (getCellAggregationResult(params.id, params.field) != null) {
114
+ return true;
115
+ }
116
+
117
+ return originalFn(params);
118
+ };
119
+ }
120
+ });
121
+ });
122
+ /**
123
+ * Add the aggregation method around the header name
124
+ */
125
+
126
+
127
+ const getWrappedRenderHeader = ({
128
+ value: renderHeader,
129
+ aggregationRule
130
+ }) => {
131
+ const wrappedRenderCell = params => {
132
+ const aggregationMeta = {
133
+ aggregationRule
134
+ };
135
+
136
+ if (!renderHeader) {
137
+ return /*#__PURE__*/_jsx(GridAggregationHeader, _extends({}, params, {
138
+ aggregation: aggregationMeta
139
+ }));
140
+ }
141
+
142
+ return renderHeader(_extends({}, params, {
143
+ aggregation: aggregationMeta
144
+ }));
145
+ };
146
+
147
+ return wrappedRenderCell;
148
+ };
149
+ /**
150
+ * Add a wrapper around each wrappable property of the column to customize the behavior of the aggregation cells.
151
+ */
152
+
153
+
154
+ export const wrapColumnWithAggregationValue = ({
155
+ column,
156
+ apiRef,
157
+ aggregationRule
158
+ }) => {
159
+ const getCellAggregationResult = (id, field) => {
160
+ let cellAggregationPosition = null;
161
+
162
+ if (id.toString().startsWith('auto-generated-row-')) {
163
+ cellAggregationPosition = 'inline';
164
+ } else if (id.toString().startsWith('auto-generated-group-footer-')) {
165
+ cellAggregationPosition = 'footer';
166
+ }
167
+
168
+ if (cellAggregationPosition == null) {
169
+ return null;
170
+ } // TODO: Add custom root id
171
+
172
+
173
+ const groupId = cellAggregationPosition === 'inline' ? id : apiRef.current.getRowNode(id).parent ?? '';
174
+ const aggregationResult = gridAggregationLookupSelector(apiRef)[groupId]?.[field];
175
+
176
+ if (!aggregationResult || aggregationResult.position !== cellAggregationPosition) {
177
+ return null;
178
+ }
179
+
180
+ return aggregationResult;
181
+ };
182
+
183
+ const aggregationWrappedProperties = {};
184
+
185
+ const wrappedColumn = _extends({}, column, {
186
+ aggregationWrappedProperties
187
+ });
188
+
189
+ const wrapColumnProperty = (property, wrapper) => {
190
+ const originalValue = column[property];
191
+ const wrappedProperty = wrapper({
192
+ apiRef,
193
+ value: originalValue,
194
+ colDef: column,
195
+ aggregationRule,
196
+ getCellAggregationResult
197
+ });
198
+
199
+ if (wrappedProperty !== originalValue) {
200
+ aggregationWrappedProperties[property] = {
201
+ original: originalValue,
202
+ wrapped: wrappedProperty
203
+ };
204
+ wrappedColumn[property] = wrappedProperty;
205
+ }
206
+ };
207
+
208
+ wrapColumnProperty('valueGetter', getAggregationValueWrappedValueGetter);
209
+ wrapColumnProperty('valueFormatter', getAggregationValueWrappedValueFormatter);
210
+ wrapColumnProperty('renderCell', getAggregationValueWrappedRenderCell);
211
+ wrapColumnProperty('renderHeader', getWrappedRenderHeader);
212
+ wrapColumnProperty('filterOperators', getWrappedFilterOperators);
213
+
214
+ if (Object.keys(aggregationWrappedProperties).length === 0) {
215
+ return column;
216
+ }
217
+
218
+ return wrappedColumn;
219
+ };
220
+ /**
221
+ * Remove the aggregation wrappers around the wrappable properties of the column.
222
+ */
223
+
224
+ export const unwrapColumnFromAggregation = ({
225
+ column
226
+ }) => {
227
+ if (!column.aggregationWrappedProperties) {
228
+ return column;
229
+ }
230
+
231
+ const originalProperties = Object.entries(column.aggregationWrappedProperties);
232
+
233
+ if (originalProperties.length === 0) {
234
+ return column;
235
+ }
236
+
237
+ const unwrappedColumn = _extends({}, column);
238
+
239
+ originalProperties.forEach(([propertyName, {
240
+ original,
241
+ wrapped
242
+ }]) => {
243
+ // The value changed since we wrapped it
244
+ if (wrapped !== column[propertyName]) {
245
+ return;
246
+ }
247
+
248
+ unwrappedColumn[propertyName] = original;
249
+ });
250
+ return unwrappedColumn;
251
+ };
@@ -46,7 +46,8 @@ const serializeRow = (id, columns, api, defaultValueOptionsFormulae) => {
46
46
  api.unstable_calculateColSpan({
47
47
  rowId: id,
48
48
  minFirstColumn: 0,
49
- maxLastColumn: columns.length - 1
49
+ maxLastColumn: columns.length,
50
+ columns
50
51
  });
51
52
  columns.forEach((column, colIndex) => {
52
53
  const colSpanInfo = api.unstable_getCellColSpanInfo(id, colIndex);
@@ -1,3 +1,4 @@
1
1
  // Only export the variable and types that should be publicly exposed and re-exported from `@mui/x-data-grid-premium`
2
+ export * from './aggregation';
2
3
  export * from './rowGrouping';
3
4
  export * from './export';