@mui/x-data-grid 6.0.0-alpha.0 → 6.0.0-alpha.2

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 (161) hide show
  1. package/CHANGELOG.md +209 -0
  2. package/DataGrid/useDataGridProps.js +4 -4
  3. package/components/DataGridVirtualScroller.js +5 -3
  4. package/components/GridPagination.d.ts +43 -1
  5. package/components/GridPagination.js +1 -2
  6. package/components/GridRow.d.ts +1 -4
  7. package/components/GridRow.js +9 -8
  8. package/components/base/GridBody.js +1 -2
  9. package/components/base/GridOverlays.js +52 -12
  10. package/components/cell/GridBooleanCell.js +2 -1
  11. package/components/columnSelection/GridCellCheckboxRenderer.d.ts +2 -2
  12. package/components/columnSelection/GridCellCheckboxRenderer.js +1 -6
  13. package/components/containers/GridOverlay.js +0 -5
  14. package/components/panel/filterPanel/GridFilterForm.js +2 -1
  15. package/components/toolbar/GridToolbarFilterButton.js +8 -4
  16. package/constants/gridClasses.d.ts +8 -0
  17. package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +1 -1
  18. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.ts +1 -1
  19. package/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  20. package/hooks/features/editRows/useGridCellEditing.new.js +18 -9
  21. package/hooks/features/editRows/useGridEditing.new.js +3 -2
  22. package/hooks/features/editRows/useGridEditing.old.js +2 -1
  23. package/hooks/features/editRows/useGridRowEditing.new.js +18 -9
  24. package/hooks/features/export/useGridPrintExport.js +31 -17
  25. package/hooks/features/export/utils.js +1 -5
  26. package/hooks/features/filter/gridFilterSelector.js +2 -2
  27. package/hooks/features/filter/useGridFilter.js +6 -6
  28. package/hooks/features/pagination/gridPaginationSelector.js +2 -2
  29. package/hooks/features/rows/gridRowsInterfaces.d.ts +106 -0
  30. package/hooks/features/rows/{gridRowsState.js → gridRowsInterfaces.js} +0 -0
  31. package/hooks/features/rows/gridRowsSelector.d.ts +17 -7
  32. package/hooks/features/rows/gridRowsSelector.js +38 -6
  33. package/hooks/features/rows/gridRowsUtils.d.ts +16 -4
  34. package/hooks/features/rows/gridRowsUtils.js +222 -39
  35. package/hooks/features/rows/index.d.ts +3 -3
  36. package/hooks/features/rows/index.js +2 -2
  37. package/hooks/features/rows/useGridRows.js +161 -124
  38. package/hooks/features/rows/useGridRowsPreProcessors.js +78 -26
  39. package/hooks/features/selection/useGridSelection.js +2 -2
  40. package/hooks/features/sorting/gridSortingSelector.js +9 -4
  41. package/hooks/features/sorting/gridSortingState.d.ts +2 -2
  42. package/hooks/features/sorting/useGridSorting.js +9 -33
  43. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +4 -7
  44. package/hooks/features/virtualization/useGridVirtualScroller.js +11 -17
  45. package/index.js +1 -1
  46. package/internals/index.d.ts +2 -1
  47. package/internals/index.js +1 -0
  48. package/legacy/DataGrid/useDataGridProps.js +4 -4
  49. package/legacy/components/DataGridVirtualScroller.js +5 -3
  50. package/legacy/components/GridPagination.js +1 -2
  51. package/legacy/components/GridRow.js +9 -8
  52. package/legacy/components/base/GridBody.js +1 -2
  53. package/legacy/components/base/GridOverlays.js +54 -12
  54. package/legacy/components/cell/GridBooleanCell.js +2 -1
  55. package/legacy/components/columnSelection/GridCellCheckboxRenderer.js +1 -6
  56. package/legacy/components/containers/GridOverlay.js +0 -5
  57. package/legacy/components/panel/filterPanel/GridFilterForm.js +2 -1
  58. package/legacy/components/toolbar/GridToolbarFilterButton.js +3 -1
  59. package/legacy/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  60. package/legacy/hooks/features/editRows/useGridCellEditing.new.js +18 -9
  61. package/legacy/hooks/features/editRows/useGridEditing.new.js +3 -2
  62. package/legacy/hooks/features/editRows/useGridEditing.old.js +2 -1
  63. package/legacy/hooks/features/editRows/useGridRowEditing.new.js +18 -9
  64. package/legacy/hooks/features/export/useGridPrintExport.js +33 -20
  65. package/legacy/hooks/features/export/utils.js +1 -3
  66. package/legacy/hooks/features/filter/gridFilterSelector.js +2 -2
  67. package/legacy/hooks/features/filter/useGridFilter.js +6 -6
  68. package/legacy/hooks/features/pagination/gridPaginationSelector.js +2 -2
  69. package/legacy/hooks/features/rows/{gridRowsState.js → gridRowsInterfaces.js} +0 -0
  70. package/legacy/hooks/features/rows/gridRowsSelector.js +52 -9
  71. package/legacy/hooks/features/rows/gridRowsUtils.js +238 -46
  72. package/legacy/hooks/features/rows/index.js +2 -2
  73. package/legacy/hooks/features/rows/useGridRows.js +163 -134
  74. package/legacy/hooks/features/rows/useGridRowsPreProcessors.js +81 -26
  75. package/legacy/hooks/features/selection/useGridSelection.js +2 -2
  76. package/legacy/hooks/features/sorting/gridSortingSelector.js +5 -2
  77. package/legacy/hooks/features/sorting/useGridSorting.js +11 -33
  78. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +11 -17
  79. package/legacy/index.js +1 -1
  80. package/legacy/internals/index.js +1 -0
  81. package/legacy/models/gridFeatureMode.js +1 -4
  82. package/models/api/gridParamsApi.d.ts +2 -2
  83. package/models/api/gridRowApi.d.ts +7 -5
  84. package/models/events/gridEventLookup.d.ts +3 -3
  85. package/models/gridApiCaches.d.ts +1 -1
  86. package/models/gridFeatureMode.d.ts +0 -4
  87. package/models/gridFeatureMode.js +1 -4
  88. package/models/gridRows.d.ts +100 -30
  89. package/models/gridSortModel.d.ts +2 -2
  90. package/models/params/gridCellParams.d.ts +7 -11
  91. package/modern/DataGrid/useDataGridProps.js +4 -4
  92. package/modern/components/DataGridVirtualScroller.js +5 -3
  93. package/modern/components/GridPagination.js +1 -2
  94. package/modern/components/GridRow.js +9 -8
  95. package/modern/components/base/GridBody.js +1 -2
  96. package/modern/components/base/GridOverlays.js +52 -12
  97. package/modern/components/cell/GridBooleanCell.js +2 -1
  98. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +1 -6
  99. package/modern/components/containers/GridOverlay.js +0 -5
  100. package/modern/components/panel/filterPanel/GridFilterForm.js +2 -1
  101. package/modern/components/toolbar/GridToolbarFilterButton.js +1 -1
  102. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  103. package/modern/hooks/features/editRows/useGridCellEditing.new.js +18 -9
  104. package/modern/hooks/features/editRows/useGridEditing.new.js +3 -2
  105. package/modern/hooks/features/editRows/useGridEditing.old.js +2 -1
  106. package/modern/hooks/features/editRows/useGridRowEditing.new.js +18 -9
  107. package/modern/hooks/features/export/useGridPrintExport.js +30 -16
  108. package/modern/hooks/features/export/utils.js +1 -1
  109. package/modern/hooks/features/filter/gridFilterSelector.js +2 -2
  110. package/modern/hooks/features/filter/useGridFilter.js +6 -6
  111. package/modern/hooks/features/pagination/gridPaginationSelector.js +2 -2
  112. package/modern/hooks/features/rows/{gridRowsState.js → gridRowsInterfaces.js} +0 -0
  113. package/modern/hooks/features/rows/gridRowsSelector.js +28 -6
  114. package/modern/hooks/features/rows/gridRowsUtils.js +220 -37
  115. package/modern/hooks/features/rows/index.js +2 -2
  116. package/modern/hooks/features/rows/useGridRows.js +158 -121
  117. package/modern/hooks/features/rows/useGridRowsPreProcessors.js +78 -26
  118. package/modern/hooks/features/selection/useGridSelection.js +2 -2
  119. package/modern/hooks/features/sorting/gridSortingSelector.js +3 -2
  120. package/modern/hooks/features/sorting/useGridSorting.js +9 -33
  121. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +10 -16
  122. package/modern/index.js +1 -1
  123. package/modern/internals/index.js +1 -0
  124. package/modern/models/gridFeatureMode.js +1 -4
  125. package/node/DataGrid/useDataGridProps.js +3 -3
  126. package/node/components/DataGridVirtualScroller.js +5 -3
  127. package/node/components/GridPagination.js +1 -2
  128. package/node/components/GridRow.js +9 -7
  129. package/node/components/base/GridBody.js +1 -3
  130. package/node/components/base/GridOverlays.js +57 -12
  131. package/node/components/cell/GridBooleanCell.js +3 -1
  132. package/node/components/columnSelection/GridCellCheckboxRenderer.js +1 -6
  133. package/node/components/containers/GridOverlay.js +0 -5
  134. package/node/components/panel/filterPanel/GridFilterForm.js +2 -1
  135. package/node/components/toolbar/GridToolbarFilterButton.js +8 -4
  136. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  137. package/node/hooks/features/editRows/useGridCellEditing.new.js +20 -10
  138. package/node/hooks/features/editRows/useGridEditing.new.js +4 -2
  139. package/node/hooks/features/editRows/useGridEditing.old.js +3 -1
  140. package/node/hooks/features/editRows/useGridRowEditing.new.js +20 -10
  141. package/node/hooks/features/export/useGridPrintExport.js +31 -17
  142. package/node/hooks/features/export/utils.js +1 -5
  143. package/node/hooks/features/filter/gridFilterSelector.js +1 -1
  144. package/node/hooks/features/filter/useGridFilter.js +5 -6
  145. package/node/hooks/features/pagination/gridPaginationSelector.js +1 -1
  146. package/node/hooks/features/rows/{gridRowsState.js → gridRowsInterfaces.js} +0 -0
  147. package/node/hooks/features/rows/gridRowsSelector.js +43 -10
  148. package/node/hooks/features/rows/gridRowsUtils.js +239 -40
  149. package/node/hooks/features/rows/index.js +23 -9
  150. package/node/hooks/features/rows/useGridRows.js +161 -122
  151. package/node/hooks/features/rows/useGridRowsPreProcessors.js +81 -26
  152. package/node/hooks/features/selection/useGridSelection.js +2 -2
  153. package/node/hooks/features/sorting/gridSortingSelector.js +9 -4
  154. package/node/hooks/features/sorting/useGridSorting.js +9 -33
  155. package/node/hooks/features/virtualization/useGridVirtualScroller.js +11 -17
  156. package/node/index.js +1 -1
  157. package/node/internals/index.js +14 -2
  158. package/node/models/gridFeatureMode.js +1 -7
  159. package/package.json +1 -1
  160. package/themeAugmentation/props.d.ts +2 -2
  161. package/hooks/features/rows/gridRowsState.d.ts +0 -60
@@ -2,12 +2,12 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
4
4
  import { useGridLogger } from '../../utils/useGridLogger';
5
- import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowIdsSelector, gridRowGroupingNameSelector, gridRowsIdToIdLookupSelector } from './gridRowsSelector';
5
+ import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridDataRowIdsSelector, gridRowsDataRowIdToIdLookupSelector, gridRowMaximumTreeDepthSelector } from './gridRowsSelector';
6
6
  import { GridSignature, useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
7
7
  import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
8
8
  import { gridSortedRowIdsSelector } from '../sorting/gridSortingSelector';
9
9
  import { gridFilteredRowsLookupSelector } from '../filter/gridFilterSelector';
10
- import { getTreeNodeDescendants, createRowsInternalCache, getRowsStateFromCache, getRowIdFromRowModel } from './gridRowsUtils';
10
+ import { getTreeNodeDescendants, createRowsInternalCache, getRowsStateFromCache, isAutoGeneratedRow, GRID_ROOT_GROUP_ID, updateCacheWithNewRows, getTopLevelRowCount, getRowIdFromRowModel } from './gridRowsUtils';
11
11
  import { useGridRegisterPipeApplier } from '../../core/pipeProcessing';
12
12
  export const rowsStateInitializer = (state, props, apiRef) => {
13
13
  apiRef.current.unstable_caches.rows = createRowsInternalCache({
@@ -18,9 +18,10 @@ export const rowsStateInitializer = (state, props, apiRef) => {
18
18
  return _extends({}, state, {
19
19
  rows: getRowsStateFromCache({
20
20
  apiRef,
21
- previousTree: null,
22
21
  rowCountProp: props.rowCount,
23
- loadingProp: props.loading
22
+ loadingProp: props.loading,
23
+ previousTree: null,
24
+ previousTreeDepths: null
24
25
  })
25
26
  });
26
27
  };
@@ -37,23 +38,42 @@ export const useGridRows = (apiRef, props) => {
37
38
  const currentPage = useGridVisibleRows(apiRef, props);
38
39
  const lastUpdateMs = React.useRef(Date.now());
39
40
  const timeout = React.useRef(null);
40
- const getRow = React.useCallback(id => gridRowsLookupSelector(apiRef)[id] ?? null, [apiRef]);
41
+ const getRow = React.useCallback(id => {
42
+ const model = gridRowsLookupSelector(apiRef)[id];
43
+
44
+ if (model) {
45
+ return model;
46
+ }
47
+
48
+ const node = apiRef.current.getRowNode(id);
49
+
50
+ if (node && isAutoGeneratedRow(node)) {
51
+ // TODO rows v6: Is it the best approach ?
52
+ return {};
53
+ }
54
+
55
+ return null;
56
+ }, [apiRef]);
41
57
  const lookup = React.useMemo(() => currentPage.rows.reduce((acc, {
42
58
  id
43
59
  }, index) => {
44
60
  acc[id] = index;
45
61
  return acc;
46
62
  }, {}), [currentPage.rows]);
47
- const throttledRowsChange = React.useCallback((newCache, throttle) => {
63
+ const throttledRowsChange = React.useCallback(({
64
+ cache,
65
+ throttle
66
+ }) => {
48
67
  const run = () => {
49
68
  timeout.current = null;
50
69
  lastUpdateMs.current = Date.now();
51
70
  apiRef.current.setState(state => _extends({}, state, {
52
71
  rows: getRowsStateFromCache({
53
72
  apiRef,
54
- previousTree: gridRowTreeSelector(apiRef),
55
73
  rowCountProp: props.rowCount,
56
- loadingProp: props.loading
74
+ loadingProp: props.loading,
75
+ previousTree: gridRowTreeSelector(apiRef),
76
+ previousTreeDepths: gridRowTreeDepthsSelector(apiRef)
57
77
  })
58
78
  }));
59
79
  apiRef.current.publishEvent('rowsSet');
@@ -65,7 +85,7 @@ export const useGridRows = (apiRef, props) => {
65
85
  timeout.current = null;
66
86
  }
67
87
 
68
- apiRef.current.unstable_caches.rows = newCache;
88
+ apiRef.current.unstable_caches.rows = cache;
69
89
 
70
90
  if (!throttle) {
71
91
  run();
@@ -87,72 +107,38 @@ export const useGridRows = (apiRef, props) => {
87
107
 
88
108
  const setRows = React.useCallback(rows => {
89
109
  logger.debug(`Updating all rows, new length ${rows.length}`);
90
- throttledRowsChange(createRowsInternalCache({
91
- rows,
92
- getRowId: props.getRowId,
93
- loading: props.loading
94
- }), true);
110
+ throttledRowsChange({
111
+ cache: createRowsInternalCache({
112
+ rows,
113
+ getRowId: props.getRowId,
114
+ loading: props.loading
115
+ }),
116
+ throttle: true
117
+ });
95
118
  }, [logger, props.getRowId, props.loading, throttledRowsChange]);
96
119
  const updateRows = React.useCallback(updates => {
97
120
  if (props.signature === GridSignature.DataGrid && updates.length > 1) {
98
121
  // TODO: Add test with direct call to `apiRef.current.updateRows` in DataGrid after enabling the `apiRef` on the free plan.
99
122
  throw new Error(["MUI: You can't update several rows at once in `apiRef.current.updateRows` on the DataGrid.", 'You need to upgrade to DataGridPro or DataGridPremium component to unlock this feature.'].join('\n'));
100
- } // we remove duplicate updates. A server can batch updates, and send several updates for the same row in one fn call.
101
-
102
-
103
- const uniqueUpdates = new Map();
104
- updates.forEach(update => {
105
- const id = getRowIdFromRowModel(update, props.getRowId, 'A row was provided without id when calling updateRows():');
123
+ }
106
124
 
107
- if (uniqueUpdates.has(id)) {
108
- uniqueUpdates.set(id, _extends({}, uniqueUpdates.get(id), update));
109
- } else {
110
- uniqueUpdates.set(id, update);
111
- }
125
+ const cache = updateCacheWithNewRows({
126
+ updates,
127
+ getRowId: props.getRowId,
128
+ previousCache: apiRef.current.unstable_caches.rows
112
129
  });
113
- const deletedRowIds = [];
114
- const prevCache = apiRef.current.unstable_caches.rows;
115
- const newCache = {
116
- rowsBeforePartialUpdates: prevCache.rowsBeforePartialUpdates,
117
- loadingPropBeforePartialUpdates: prevCache.loadingPropBeforePartialUpdates,
118
- idRowsLookup: _extends({}, prevCache.idRowsLookup),
119
- idToIdLookup: _extends({}, prevCache.idToIdLookup),
120
- ids: [...prevCache.ids]
121
- };
122
- uniqueUpdates.forEach((partialRow, id) => {
123
- // eslint-disable-next-line no-underscore-dangle
124
- if (partialRow._action === 'delete') {
125
- delete newCache.idRowsLookup[id];
126
- delete newCache.idToIdLookup[id];
127
- deletedRowIds.push(id);
128
- return;
129
- }
130
-
131
- const oldRow = apiRef.current.getRow(id);
132
-
133
- if (!oldRow) {
134
- newCache.idRowsLookup[id] = partialRow;
135
- newCache.idToIdLookup[id] = id;
136
- newCache.ids.push(id);
137
- return;
138
- }
139
-
140
- newCache.idRowsLookup[id] = _extends({}, apiRef.current.getRow(id), partialRow);
130
+ throttledRowsChange({
131
+ cache,
132
+ throttle: true
141
133
  });
142
-
143
- if (deletedRowIds.length > 0) {
144
- newCache.ids = newCache.ids.filter(id => !deletedRowIds.includes(id));
145
- }
146
-
147
- throttledRowsChange(newCache, true);
148
134
  }, [props.signature, props.getRowId, throttledRowsChange, apiRef]);
149
135
  const getRowModels = React.useCallback(() => {
150
- const allRows = gridRowIdsSelector(apiRef);
136
+ const dataRows = gridDataRowIdsSelector(apiRef);
151
137
  const idRowsLookup = gridRowsLookupSelector(apiRef);
152
- return new Map(allRows.map(id => [id, idRowsLookup[id]]));
138
+ return new Map(dataRows.map(id => [id, idRowsLookup[id] ?? {}]));
153
139
  }, [apiRef]);
154
140
  const getRowsCount = React.useCallback(() => gridRowCountSelector(apiRef), [apiRef]);
155
- const getAllRowIds = React.useCallback(() => gridRowIdsSelector(apiRef), [apiRef]);
141
+ const getAllRowIds = React.useCallback(() => gridDataRowIdsSelector(apiRef), [apiRef]);
156
142
  const getRowIndexRelativeToVisibleRows = React.useCallback(id => lookup[id], [lookup]);
157
143
  const setRowChildrenExpansion = React.useCallback((id, isExpanded) => {
158
144
  const currentNode = apiRef.current.getRowNode(id);
@@ -161,6 +147,10 @@ export const useGridRows = (apiRef, props) => {
161
147
  throw new Error(`MUI: No row with id #${id} found`);
162
148
  }
163
149
 
150
+ if (currentNode.type !== 'group') {
151
+ throw new Error('MUI: Only group nodes can be expanded or collapsed');
152
+ }
153
+
164
154
  const newNode = _extends({}, currentNode, {
165
155
  childrenExpanded: isExpanded
166
156
  });
@@ -200,9 +190,8 @@ export const useGridRows = (apiRef, props) => {
200
190
 
201
191
  for (let index = startIndex; index < sortedRowIds.length && tree[sortedRowIds[index]].depth > groupNode.depth; index += 1) {
202
192
  const id = sortedRowIds[index];
203
- const node = tree[id];
204
193
 
205
- if (!skipAutoGeneratedRows || !node.isAutoGenerated) {
194
+ if (!skipAutoGeneratedRows || !isAutoGeneratedRow(tree[id])) {
206
195
  children.push(id);
207
196
  }
208
197
  }
@@ -218,21 +207,42 @@ export const useGridRows = (apiRef, props) => {
218
207
  return children;
219
208
  }, [apiRef]);
220
209
  const setRowIndex = React.useCallback((rowId, targetIndex) => {
221
- const allRows = gridRowIdsSelector(apiRef);
222
- const oldIndex = allRows.findIndex(row => row === rowId);
210
+ const node = apiRef.current.getRowNode(rowId);
223
211
 
224
- if (oldIndex === -1 || oldIndex === targetIndex) {
225
- return;
212
+ if (!node) {
213
+ throw new Error(`MUI: No row with id #${rowId} found`);
226
214
  }
227
215
 
228
- logger.debug(`Moving row ${rowId} to index ${targetIndex}`);
229
- const updatedRows = [...allRows];
230
- updatedRows.splice(targetIndex, 0, updatedRows.splice(oldIndex, 1)[0]);
231
- apiRef.current.setState(state => _extends({}, state, {
232
- rows: _extends({}, state.rows, {
233
- ids: updatedRows
234
- })
235
- }));
216
+ if (node.parent !== GRID_ROOT_GROUP_ID) {
217
+ throw new Error(`MUI: The row reordering do not support reordering of grouped rows yet`);
218
+ }
219
+
220
+ if (node.type !== 'leaf') {
221
+ throw new Error(`MUI: The row reordering do not support reordering of footer or grouping rows`);
222
+ }
223
+
224
+ apiRef.current.setState(state => {
225
+ const group = gridRowTreeSelector(state, apiRef.current.instanceId)[GRID_ROOT_GROUP_ID];
226
+ const allRows = group.children;
227
+ const oldIndex = allRows.findIndex(row => row === rowId);
228
+
229
+ if (oldIndex === -1 || oldIndex === targetIndex) {
230
+ return state;
231
+ }
232
+
233
+ logger.debug(`Moving row ${rowId} to index ${targetIndex}`);
234
+ const updatedRows = [...allRows];
235
+ updatedRows.splice(targetIndex, 0, updatedRows.splice(oldIndex, 1)[0]);
236
+ return _extends({}, state, {
237
+ rows: _extends({}, state.rows, {
238
+ tree: _extends({}, state.rows.tree, {
239
+ [GRID_ROOT_GROUP_ID]: _extends({}, group, {
240
+ children: updatedRows
241
+ })
242
+ })
243
+ })
244
+ });
245
+ });
236
246
  apiRef.current.publishEvent('rowsSet');
237
247
  }, [apiRef, logger]);
238
248
  const replaceRows = React.useCallback((firstRowToRender, newRows) => {
@@ -244,49 +254,51 @@ export const useGridRows = (apiRef, props) => {
244
254
  return;
245
255
  }
246
256
 
247
- const allRows = gridRowIdsSelector(apiRef);
248
- const updatedRows = [...allRows];
249
- const idRowsLookup = gridRowsLookupSelector(apiRef);
250
- const idToIdLookup = gridRowsIdToIdLookupSelector(apiRef);
251
- const tree = gridRowTreeSelector(apiRef);
257
+ const treeDepth = gridRowMaximumTreeDepthSelector(apiRef);
252
258
 
253
- const updatedIdRowsLookup = _extends({}, idRowsLookup);
259
+ if (treeDepth > 1) {
260
+ throw new Error('`apiRef.current.unstable_replaceRows` is not compatible with tree data and row grouping');
261
+ }
254
262
 
255
- const updatedIdToIdLookup = _extends({}, idToIdLookup);
263
+ const tree = _extends({}, gridRowTreeSelector(apiRef));
256
264
 
257
- const updatedTree = _extends({}, tree);
265
+ const dataRowIdToModelLookup = _extends({}, gridRowsLookupSelector(apiRef));
258
266
 
259
- const newRowEntries = newRows.map(newRowModel => {
260
- const rowId = getRowIdFromRowModel(newRowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
261
- return {
262
- id: rowId,
263
- model: newRowModel
264
- };
265
- });
266
- newRowEntries.forEach((row, index) => {
267
- const [replacedRowId] = updatedRows.splice(firstRowToRender + index, 1, row.id);
268
- delete updatedIdRowsLookup[replacedRowId];
269
- delete updatedIdToIdLookup[replacedRowId];
270
- delete updatedTree[replacedRowId];
271
- });
272
- newRowEntries.forEach(row => {
267
+ const dataRowIdToIdLookup = _extends({}, gridRowsDataRowIdToIdLookupSelector(apiRef));
268
+
269
+ const rootGroup = tree[GRID_ROOT_GROUP_ID];
270
+ const rootGroupChildren = [...rootGroup.children];
271
+
272
+ for (let i = 0; i < newRows.length; i += 1) {
273
+ const rowModel = newRows[i];
274
+ const rowId = getRowIdFromRowModel(rowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
275
+ const [replacedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
276
+ delete dataRowIdToModelLookup[replacedRowId];
277
+ delete dataRowIdToIdLookup[replacedRowId];
278
+ delete tree[replacedRowId];
273
279
  const rowTreeNodeConfig = {
274
- id: row.id,
275
- parent: null,
280
+ id: rowId,
276
281
  depth: 0,
277
- groupingKey: null,
278
- groupingField: null
282
+ parent: GRID_ROOT_GROUP_ID,
283
+ type: 'leaf',
284
+ groupingKey: null
279
285
  };
280
- updatedIdRowsLookup[row.id] = row.model;
281
- updatedIdToIdLookup[row.id] = row.id;
282
- updatedTree[row.id] = rowTreeNodeConfig;
283
- });
286
+ dataRowIdToModelLookup[rowId] = rowModel;
287
+ dataRowIdToIdLookup[rowId] = rowId;
288
+ tree[rowId] = rowTreeNodeConfig;
289
+ }
290
+
291
+ tree[GRID_ROOT_GROUP_ID] = _extends({}, rootGroup, {
292
+ children: rootGroupChildren
293
+ }); // Removes potential remaining skeleton rows from the dataRowIds.
294
+
295
+ const dataRowIds = rootGroupChildren.filter(childId => tree[childId].type === 'leaf');
284
296
  apiRef.current.setState(state => _extends({}, state, {
285
297
  rows: _extends({}, state.rows, {
286
- idRowsLookup: updatedIdRowsLookup,
287
- idToIdLookup: updatedIdToIdLookup,
288
- tree: updatedTree,
289
- ids: updatedRows
298
+ dataRowIdToModelLookup,
299
+ dataRowIdToIdLookup,
300
+ dataRowIds,
301
+ tree
290
302
  })
291
303
  }));
292
304
  apiRef.current.publishEvent('rowsSet');
@@ -316,7 +328,12 @@ export const useGridRows = (apiRef, props) => {
316
328
  if (apiRef.current.unstable_caches.rows.rowsBeforePartialUpdates === props.rows) {
317
329
  // The `props.rows` did not change since the last row grouping
318
330
  // We can use the current rows cache which contains the partial updates done recently.
319
- cache = apiRef.current.unstable_caches.rows;
331
+ cache = _extends({}, apiRef.current.unstable_caches.rows, {
332
+ updates: {
333
+ type: 'full',
334
+ rows: gridDataRowIdsSelector(apiRef)
335
+ }
336
+ });
320
337
  } else {
321
338
  // The `props.rows` has changed since the last row grouping
322
339
  // We must use the new `props.rows` on the new grouping
@@ -328,7 +345,10 @@ export const useGridRows = (apiRef, props) => {
328
345
  });
329
346
  }
330
347
 
331
- throttledRowsChange(cache, false);
348
+ throttledRowsChange({
349
+ cache,
350
+ throttle: false
351
+ });
332
352
  }, [logger, apiRef, props.rows, props.getRowId, props.loading, throttledRowsChange]);
333
353
  const handleStrategyProcessorChange = React.useCallback(methodName => {
334
354
  if (methodName === 'rowTreeCreation') {
@@ -349,12 +369,26 @@ export const useGridRows = (apiRef, props) => {
349
369
  */
350
370
 
351
371
  const applyHydrateRowsProcessor = React.useCallback(() => {
352
- apiRef.current.setState(state => _extends({}, state, {
353
- rows: _extends({}, state.rows, apiRef.current.unstable_applyPipeProcessors('hydrateRows', state.rows.groupingResponseBeforeRowHydration))
354
- }));
372
+ apiRef.current.setState(state => {
373
+ const response = apiRef.current.unstable_applyPipeProcessors('hydrateRows', {
374
+ tree: gridRowTreeSelector(state, apiRef.current.instanceId),
375
+ treeDepths: gridRowTreeDepthsSelector(state, apiRef.current.instanceId),
376
+ dataRowIds: gridDataRowIdsSelector(state, apiRef.current.instanceId),
377
+ dataRowIdToModelLookup: gridRowsLookupSelector(state, apiRef.current.instanceId),
378
+ dataRowIdToIdLookup: gridRowsDataRowIdToIdLookupSelector(state, apiRef.current.instanceId)
379
+ });
380
+ return _extends({}, state, {
381
+ rows: _extends({}, state.rows, response, {
382
+ totalTopLevelRowCount: getTopLevelRowCount({
383
+ tree: response.tree,
384
+ rowCountProp: props.rowCount
385
+ })
386
+ })
387
+ });
388
+ });
355
389
  apiRef.current.publishEvent('rowsSet');
356
390
  apiRef.current.forceUpdate();
357
- }, [apiRef]);
391
+ }, [apiRef, props.rowCount]);
358
392
  useGridRegisterPipeApplier(apiRef, 'hydrateRows', applyHydrateRowsProcessor);
359
393
  useGridApiMethod(apiRef, rowApi, 'GridRowApi');
360
394
  /**
@@ -396,10 +430,13 @@ export const useGridRows = (apiRef, props) => {
396
430
  }
397
431
 
398
432
  logger.debug(`Updating all rows, new length ${props.rows.length}`);
399
- throttledRowsChange(createRowsInternalCache({
400
- rows: props.rows,
401
- getRowId: props.getRowId,
402
- loading: props.loading
403
- }), false);
433
+ throttledRowsChange({
434
+ cache: createRowsInternalCache({
435
+ rows: props.rows,
436
+ getRowId: props.getRowId,
437
+ loading: props.loading
438
+ }),
439
+ throttle: false
440
+ });
404
441
  }, [props.rows, props.rowCount, props.getRowId, props.loading, logger, throttledRowsChange, apiRef]);
405
442
  };
@@ -1,40 +1,92 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
1
2
  import { GRID_DEFAULT_STRATEGY, useGridRegisterStrategyProcessor } from '../../core/strategyProcessing';
3
+ import { buildRootGroup, GRID_ROOT_GROUP_ID } from './gridRowsUtils';
2
4
 
3
- const flatRowTreeCreationMethod = ({
4
- ids,
5
- idRowsLookup,
6
- idToIdLookup,
7
- previousTree
5
+ const createFlatRowTree = rows => {
6
+ const tree = {
7
+ [GRID_ROOT_GROUP_ID]: _extends({}, buildRootGroup(), {
8
+ children: rows
9
+ })
10
+ };
11
+
12
+ for (let i = 0; i < rows.length; i += 1) {
13
+ const rowId = rows[i];
14
+ tree[rowId] = {
15
+ id: rowId,
16
+ depth: 0,
17
+ parent: GRID_ROOT_GROUP_ID,
18
+ type: 'leaf',
19
+ groupingKey: null
20
+ };
21
+ }
22
+
23
+ return {
24
+ groupingName: GRID_DEFAULT_STRATEGY,
25
+ tree,
26
+ treeDepths: {
27
+ 0: rows.length
28
+ },
29
+ dataRowIds: rows
30
+ };
31
+ };
32
+
33
+ const updateFlatRowTree = ({
34
+ previousTree,
35
+ actions
8
36
  }) => {
9
- const tree = {};
10
-
11
- for (let i = 0; i < ids.length; i += 1) {
12
- const rowId = ids[i];
13
-
14
- if (previousTree && previousTree[rowId] && previousTree[rowId].depth === 0 && previousTree[rowId].parent == null && // pinned row can be unpinned
15
- !previousTree[rowId].isPinned) {
16
- tree[rowId] = previousTree[rowId];
17
- } else {
18
- tree[rowId] = {
19
- id: rowId,
20
- depth: 0,
21
- parent: null,
22
- groupingKey: '',
23
- groupingField: null
24
- };
25
- }
37
+ const tree = _extends({}, previousTree);
38
+
39
+ const idsToRemoveFromRootGroup = {};
40
+
41
+ for (let i = 0; i < actions.remove.length; i += 1) {
42
+ const idToDelete = actions.remove[i];
43
+ idsToRemoveFromRootGroup[idToDelete] = true;
44
+ delete tree[idToDelete];
45
+ }
46
+
47
+ for (let i = 0; i < actions.insert.length; i += 1) {
48
+ const idToInsert = actions.insert[i];
49
+ tree[idToInsert] = {
50
+ id: idToInsert,
51
+ depth: 0,
52
+ parent: GRID_ROOT_GROUP_ID,
53
+ type: 'leaf',
54
+ groupingKey: null
55
+ };
56
+ } // TODO rows v6: Support row unpinning
57
+
58
+
59
+ const rootGroup = tree[GRID_ROOT_GROUP_ID];
60
+ let rootGroupChildren = [...rootGroup.children, ...actions.insert];
61
+
62
+ if (Object.values(idsToRemoveFromRootGroup).length) {
63
+ rootGroupChildren = rootGroupChildren.filter(id => !idsToRemoveFromRootGroup[id]);
26
64
  }
27
65
 
66
+ tree[GRID_ROOT_GROUP_ID] = _extends({}, rootGroup, {
67
+ children: rootGroupChildren
68
+ });
28
69
  return {
29
70
  groupingName: GRID_DEFAULT_STRATEGY,
30
71
  tree,
31
- treeDepth: 1,
32
- idRowsLookup,
33
- idToIdLookup,
34
- ids
72
+ treeDepths: {
73
+ 0: rootGroupChildren.length
74
+ },
75
+ dataRowIds: rootGroupChildren
35
76
  };
36
77
  };
37
78
 
79
+ const flatRowTreeCreationMethod = params => {
80
+ if (params.updates.type === 'full') {
81
+ return createFlatRowTree(params.updates.rows);
82
+ }
83
+
84
+ return updateFlatRowTree({
85
+ previousTree: params.previousTree,
86
+ actions: params.updates.actions
87
+ });
88
+ };
89
+
38
90
  export const useGridRowsPreProcessors = apiRef => {
39
91
  useGridRegisterStrategyProcessor(apiRef, GRID_DEFAULT_STRATEGY, 'rowTreeCreation', flatRowTreeCreationMethod);
40
92
  };
@@ -113,7 +113,7 @@ export const useGridSelection = (apiRef, props) => {
113
113
 
114
114
  const rowNode = apiRef.current.getRowNode(id);
115
115
 
116
- if (rowNode?.position === 'footer' || rowNode?.isPinned) {
116
+ if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow') {
117
117
  return false;
118
118
  }
119
119
 
@@ -265,7 +265,7 @@ export const useGridSelection = (apiRef, props) => {
265
265
  }
266
266
  }
267
267
 
268
- if (params.rowNode.isPinned) {
268
+ if (params.rowNode.type === 'pinnedRow') {
269
269
  return;
270
270
  }
271
271
 
@@ -17,9 +17,10 @@ export const gridSortedRowIdsSelector = createSelector(gridSortingStateSelector,
17
17
  * @category Sorting
18
18
  */
19
19
 
20
- export const gridSortedRowEntriesSelector = createSelector(gridSortedRowIdsSelector, gridRowsLookupSelector, (sortedIds, idRowsLookup) => sortedIds.map(id => ({
20
+ export const gridSortedRowEntriesSelector = createSelector(gridSortedRowIdsSelector, gridRowsLookupSelector, // TODO rows v6: Is this the best approach ?
21
+ (sortedIds, idRowsLookup) => sortedIds.map(id => ({
21
22
  id,
22
- model: idRowsLookup[id]
23
+ model: idRowsLookup[id] ?? {}
23
24
  })));
24
25
  /**
25
26
  * Get the current sorting model.
@@ -1,17 +1,17 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { GridFeatureModeConstant } from '../../../models/gridFeatureMode';
4
3
  import { isEnterKey } from '../../../utils/keyboardUtils';
5
4
  import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
6
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
7
6
  import { useGridLogger } from '../../utils/useGridLogger';
8
7
  import { gridColumnLookupSelector } from '../columns/gridColumnsSelector';
9
8
  import { gridSortedRowEntriesSelector, gridSortedRowIdsSelector, gridSortModelSelector } from './gridSortingSelector';
10
- import { gridRowIdsSelector, gridRowTreeSelector } from '../rows';
9
+ import { GRID_ROOT_GROUP_ID, gridRowTreeSelector } from '../rows';
11
10
  import { useFirstRender } from '../../utils/useFirstRender';
12
11
  import { useGridRegisterStrategyProcessor, GRID_DEFAULT_STRATEGY } from '../../core/strategyProcessing';
13
12
  import { buildAggregatedSortingApplier, mergeStateWithSortModel, getNextGridSortDirection, sanitizeSortModel } from './gridSortingUtils';
14
13
  import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
14
+ import { getTreeNodeDescendants } from '../rows/gridRowsUtils';
15
15
  export const sortingStateInitializer = (state, props) => {
16
16
  const sortModel = props.sortModel ?? props.initialState?.sorting?.sortModel ?? [];
17
17
  return _extends({}, state, {
@@ -74,11 +74,11 @@ export const useGridSorting = (apiRef, props) => {
74
74
 
75
75
  const applySorting = React.useCallback(() => {
76
76
  apiRef.current.setState(state => {
77
- if (props.sortingMode === GridFeatureModeConstant.server) {
77
+ if (props.sortingMode === 'server') {
78
78
  logger.debug('Skipping sorting rows as sortingMode = server');
79
79
  return _extends({}, state, {
80
80
  sorting: _extends({}, state.sorting, {
81
- sortedRows: gridRowIdsSelector(state, apiRef.current.instanceId)
81
+ sortedRows: getTreeNodeDescendants(gridRowTreeSelector(apiRef), GRID_ROOT_GROUP_ID, false)
82
82
  })
83
83
  });
84
84
  }
@@ -178,38 +178,14 @@ export const useGridSorting = (apiRef, props) => {
178
178
  }, [apiRef, props.disableMultipleColumnsSorting]);
179
179
  const flatSortingMethod = React.useCallback(params => {
180
180
  const rowTree = gridRowTreeSelector(apiRef);
181
+ const rootGroupNode = rowTree[GRID_ROOT_GROUP_ID];
182
+ const sortedChildren = params.sortRowList ? params.sortRowList(rootGroupNode.children.map(childId => rowTree[childId])) : [...rootGroupNode.children];
181
183
 
182
- if (!params.sortRowList) {
183
- const bodyRowIds = [];
184
- const footerRowIds = [];
185
- gridRowIdsSelector(apiRef).forEach(rowId => {
186
- if (rowTree[rowId].isPinned) {
187
- return;
188
- }
189
-
190
- if (rowTree[rowId].position === 'footer') {
191
- footerRowIds.push(rowId);
192
- } else {
193
- bodyRowIds.push(rowId);
194
- }
195
- });
196
- return [...bodyRowIds, ...footerRowIds];
184
+ if (rootGroupNode.footerId != null) {
185
+ sortedChildren.push(rootGroupNode.footerId);
197
186
  }
198
187
 
199
- const bodyRows = [];
200
- const footerRowIds = [];
201
- Object.values(rowTree).forEach(rowNode => {
202
- if (rowNode.isPinned) {
203
- return;
204
- }
205
-
206
- if (rowNode.position === 'footer') {
207
- footerRowIds.push(rowNode.id);
208
- } else {
209
- bodyRows.push(rowNode);
210
- }
211
- });
212
- return [...params.sortRowList(bodyRows), ...footerRowIds];
188
+ return sortedChildren;
213
189
  }, [apiRef]);
214
190
  useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
215
191
  useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);