@mui/x-data-grid-premium 8.13.1 → 8.14.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 (52) hide show
  1. package/CHANGELOG.md +109 -1
  2. package/DataGridPremium/DataGridPremium.js +7 -5
  3. package/DataGridPremium/useDataGridPremiumProps.js +3 -2
  4. package/components/GridDataSourceGroupingCriteriaCell.js +8 -2
  5. package/components/GridPremiumToolbar.js +1 -2
  6. package/components/pivotPanel/GridPivotPanelField.js +4 -4
  7. package/esm/DataGridPremium/DataGridPremium.js +7 -5
  8. package/esm/DataGridPremium/useDataGridPremiumProps.js +3 -2
  9. package/esm/components/GridDataSourceGroupingCriteriaCell.js +9 -3
  10. package/esm/components/GridPremiumToolbar.js +1 -2
  11. package/esm/components/pivotPanel/GridPivotPanelField.js +4 -4
  12. package/esm/hooks/features/aggregation/useGridAggregation.js +3 -2
  13. package/esm/hooks/features/dataSource/models.d.ts +52 -1
  14. package/esm/hooks/features/dataSource/useGridDataSourcePremium.js +30 -5
  15. package/esm/hooks/features/dataSource/utils.d.ts +6 -0
  16. package/esm/hooks/features/dataSource/utils.js +140 -0
  17. package/esm/hooks/features/index.d.ts +2 -1
  18. package/esm/hooks/features/index.js +2 -1
  19. package/esm/hooks/features/pivoting/gridPivotingInterfaces.d.ts +23 -13
  20. package/esm/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -1
  21. package/esm/hooks/features/pivoting/index.d.ts +1 -0
  22. package/esm/hooks/features/pivoting/index.js +1 -0
  23. package/esm/hooks/features/pivoting/useGridPivoting.d.ts +1 -1
  24. package/esm/hooks/features/pivoting/useGridPivoting.js +83 -32
  25. package/esm/hooks/features/pivoting/utils.d.ts +7 -9
  26. package/esm/hooks/features/pivoting/utils.js +39 -24
  27. package/esm/hooks/features/rowGrouping/createGroupingColDef.js +1 -1
  28. package/esm/hooks/features/rowGrouping/useGridDataSourceRowGroupingPreProcessors.js +7 -3
  29. package/esm/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
  30. package/esm/index.js +1 -1
  31. package/esm/models/dataGridPremiumProps.d.ts +15 -14
  32. package/hooks/features/aggregation/useGridAggregation.js +2 -1
  33. package/hooks/features/dataSource/models.d.ts +52 -1
  34. package/hooks/features/dataSource/useGridDataSourcePremium.js +29 -4
  35. package/hooks/features/dataSource/utils.d.ts +6 -0
  36. package/hooks/features/dataSource/utils.js +148 -0
  37. package/hooks/features/index.d.ts +2 -1
  38. package/hooks/features/index.js +11 -0
  39. package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +23 -13
  40. package/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -1
  41. package/hooks/features/pivoting/index.d.ts +1 -0
  42. package/hooks/features/pivoting/index.js +12 -0
  43. package/hooks/features/pivoting/useGridPivoting.d.ts +1 -1
  44. package/hooks/features/pivoting/useGridPivoting.js +82 -31
  45. package/hooks/features/pivoting/utils.d.ts +7 -9
  46. package/hooks/features/pivoting/utils.js +42 -27
  47. package/hooks/features/rowGrouping/createGroupingColDef.js +1 -1
  48. package/hooks/features/rowGrouping/useGridDataSourceRowGroupingPreProcessors.js +6 -2
  49. package/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
  50. package/index.js +1 -1
  51. package/models/dataGridPremiumProps.d.ts +15 -14
  52. package/package.json +6 -7
@@ -0,0 +1,140 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import { gridStringOrNumberComparator } from '@mui/x-data-grid-pro';
3
+ export const getPropsOverrides = (pivotColumns, pivotingColDef, pivotModel, initialColumns, apiRef) => {
4
+ const visiblePivotColumns = pivotModel.columns.filter(column => !column.hidden);
5
+ const visiblePivotValues = pivotModel.values.filter(value => !value.hidden);
6
+ const columns = Array.from(initialColumns.values());
7
+
8
+ // Build column grouping model from pivot column paths
9
+ const columnGroupingModel = [];
10
+ const columnGroupingModelLookup = new Map();
11
+
12
+ // Build new columns lookup and ordered fields
13
+ const newColumns = {};
14
+
15
+ // Build aggregation model
16
+ const aggregationModel = {};
17
+
18
+ // Create unique combinations of all values from pivotColumns and pivotValues
19
+ const uniquePaths = [];
20
+ const processPath = (currentPath, remainingColumns, level) => {
21
+ if (level === visiblePivotColumns.length) {
22
+ uniquePaths.push([...currentPath]);
23
+ return;
24
+ }
25
+ remainingColumns.forEach(column => {
26
+ processPath([...currentPath, {
27
+ key: column.key,
28
+ field: visiblePivotColumns[level].field,
29
+ value: column.group
30
+ }], column.children || [], level + 1);
31
+ });
32
+ };
33
+ processPath([], pivotColumns, 0);
34
+
35
+ /**
36
+ * Column group headers are sorted by the leaf columns order in the column definition.
37
+ * Store the values of each column group path to be able to sort them by pivot column sort order.
38
+ * The values are stored by the column group level which allows easier sorting by going through the column group levels in reverse order.
39
+ * Store raw value to be able to determine if the value was formatted on the client using `getRowValue`.
40
+ * Values sent from the server as strings will not be sorted on the client.
41
+ */
42
+ const columnGroupPathValues = [];
43
+ uniquePaths.forEach(columnPath => {
44
+ const columnPathKeys = columnPath.map(path => path.key);
45
+ const columnPathValues = columnPath.map(path => path.value);
46
+ visiblePivotValues.forEach(pivotValue => {
47
+ // Find the original column definition for the last field
48
+ const originalColumn = initialColumns.get(pivotValue.field);
49
+ // get the overrides defined from the data source definition
50
+ const overrides = pivotingColDef(pivotValue.field, columnPathKeys);
51
+
52
+ // Create new column definition based on original column
53
+ const newColumnDef = _extends({}, originalColumn, overrides, {
54
+ aggregable: false,
55
+ groupable: false,
56
+ filterable: false,
57
+ hideable: false,
58
+ editable: false,
59
+ disableReorder: true
60
+ });
61
+ const pivotFieldName = newColumnDef.field;
62
+ newColumns[pivotFieldName] = newColumnDef;
63
+ aggregationModel[pivotFieldName] = pivotValue.aggFunc;
64
+
65
+ // Build column grouping model
66
+ const combinedPathValues = [...columnPathValues, pivotValue.field].map((path, index) => typeof path === 'string' ? path : apiRef.current.getRowValue(path, initialColumns.get(visiblePivotColumns[index].field)));
67
+ columnGroupPathValues.push({
68
+ field: pivotFieldName,
69
+ pathValues: combinedPathValues.slice(0, -1),
70
+ pathValuesRaw: columnPathValues
71
+ });
72
+
73
+ // Build the hierarchy for column groups
74
+ for (let i = 0; i < combinedPathValues.length - 1; i += 1) {
75
+ const currentField = visiblePivotColumns[i].field;
76
+ const groupPath = combinedPathValues.slice(0, i + 1);
77
+ const groupId = groupPath.join('-');
78
+ let headerName = columnPathValues[groupPath.length - 1];
79
+ if (typeof headerName !== 'string') {
80
+ headerName = apiRef.current.getRowFormattedValue(headerName, initialColumns.get(currentField));
81
+ }
82
+ if (typeof headerName === 'number') {
83
+ headerName = String(headerName);
84
+ }
85
+ if (typeof headerName !== 'string') {
86
+ throw new Error(`MUI X: Header name for a column group based on ${currentField} cannot be converted to a string.`);
87
+ }
88
+ if (!columnGroupingModelLookup.has(groupId)) {
89
+ const columnGroup = {
90
+ groupId,
91
+ headerName,
92
+ children: []
93
+ };
94
+ columnGroupingModelLookup.set(groupId, columnGroup);
95
+ if (i === 0) {
96
+ columnGroupingModel.push(columnGroup);
97
+ } else {
98
+ const parentGroupId = groupPath.slice(0, -1).join('-');
99
+ const parentGroup = columnGroupingModelLookup.get(parentGroupId);
100
+ if (parentGroup) {
101
+ parentGroup.children.push(columnGroup);
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ // Add the final column to the appropriate group
108
+ const parentGroupId = combinedPathValues.slice(0, -1).join('-');
109
+ const parentGroup = columnGroupingModelLookup.get(parentGroupId);
110
+ if (parentGroup) {
111
+ parentGroup.children.push({
112
+ field: pivotFieldName
113
+ });
114
+ }
115
+ });
116
+ });
117
+ for (let i = visiblePivotColumns.length - 1; i >= 0; i -= 1) {
118
+ const sort = visiblePivotColumns[i].sort;
119
+ if (!sort) {
120
+ continue;
121
+ }
122
+ columnGroupPathValues.sort((a, b) => {
123
+ // Do not sort values that are returned as strings
124
+ if (typeof a.pathValuesRaw[i] === 'string' && typeof b.pathValuesRaw[i] === 'string') {
125
+ return 0;
126
+ }
127
+ return (sort === 'asc' ? 1 : -1) * gridStringOrNumberComparator(a.pathValues[i], b.pathValues[i], {}, {});
128
+ });
129
+ }
130
+ if (visiblePivotColumns.length > 0) {
131
+ for (let i = 0; i < columnGroupPathValues.length; i += 1) {
132
+ columns.push(newColumns[columnGroupPathValues[i].field]);
133
+ }
134
+ }
135
+ return {
136
+ columns,
137
+ columnGroupingModel,
138
+ aggregationModel
139
+ };
140
+ };
@@ -3,4 +3,5 @@ export * from "./rowGrouping/index.js";
3
3
  export * from "./export/index.js";
4
4
  export * from "./cellSelection/index.js";
5
5
  export * from "./aiAssistant/index.js";
6
- export * from "./sidebar/index.js";
6
+ export * from "./sidebar/index.js";
7
+ export * from "./pivoting/index.js";
@@ -4,4 +4,5 @@ export * from "./rowGrouping/index.js";
4
4
  export * from "./export/index.js";
5
5
  export * from "./cellSelection/index.js";
6
6
  export * from "./aiAssistant/index.js";
7
- export * from "./sidebar/index.js";
7
+ export * from "./sidebar/index.js";
8
+ export * from "./pivoting/index.js";
@@ -3,22 +3,25 @@ import type { GridPivotingPrivateApiCommunity, GridPivotingStatePartial } from '
3
3
  import type { RefObject } from '@mui/x-internals/types';
4
4
  import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
5
5
  import type { GridInitialStatePremium } from "../../../models/gridStatePremium.js";
6
- export type GridPivotingPropsOverrides = {
7
- rows: DataGridPremiumProcessedProps['rows'];
6
+ export type GridPivotingStaticPropsOverrides = {
7
+ rowGroupingModel: DataGridPremiumProcessedProps['rowGroupingModel'];
8
+ getAggregationPosition: DataGridPremiumProcessedProps['getAggregationPosition'];
9
+ columnVisibilityModel: DataGridPremiumProcessedProps['columnVisibilityModel'];
10
+ groupingColDef: DataGridPremiumProcessedProps['groupingColDef'];
11
+ headerFilters: DataGridPremiumProcessedProps['headerFilters'];
12
+ disableAggregation: DataGridPremiumProcessedProps['disableAggregation'];
13
+ disableRowGrouping: DataGridPremiumProcessedProps['disableRowGrouping'];
14
+ };
15
+ export type GridPivotingDynamicPropsOverrides = {
16
+ rows?: DataGridPremiumProcessedProps['rows'];
8
17
  columns: DataGridPremiumProcessedProps['columns'];
9
- rowGroupingModel: NonNullable<DataGridPremiumProcessedProps['rowGroupingModel']>;
10
- aggregationModel: NonNullable<DataGridPremiumProcessedProps['aggregationModel']>;
11
- getAggregationPosition: NonNullable<DataGridPremiumProcessedProps['getAggregationPosition']>;
12
- columnVisibilityModel: NonNullable<DataGridPremiumProcessedProps['columnVisibilityModel']>;
13
- columnGroupingModel: NonNullable<DataGridPremiumProcessedProps['columnGroupingModel']>;
14
- groupingColDef: NonNullable<DataGridPremiumProcessedProps['groupingColDef']>;
15
- headerFilters: NonNullable<DataGridPremiumProcessedProps['headerFilters']>;
16
- disableAggregation: NonNullable<DataGridPremiumProcessedProps['disableAggregation']>;
17
- disableRowGrouping: NonNullable<DataGridPremiumProcessedProps['disableRowGrouping']>;
18
+ aggregationModel: DataGridPremiumProcessedProps['aggregationModel'];
19
+ columnGroupingModel: DataGridPremiumProcessedProps['columnGroupingModel'];
18
20
  };
21
+ export type GridPivotingPropsOverrides = GridPivotingStaticPropsOverrides & GridPivotingDynamicPropsOverrides;
19
22
  export interface GridPivotingState extends GridPivotingStatePartial {
20
23
  model: GridPivotModel;
21
- propsOverrides: GridPivotingPropsOverrides | undefined;
24
+ propsOverrides: GridPivotingPropsOverrides | GridPivotingStaticPropsOverrides | {} | undefined;
22
25
  }
23
26
  export interface GridPivotingInitialState {
24
27
  model?: GridPivotModel;
@@ -73,7 +76,14 @@ export interface GridPivotingPrivateApi extends GridPivotingPrivateApiCommunity
73
76
  targetFieldPosition?: DropPosition;
74
77
  }) => void;
75
78
  }
76
- export type GridPivotingColDefOverrides = Pick<GridColDef, 'width' | 'flex' | 'headerName' | 'description' | 'align' | 'headerAlign' | 'cellClassName' | 'headerClassName' | 'display' | 'maxWidth' | 'minWidth' | 'resizable' | 'sortingOrder'>;
79
+ export type GridPivotingColDefOverrides = Pick<GridColDef, 'field' | 'width' | 'flex' | 'headerName' | 'description' | 'align' | 'headerAlign' | 'cellClassName' | 'headerClassName' | 'display' | 'maxWidth' | 'minWidth' | 'resizable' | 'sortingOrder'>;
80
+ /**
81
+ * The column definition overrides callback for the columns generated by the pivoting feature.
82
+ * @param {string} originalColumnField The field of the original column.
83
+ * @param {string[]} columnGroupPath The path of the column groups the column belongs to.
84
+ * @returns {Partial<GridPivotingColDefOverrides> | undefined | void} The column definition overrides.
85
+ */
86
+ export type PivotingColDefCallback = (originalColumnField: GridColDef['field'], columnGroupPath: string[]) => Partial<GridPivotingColDefOverrides> | undefined;
77
87
  export interface GridPivotingInternalCache {
78
88
  nonPivotDataRef: RefObject<{
79
89
  rows: GridRowModel[];
@@ -7,5 +7,5 @@ export declare const gridPivotModelSelector: (args_0: import("react").RefObject<
7
7
  } | null>) => import("./gridPivotingInterfaces.js").GridPivotModel;
8
8
  export declare const gridPivotPropsOverridesSelector: (args_0: import("react").RefObject<{
9
9
  state: GridStatePremium;
10
- } | null>) => import("./gridPivotingInterfaces.js").GridPivotingPropsOverrides | undefined;
10
+ } | null>) => {} | undefined;
11
11
  export { gridPivotActiveSelector, gridPivotInitialColumnsSelector } from '@mui/x-data-grid/internals';
@@ -0,0 +1 @@
1
+ export { gridPivotModelSelector } from "./gridPivotingSelectors.js";
@@ -0,0 +1 @@
1
+ export { gridPivotModelSelector } from "./gridPivotingSelectors.js";
@@ -4,5 +4,5 @@ import { GridStateInitializer } from '@mui/x-data-grid-pro/internals';
4
4
  import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
5
5
  import { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
6
6
  export declare const pivotingStateInitializer: GridStateInitializer<Pick<DataGridPremiumProcessedProps, 'pivotActive' | 'pivotModel' | 'pivotPanelOpen' | 'initialState' | 'disablePivoting' | 'getPivotDerivedColumns' | 'columns'>, GridPrivateApiPremium>;
7
- export declare const useGridPivoting: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "pivotActive" | "onPivotActiveChange" | "pivotModel" | "onPivotModelChange" | "pivotPanelOpen" | "onPivotPanelOpenChange" | "disablePivoting" | "getPivotDerivedColumns" | "pivotingColDef" | "groupingColDef" | "aggregationFunctions">, originalColumnsProp: readonly GridColDef[], originalRowsProp: readonly GridRowModel[]) => void;
7
+ export declare const useGridPivoting: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "pivotActive" | "onPivotActiveChange" | "pivotModel" | "onPivotModelChange" | "pivotPanelOpen" | "onPivotPanelOpenChange" | "disablePivoting" | "getPivotDerivedColumns" | "pivotingColDef" | "groupingColDef" | "aggregationFunctions" | "loading" | "dataSource">, originalColumnsProp: readonly GridColDef[], originalRowsProp: readonly GridRowModel[]) => void;
8
8
  export declare const useGridPivotingExportState: (apiRef: RefObject<GridPrivateApiPremium>) => void;
@@ -6,7 +6,7 @@ import useOnMount from '@mui/utils/useOnMount';
6
6
  import { useGridApiMethod, useGridRegisterPipeProcessor, useGridSelector, gridPivotInitialColumnsSelector } from '@mui/x-data-grid-pro/internals';
7
7
  import { GridPivotPanel } from "../../../components/pivotPanel/index.js";
8
8
  import { gridPivotModelSelector, gridPivotActiveSelector, gridPivotPanelOpenSelector } from "./gridPivotingSelectors.js";
9
- import { getInitialColumns, getPivotedData, isPivotingAvailable as isPivotingAvailableFn } from "./utils.js";
9
+ import { getInitialColumns, getPivotForcedProps, createPivotPropsFromRows } from "./utils.js";
10
10
  import { getAvailableAggregationFunctions } from "../aggregation/gridAggregationUtils.js";
11
11
  import { GridSidebarValue } from "../sidebar/index.js";
12
12
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -24,7 +24,7 @@ export const pivotingStateInitializer = (state, props, apiRef) => {
24
24
  current: undefined
25
25
  }
26
26
  };
27
- if (!isPivotingAvailableFn(props)) {
27
+ if (props.disablePivoting) {
28
28
  return _extends({}, state, {
29
29
  pivoting: {
30
30
  active: false,
@@ -49,11 +49,12 @@ export const pivotingStateInitializer = (state, props, apiRef) => {
49
49
  };
50
50
  export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRowsProp) => {
51
51
  const isPivotActive = useGridSelector(apiRef, gridPivotActiveSelector);
52
+ const isLoading = props.loading ?? gridRowsLoadingSelector(apiRef);
52
53
  const {
53
54
  exportedStateRef,
54
55
  nonPivotDataRef
55
56
  } = apiRef.current.caches.pivoting;
56
- const isPivotingAvailable = isPivotingAvailableFn(props);
57
+ const isPivotingAvailable = !props.disablePivoting;
57
58
  apiRef.current.registerControlState({
58
59
  stateId: 'pivotModel',
59
60
  propModel: props.pivotModel,
@@ -79,16 +80,19 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
79
80
  if (!exportedStateRef.current) {
80
81
  exportedStateRef.current = apiRef.current.exportState();
81
82
  }
82
- const rowIds = gridDataRowIdsSelector(apiRef);
83
- const rowsLookup = gridRowsLookupSelector(apiRef);
84
- const rows = rowIds.map(id => rowsLookup[id]);
83
+ let rows = [];
84
+ if (!props.dataSource) {
85
+ const rowIds = gridDataRowIdsSelector(apiRef);
86
+ const rowsLookup = gridRowsLookupSelector(apiRef);
87
+ rows = rowIds.map(id => rowsLookup[id]);
88
+ }
85
89
  const initialColumns = getInitialColumns(originalColumnsProp, props.getPivotDerivedColumns, apiRef.current.getLocaleText);
86
90
  return {
87
91
  rows,
88
92
  columns: initialColumns,
89
93
  originalRowsProp
90
94
  };
91
- }, [apiRef, props.getPivotDerivedColumns, originalColumnsProp, originalRowsProp, exportedStateRef]);
95
+ }, [apiRef, props.getPivotDerivedColumns, originalColumnsProp, originalRowsProp, exportedStateRef, props.dataSource]);
92
96
  const computePivotingState = React.useCallback(({
93
97
  active,
94
98
  model: pivotModel
@@ -101,32 +105,39 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
101
105
  rows: [],
102
106
  columns: new Map()
103
107
  };
104
- return {
105
- initialColumns: columns,
106
- // TODO: fix getPivotedData called twice in controlled mode
107
- propsOverrides: getPivotedData({
108
+ let propsOverrides = getPivotForcedProps(pivotModel, columns, props.groupingColDef);
109
+
110
+ // without data source, add more props overrides based on the data
111
+ if (!isLoading && !props.dataSource) {
112
+ propsOverrides = _extends({}, propsOverrides, createPivotPropsFromRows({
108
113
  rows,
109
114
  columns,
110
115
  pivotModel,
111
- apiRef: apiRef,
112
116
  pivotingColDef: props.pivotingColDef,
113
- groupingColDef: props.groupingColDef
114
- })
117
+ apiRef
118
+ }));
119
+ }
120
+ return {
121
+ initialColumns: columns,
122
+ propsOverrides
115
123
  };
116
124
  }
117
- return undefined;
118
- }, [apiRef, props.pivotingColDef, props.groupingColDef, nonPivotDataRef]);
125
+ return {};
126
+ }, [apiRef, isLoading, props.dataSource, props.pivotingColDef, props.groupingColDef, nonPivotDataRef]);
119
127
  useOnMount(() => {
120
128
  if (!isPivotingAvailable || !isPivotActive) {
121
129
  return undefined;
122
130
  }
123
131
  nonPivotDataRef.current = getInitialData();
124
- const isLoading = gridRowsLoadingSelector(apiRef) ?? false;
125
- if (isLoading) {
126
- return undefined;
127
- }
128
132
  apiRef.current.setState(state => {
129
- const pivotingState = _extends({}, state.pivoting, computePivotingState(state.pivoting));
133
+ const {
134
+ initialColumns,
135
+ propsOverrides
136
+ } = computePivotingState(state.pivoting);
137
+ const pivotingState = _extends({}, state.pivoting, {
138
+ initialColumns: initialColumns || state.pivoting.initialColumns,
139
+ propsOverrides: _extends({}, state.pivoting.propsOverrides, propsOverrides)
140
+ });
130
141
  return _extends({}, state, {
131
142
  pivoting: pivotingState
132
143
  });
@@ -156,9 +167,15 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
156
167
  if (state.pivoting?.model === newPivotModel) {
157
168
  return state;
158
169
  }
159
- const newPivotingState = _extends({}, state.pivoting, computePivotingState(_extends({}, state.pivoting, {
170
+ const {
171
+ initialColumns,
172
+ propsOverrides
173
+ } = computePivotingState(_extends({}, state.pivoting, {
160
174
  model: newPivotModel
161
- })), {
175
+ }));
176
+ const newPivotingState = _extends({}, state.pivoting, {
177
+ initialColumns: initialColumns || state.pivoting.initialColumns,
178
+ propsOverrides: _extends({}, state.pivoting.propsOverrides, propsOverrides),
162
179
  model: newPivotModel
163
180
  });
164
181
  return _extends({}, state, {
@@ -198,7 +215,7 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
198
215
  const aggFunc = isSameSection ? prev.values.find(item => item.field === field)?.aggFunc : getAvailableAggregationFunctions({
199
216
  aggregationFunctions: props.aggregationFunctions,
200
217
  colDef: initialColumns.get(field),
201
- isDataSource: false
218
+ isDataSource: !!props.dataSource
202
219
  })[0];
203
220
  newSectionArray.splice(toIndex, 0, {
204
221
  field,
@@ -227,7 +244,7 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
227
244
  }
228
245
  return newModel;
229
246
  });
230
- }, [apiRef, props.aggregationFunctions]);
247
+ }, [apiRef, props.aggregationFunctions, props.dataSource]);
231
248
  const setPivotActive = React.useCallback(callback => {
232
249
  if (!isPivotingAvailable) {
233
250
  return;
@@ -240,9 +257,15 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
240
257
  if (newPivotMode) {
241
258
  nonPivotDataRef.current = getInitialData();
242
259
  }
243
- const newPivotingState = _extends({}, state.pivoting, computePivotingState(_extends({}, state.pivoting, {
260
+ const {
261
+ initialColumns,
262
+ propsOverrides
263
+ } = computePivotingState(_extends({}, state.pivoting, {
244
264
  active: newPivotMode
245
- })), {
265
+ }));
266
+ const newPivotingState = _extends({}, state.pivoting, {
267
+ initialColumns: initialColumns || state.pivoting.initialColumns,
268
+ propsOverrides: _extends({}, state.pivoting.propsOverrides, propsOverrides),
246
269
  active: newPivotMode
247
270
  });
248
271
  const newState = _extends({}, state, {
@@ -286,15 +309,19 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
286
309
  nonPivotDataRef.current.columns = getInitialColumns(columns, props.getPivotDerivedColumns, apiRef.current.getLocaleText);
287
310
  }
288
311
  apiRef.current.setState(state => {
312
+ const {
313
+ propsOverrides
314
+ } = computePivotingState(state.pivoting);
289
315
  return _extends({}, state, {
290
- pivoting: _extends({}, state.pivoting, computePivotingState(state.pivoting), {
291
- initialColumns: nonPivotDataRef.current?.columns
316
+ pivoting: _extends({}, state.pivoting, {
317
+ initialColumns: nonPivotDataRef.current?.columns,
318
+ propsOverrides: _extends({}, state.pivoting.propsOverrides, propsOverrides)
292
319
  })
293
320
  });
294
321
  });
295
322
  }, [isPivotingAvailable, apiRef, props.getPivotDerivedColumns, computePivotingState, nonPivotDataRef]);
296
323
  const updateNonPivotRows = React.useCallback((rows, keepPreviousRows = true) => {
297
- if (!nonPivotDataRef.current || !isPivotingAvailable || !rows || rows.length === 0) {
324
+ if (!nonPivotDataRef.current || props.dataSource || !isPivotingAvailable || !rows || rows.length === 0) {
298
325
  return;
299
326
  }
300
327
  if (keepPreviousRows) {
@@ -316,18 +343,42 @@ export const useGridPivoting = (apiRef, props, originalColumnsProp, originalRows
316
343
  nonPivotDataRef.current.rows = rows;
317
344
  }
318
345
  apiRef.current.setState(state => {
346
+ const {
347
+ initialColumns,
348
+ propsOverrides
349
+ } = computePivotingState(state.pivoting);
319
350
  return _extends({}, state, {
320
- pivoting: _extends({}, state.pivoting, computePivotingState(state.pivoting))
351
+ pivoting: _extends({}, state.pivoting, {
352
+ initialColumns: initialColumns || state.pivoting.initialColumns,
353
+ propsOverrides: _extends({}, state.pivoting.propsOverrides, propsOverrides)
354
+ })
321
355
  });
322
356
  });
323
- }, [apiRef, computePivotingState, isPivotingAvailable, nonPivotDataRef]);
357
+ }, [apiRef, computePivotingState, isPivotingAvailable, nonPivotDataRef, props.dataSource]);
324
358
  const addPivotingPanel = React.useCallback((initialValue, value) => {
325
359
  if (isPivotingAvailable && value === GridSidebarValue.Pivot) {
326
360
  return /*#__PURE__*/_jsx(GridPivotPanel, {});
327
361
  }
328
362
  return initialValue;
329
363
  }, [isPivotingAvailable]);
364
+ const addGetRowsParams = React.useCallback(params => {
365
+ if (!isPivotingAvailable || !isPivotActive) {
366
+ return params;
367
+ }
368
+ const pivotModel = gridPivotModelSelector(apiRef);
369
+ const visibleColumns = pivotModel.columns.filter(column => !column.hidden);
370
+ const visibleRows = pivotModel.rows.filter(row => !row.hidden);
371
+ const visibleValues = pivotModel.values.filter(value => !value.hidden);
372
+ return _extends({}, params, {
373
+ pivotModel: {
374
+ columns: visibleColumns,
375
+ rows: visibleRows,
376
+ values: visibleValues
377
+ }
378
+ });
379
+ }, [apiRef, isPivotingAvailable, isPivotActive]);
330
380
  useGridRegisterPipeProcessor(apiRef, 'sidebar', addPivotingPanel);
381
+ useGridRegisterPipeProcessor(apiRef, 'getRowsParams', addGetRowsParams);
331
382
  useGridApiMethod(apiRef, {
332
383
  setPivotModel,
333
384
  setPivotActive,
@@ -2,22 +2,20 @@ import { GridColDef, GridRowModel, GridLocaleTextApi } from '@mui/x-data-grid-pr
2
2
  import type { RefObject } from '@mui/x-internals/types';
3
3
  import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
4
4
  import type { GridApiPremium } from "../../../models/gridApiPremium.js";
5
- import type { GridPivotingPropsOverrides, GridPivotModel } from "./gridPivotingInterfaces.js";
6
- export declare const isPivotingAvailable: (props: Pick<DataGridPremiumProcessedProps, "disablePivoting">) => boolean;
7
- export declare const defaultGetPivotDerivedColumns: DataGridPremiumProcessedProps['getPivotDerivedColumns'];
5
+ import type { GridPivotingStaticPropsOverrides, GridPivotingDynamicPropsOverrides, GridPivotModel } from "./gridPivotingInterfaces.js";
6
+ export declare const defaultGetPivotDerivedColumns: NonNullable<DataGridPremiumProcessedProps['getPivotDerivedColumns']>;
8
7
  export declare const getInitialColumns: (originalColumns: DataGridPremiumProcessedProps["columns"], getPivotDerivedColumns: DataGridPremiumProcessedProps["getPivotDerivedColumns"], getLocaleText: GridLocaleTextApi["getLocaleText"]) => Map<string, GridColDef>;
9
- export declare const getPivotedData: ({
8
+ export declare const getPivotForcedProps: (pivotModel: GridPivotModel, columns: Map<string, GridColDef>, groupingColDef: DataGridPremiumProcessedProps["groupingColDef"]) => GridPivotingStaticPropsOverrides;
9
+ export declare const createPivotPropsFromRows: ({
10
10
  rows,
11
11
  columns,
12
12
  pivotModel,
13
- apiRef,
14
13
  pivotingColDef,
15
- groupingColDef
14
+ apiRef
16
15
  }: {
17
16
  rows: GridRowModel[];
18
17
  columns: Map<string, GridColDef>;
19
18
  pivotModel: GridPivotModel;
20
- apiRef: RefObject<GridApiPremium>;
21
19
  pivotingColDef: DataGridPremiumProcessedProps["pivotingColDef"];
22
- groupingColDef: DataGridPremiumProcessedProps["groupingColDef"];
23
- }) => GridPivotingPropsOverrides;
20
+ apiRef: RefObject<GridApiPremium>;
21
+ }) => GridPivotingDynamicPropsOverrides;
@@ -4,9 +4,6 @@ import { getDefaultColTypeDef } from '@mui/x-data-grid-pro/internals';
4
4
  import { COLUMN_GROUP_ID_SEPARATOR } from "../../../constants/columnGroups.js";
5
5
  import { isGroupingColumn } from "../rowGrouping/index.js";
6
6
  import { defaultGetAggregationPosition } from "../aggregation/gridAggregationUtils.js";
7
- export const isPivotingAvailable = props => {
8
- return !props.disablePivoting;
9
- };
10
7
  export const defaultGetPivotDerivedColumns = (column, getLocaleText) => {
11
8
  if (column.type === 'date') {
12
9
  const field = column.field;
@@ -39,11 +36,17 @@ export const getInitialColumns = (originalColumns, getPivotDerivedColumns, getLo
39
36
  }
40
37
  return initialColumns;
41
38
  };
42
- function sortColumnGroups(columnGroups, pivotModelColumns, depth = 0) {
39
+ const sortColumnGroups = (columnGroups, pivotModelColumns, depth = 0) => {
43
40
  if (depth > pivotModelColumns.length - 1) {
44
41
  return;
45
42
  }
46
43
  const sort = pivotModelColumns[depth].sort;
44
+ if (columnGroups.length < 2) {
45
+ if (columnGroups[0]?.children) {
46
+ sortColumnGroups(columnGroups[0].children, pivotModelColumns, depth + 1);
47
+ }
48
+ return;
49
+ }
47
50
  columnGroups.sort((a, b) => {
48
51
  if (isLeaf(a) || isLeaf(b)) {
49
52
  return 0;
@@ -59,20 +62,46 @@ function sortColumnGroups(columnGroups, pivotModelColumns, depth = 0) {
59
62
  }
60
63
  return (sort === 'asc' ? 1 : -1) * gridStringOrNumberComparator(a.rawHeaderName, b.rawHeaderName, {}, {});
61
64
  });
62
- }
63
- export const getPivotedData = ({
65
+ };
66
+ export const getPivotForcedProps = (pivotModel, columns, groupingColDef) => {
67
+ const visibleRows = pivotModel.rows.filter(row => !row.hidden);
68
+ const visibleColumns = pivotModel.columns.filter(column => !column.hidden);
69
+ const visibleValues = pivotModel.values.filter(value => !value.hidden);
70
+ const columnVisibilityModel = {};
71
+ for (const column of columns.values()) {
72
+ columnVisibilityModel[column.field] = false;
73
+ }
74
+ if (visibleColumns.length === 0) {
75
+ visibleValues.forEach(value => {
76
+ delete columnVisibilityModel[value.field];
77
+ });
78
+ }
79
+ const groupingColDefOverrides = params => _extends({}, typeof groupingColDef === 'function' ? groupingColDef(params) : groupingColDef || {}, {
80
+ filterable: false,
81
+ aggregable: false,
82
+ hideable: false
83
+ });
84
+ return {
85
+ columnVisibilityModel,
86
+ rowGroupingModel: visibleRows.map(row => row.field),
87
+ getAggregationPosition: defaultGetAggregationPosition,
88
+ groupingColDef: groupingColDefOverrides,
89
+ headerFilters: false,
90
+ disableAggregation: false,
91
+ disableRowGrouping: false
92
+ };
93
+ };
94
+ export const createPivotPropsFromRows = ({
64
95
  rows,
65
96
  columns,
66
97
  pivotModel,
67
- apiRef,
68
98
  pivotingColDef,
69
- groupingColDef
99
+ apiRef
70
100
  }) => {
71
101
  const visibleColumns = pivotModel.columns.filter(column => !column.hidden);
72
102
  const visibleRows = pivotModel.rows.filter(row => !row.hidden);
73
103
  const visibleValues = pivotModel.values.filter(value => !value.hidden);
74
104
  let pivotColumns = [];
75
- const columnVisibilityModel = {};
76
105
  const pivotColumnsIncludedInPivotValues = [];
77
106
  const initialColumns = new Map();
78
107
  for (const column of columns.values()) {
@@ -96,7 +125,6 @@ export const getPivotedData = ({
96
125
  } else {
97
126
  pivotColumns.push(columnToAdd);
98
127
  }
99
- columnVisibilityModel[column.field] = false;
100
128
  }
101
129
  }
102
130
  pivotColumns = pivotColumns.concat(pivotColumnsIncludedInPivotValues);
@@ -124,7 +152,6 @@ export const getPivotedData = ({
124
152
  newRows = rows;
125
153
  visibleValues.forEach(pivotValue => {
126
154
  aggregationModel[pivotValue.field] = pivotValue.aggFunc;
127
- delete columnVisibilityModel[pivotValue.field];
128
155
  });
129
156
  } else {
130
157
  for (let i = 0; i < rows.length; i += 1) {
@@ -250,22 +277,10 @@ export const getPivotedData = ({
250
277
  }
251
278
  }
252
279
  createColumns(columnGroupingModel);
253
- const groupingColDefOverrides = params => _extends({}, typeof groupingColDef === 'function' ? groupingColDef(params) : groupingColDef || {}, {
254
- filterable: false,
255
- aggregable: false,
256
- hideable: false
257
- });
258
280
  return {
259
281
  rows: visibleRows.length > 0 ? newRows : [],
260
282
  columns: pivotColumns,
261
- rowGroupingModel: visibleRows.map(row => row.field),
262
- aggregationModel,
263
- getAggregationPosition: defaultGetAggregationPosition,
264
- columnVisibilityModel,
265
283
  columnGroupingModel,
266
- groupingColDef: groupingColDefOverrides,
267
- headerFilters: false,
268
- disableAggregation: false,
269
- disableRowGrouping: false
284
+ aggregationModel
270
285
  };
271
286
  };
@@ -83,7 +83,7 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
83
83
  valueFormatter = (value, row, column, apiRef) => {
84
84
  const rowId = gridRowIdSelector(apiRef, row);
85
85
  const rowNode = gridRowNodeSelector(apiRef, rowId);
86
- if (rowNode.type === 'group') {
86
+ if (rowNode?.type === 'group') {
87
87
  const originalColDef = columnsLookup[rowNode.groupingField];
88
88
  if (originalColDef.type === 'singleSelect') {
89
89
  // the default valueFormatter of a singleSelect colDef won't work with the grouping column values