@mui/x-data-grid 7.17.0 → 7.19.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 (203) hide show
  1. package/CHANGELOG.md +208 -5
  2. package/DataGrid/DataGrid.js +16 -1
  3. package/DataGrid/useDataGridComponent.js +3 -0
  4. package/DataGrid/useDataGridProps.js +2 -1
  5. package/components/GridRow.js +1 -0
  6. package/components/cell/GridCell.js +33 -9
  7. package/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
  8. package/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
  9. package/components/columnSelection/GridHeaderCheckbox.d.ts +1 -1
  10. package/components/containers/GridRoot.js +1 -1
  11. package/components/containers/GridRootStyles.js +32 -23
  12. package/components/containers/GridToolbarContainer.js +1 -1
  13. package/components/menu/GridMenu.js +1 -1
  14. package/components/panel/GridPanel.d.ts +1 -1
  15. package/components/panel/GridPanel.js +1 -1
  16. package/components/panel/GridPanelContent.js +1 -1
  17. package/components/panel/GridPanelFooter.js +1 -1
  18. package/components/panel/GridPanelHeader.js +1 -1
  19. package/components/panel/GridPanelWrapper.js +1 -1
  20. package/components/panel/filterPanel/filterPanelUtils.d.ts +1 -1
  21. package/components/toolbar/GridToolbarQuickFilter.js +1 -1
  22. package/components/virtualization/GridBottomContainer.d.ts +1 -1
  23. package/components/virtualization/GridBottomContainer.js +18 -1
  24. package/components/virtualization/GridMainContainer.js +3 -1
  25. package/components/virtualization/GridTopContainer.d.ts +1 -1
  26. package/components/virtualization/GridTopContainer.js +1 -1
  27. package/components/virtualization/GridVirtualScrollbar.js +1 -7
  28. package/components/virtualization/GridVirtualScroller.js +1 -0
  29. package/components/virtualization/GridVirtualScrollerFiller.js +3 -4
  30. package/hooks/features/columnGrouping/gridColumnGroupsSelector.d.ts +4 -4
  31. package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -2
  32. package/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -11
  33. package/hooks/features/columnResize/columnResizeSelector.d.ts +1 -1
  34. package/hooks/features/columnResize/useGridColumnResize.js +6 -6
  35. package/hooks/features/columns/gridColumnsSelector.d.ts +12 -12
  36. package/hooks/features/columns/gridColumnsUtils.js +3 -2
  37. package/hooks/features/density/densitySelector.d.ts +1 -1
  38. package/hooks/features/dimensions/gridDimensionsApi.d.ts +4 -0
  39. package/hooks/features/dimensions/useGridDimensions.d.ts +1 -1
  40. package/hooks/features/dimensions/useGridDimensions.js +4 -1
  41. package/hooks/features/editing/useGridCellEditing.js +3 -19
  42. package/hooks/features/editing/useGridRowEditing.js +7 -2
  43. package/hooks/features/editing/utils.d.ts +2 -0
  44. package/hooks/features/editing/utils.js +15 -0
  45. package/hooks/features/export/useGridPrintExport.js +2 -1
  46. package/hooks/features/filter/gridFilterSelector.d.ts +17 -17
  47. package/hooks/features/focus/gridFocusStateSelector.d.ts +8 -8
  48. package/hooks/features/focus/useGridFocus.js +2 -1
  49. package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.d.ts +3 -3
  50. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +10 -46
  51. package/hooks/features/keyboardNavigation/utils.d.ts +17 -0
  52. package/hooks/features/keyboardNavigation/utils.js +58 -0
  53. package/hooks/features/pagination/gridPaginationSelector.d.ts +9 -9
  54. package/hooks/features/rowSelection/gridRowSelectionSelector.d.ts +3 -3
  55. package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
  56. package/hooks/features/rowSelection/useGridRowSelection.js +105 -29
  57. package/hooks/features/rowSelection/utils.d.ts +10 -0
  58. package/hooks/features/rowSelection/utils.js +156 -1
  59. package/hooks/features/rows/gridRowSpanningSelectors.d.ts +4 -0
  60. package/hooks/features/rows/gridRowSpanningSelectors.js +5 -0
  61. package/hooks/features/rows/gridRowSpanningUtils.d.ts +10 -0
  62. package/hooks/features/rows/gridRowSpanningUtils.js +42 -0
  63. package/hooks/features/rows/gridRowsSelector.d.ts +14 -14
  64. package/hooks/features/rows/useGridRowSpanning.d.ts +27 -0
  65. package/hooks/features/rows/useGridRowSpanning.js +257 -0
  66. package/hooks/features/rows/useGridRows.d.ts +1 -1
  67. package/hooks/features/rows/useGridRows.js +7 -1
  68. package/hooks/features/scroll/useGridScroll.js +19 -19
  69. package/hooks/features/sorting/gridSortingSelector.d.ts +4 -4
  70. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +5 -5
  71. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
  72. package/hooks/features/virtualization/useGridVirtualScroller.js +17 -7
  73. package/hooks/utils/useGridApiEventHandler.js +0 -1
  74. package/hooks/utils/useGridVisibleRows.d.ts +2 -2
  75. package/index.js +1 -1
  76. package/internals/index.d.ts +2 -0
  77. package/internals/index.js +2 -0
  78. package/locales/bgBG.js +8 -9
  79. package/locales/deDE.js +4 -4
  80. package/locales/frFR.js +4 -4
  81. package/locales/hrHR.d.ts +1 -1
  82. package/locales/hrHR.js +69 -46
  83. package/locales/jaJP.js +1 -2
  84. package/locales/ptPT.d.ts +1 -1
  85. package/locales/ptPT.js +4 -4
  86. package/locales/viVN.js +20 -20
  87. package/locales/zhHK.d.ts +1 -1
  88. package/models/colDef/gridColDef.d.ts +4 -0
  89. package/models/gridRowSelectionModel.d.ts +4 -0
  90. package/models/gridStateCommunity.d.ts +2 -0
  91. package/models/props/DataGridProps.d.ts +30 -1
  92. package/modern/DataGrid/DataGrid.js +16 -1
  93. package/modern/DataGrid/useDataGridComponent.js +3 -0
  94. package/modern/DataGrid/useDataGridProps.js +2 -1
  95. package/modern/components/GridRow.js +1 -0
  96. package/modern/components/cell/GridCell.js +33 -9
  97. package/modern/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
  98. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
  99. package/modern/components/containers/GridRoot.js +1 -1
  100. package/modern/components/containers/GridRootStyles.js +32 -23
  101. package/modern/components/containers/GridToolbarContainer.js +1 -1
  102. package/modern/components/menu/GridMenu.js +1 -1
  103. package/modern/components/panel/GridPanel.js +1 -1
  104. package/modern/components/panel/GridPanelContent.js +1 -1
  105. package/modern/components/panel/GridPanelFooter.js +1 -1
  106. package/modern/components/panel/GridPanelHeader.js +1 -1
  107. package/modern/components/panel/GridPanelWrapper.js +1 -1
  108. package/modern/components/toolbar/GridToolbarQuickFilter.js +1 -1
  109. package/modern/components/virtualization/GridBottomContainer.js +18 -1
  110. package/modern/components/virtualization/GridMainContainer.js +3 -1
  111. package/modern/components/virtualization/GridTopContainer.js +1 -1
  112. package/modern/components/virtualization/GridVirtualScrollbar.js +1 -7
  113. package/modern/components/virtualization/GridVirtualScroller.js +1 -0
  114. package/modern/components/virtualization/GridVirtualScrollerFiller.js +3 -4
  115. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -11
  116. package/modern/hooks/features/columnResize/useGridColumnResize.js +6 -6
  117. package/modern/hooks/features/columns/gridColumnsUtils.js +3 -2
  118. package/modern/hooks/features/dimensions/useGridDimensions.js +4 -1
  119. package/modern/hooks/features/editing/useGridCellEditing.js +3 -19
  120. package/modern/hooks/features/editing/useGridRowEditing.js +7 -2
  121. package/modern/hooks/features/editing/utils.js +15 -0
  122. package/modern/hooks/features/export/useGridPrintExport.js +2 -1
  123. package/modern/hooks/features/focus/useGridFocus.js +2 -1
  124. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +10 -46
  125. package/modern/hooks/features/keyboardNavigation/utils.js +58 -0
  126. package/modern/hooks/features/rowSelection/useGridRowSelection.js +105 -29
  127. package/modern/hooks/features/rowSelection/utils.js +156 -1
  128. package/modern/hooks/features/rows/gridRowSpanningSelectors.js +5 -0
  129. package/modern/hooks/features/rows/gridRowSpanningUtils.js +42 -0
  130. package/modern/hooks/features/rows/useGridRowSpanning.js +257 -0
  131. package/modern/hooks/features/rows/useGridRows.js +7 -1
  132. package/modern/hooks/features/scroll/useGridScroll.js +19 -19
  133. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +17 -7
  134. package/modern/hooks/utils/useGridApiEventHandler.js +0 -1
  135. package/modern/index.js +1 -1
  136. package/modern/internals/index.js +2 -0
  137. package/modern/locales/bgBG.js +8 -9
  138. package/modern/locales/deDE.js +4 -4
  139. package/modern/locales/frFR.js +4 -4
  140. package/modern/locales/hrHR.js +69 -46
  141. package/modern/locales/jaJP.js +1 -2
  142. package/modern/locales/ptPT.js +4 -4
  143. package/modern/locales/viVN.js +20 -20
  144. package/modern/utils/createSelector.js +6 -0
  145. package/modern/utils/domUtils.js +12 -12
  146. package/node/DataGrid/DataGrid.js +16 -1
  147. package/node/DataGrid/useDataGridComponent.js +3 -0
  148. package/node/DataGrid/useDataGridProps.js +2 -1
  149. package/node/components/GridRow.js +1 -0
  150. package/node/components/cell/GridCell.js +33 -9
  151. package/node/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
  152. package/node/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
  153. package/node/components/containers/GridRoot.js +1 -1
  154. package/node/components/containers/GridRootStyles.js +32 -23
  155. package/node/components/containers/GridToolbarContainer.js +1 -1
  156. package/node/components/menu/GridMenu.js +1 -1
  157. package/node/components/panel/GridPanel.js +1 -1
  158. package/node/components/panel/GridPanelContent.js +1 -1
  159. package/node/components/panel/GridPanelFooter.js +1 -1
  160. package/node/components/panel/GridPanelHeader.js +1 -1
  161. package/node/components/panel/GridPanelWrapper.js +1 -1
  162. package/node/components/toolbar/GridToolbarQuickFilter.js +1 -1
  163. package/node/components/virtualization/GridBottomContainer.js +18 -1
  164. package/node/components/virtualization/GridMainContainer.js +3 -1
  165. package/node/components/virtualization/GridTopContainer.js +1 -1
  166. package/node/components/virtualization/GridVirtualScrollbar.js +1 -7
  167. package/node/components/virtualization/GridVirtualScroller.js +1 -0
  168. package/node/components/virtualization/GridVirtualScrollerFiller.js +3 -4
  169. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -11
  170. package/node/hooks/features/columnResize/useGridColumnResize.js +6 -6
  171. package/node/hooks/features/columns/gridColumnsUtils.js +3 -2
  172. package/node/hooks/features/dimensions/useGridDimensions.js +4 -1
  173. package/node/hooks/features/editing/useGridCellEditing.js +3 -19
  174. package/node/hooks/features/editing/useGridRowEditing.js +7 -2
  175. package/node/hooks/features/editing/utils.js +22 -0
  176. package/node/hooks/features/export/useGridPrintExport.js +2 -1
  177. package/node/hooks/features/focus/useGridFocus.js +2 -1
  178. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +16 -53
  179. package/node/hooks/features/keyboardNavigation/utils.js +68 -0
  180. package/node/hooks/features/rowSelection/useGridRowSelection.js +102 -26
  181. package/node/hooks/features/rowSelection/utils.js +160 -1
  182. package/node/hooks/features/rows/gridRowSpanningSelectors.js +11 -0
  183. package/node/hooks/features/rows/gridRowSpanningUtils.js +52 -0
  184. package/node/hooks/features/rows/useGridRowSpanning.js +267 -0
  185. package/node/hooks/features/rows/useGridRows.js +7 -1
  186. package/node/hooks/features/scroll/useGridScroll.js +19 -19
  187. package/node/hooks/features/virtualization/useGridVirtualScroller.js +17 -7
  188. package/node/hooks/utils/useGridApiEventHandler.js +0 -1
  189. package/node/index.js +1 -1
  190. package/node/internals/index.js +38 -15
  191. package/node/locales/bgBG.js +8 -9
  192. package/node/locales/deDE.js +4 -4
  193. package/node/locales/frFR.js +4 -4
  194. package/node/locales/hrHR.js +69 -46
  195. package/node/locales/jaJP.js +1 -2
  196. package/node/locales/ptPT.js +4 -4
  197. package/node/locales/viVN.js +20 -20
  198. package/node/utils/createSelector.js +6 -0
  199. package/node/utils/domUtils.js +12 -12
  200. package/package.json +3 -3
  201. package/utils/createSelector.js +6 -0
  202. package/utils/domUtils.d.ts +4 -4
  203. package/utils/domUtils.js +12 -12
@@ -0,0 +1,257 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import useLazyRef from '@mui/utils/useLazyRef';
4
+ import { gridVisibleColumnDefinitionsSelector } from "../columns/gridColumnsSelector.js";
5
+ import { useGridVisibleRows } from "../../utils/useGridVisibleRows.js";
6
+ import { gridRenderContextSelector } from "../virtualization/gridVirtualizationSelectors.js";
7
+ import { useGridSelector } from "../../utils/useGridSelector.js";
8
+ import { getUnprocessedRange, isRowRangeUpdated, isRowContextInitialized, getCellValue } from "./gridRowSpanningUtils.js";
9
+ const EMPTY_STATE = {
10
+ spannedCells: {},
11
+ hiddenCells: {},
12
+ hiddenCellOriginMap: {}
13
+ };
14
+ const EMPTY_RANGE = {
15
+ firstRowIndex: 0,
16
+ lastRowIndex: 0
17
+ };
18
+ const skippedFields = new Set(['__check__', '__reorder__', '__detail_panel_toggle__']);
19
+ /**
20
+ * Default number of rows to process during state initialization to avoid flickering.
21
+ * Number `20` is arbitrarily chosen to be large enough to cover most of the cases without
22
+ * compromising performance.
23
+ */
24
+ const DEFAULT_ROWS_TO_PROCESS = 20;
25
+ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToProcess, resetState, processedRange) => {
26
+ const spannedCells = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.spannedCells);
27
+ const hiddenCells = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.hiddenCells);
28
+ const hiddenCellOriginMap = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.hiddenCellOriginMap);
29
+ if (resetState) {
30
+ processedRange = EMPTY_RANGE;
31
+ }
32
+ colDefs.forEach(colDef => {
33
+ if (skippedFields.has(colDef.field)) {
34
+ return;
35
+ }
36
+ for (let index = rangeToProcess.firstRowIndex; index <= rangeToProcess.lastRowIndex; index += 1) {
37
+ const row = visibleRows[index];
38
+ if (hiddenCells[row.id]?.[colDef.field]) {
39
+ continue;
40
+ }
41
+ const cellValue = getCellValue(row.model, colDef, apiRef);
42
+ if (cellValue == null) {
43
+ continue;
44
+ }
45
+ let spannedRowId = row.id;
46
+ let spannedRowIndex = index;
47
+ let rowSpan = 0;
48
+
49
+ // For first index, also scan in the previous rows to handle the reset state case e.g by sorting
50
+ const backwardsHiddenCells = [];
51
+ if (index === rangeToProcess.firstRowIndex) {
52
+ let prevIndex = index - 1;
53
+ const prevRowEntry = visibleRows[prevIndex];
54
+ while (prevIndex >= range.firstRowIndex && getCellValue(prevRowEntry.model, colDef, apiRef) === cellValue) {
55
+ const currentRow = visibleRows[prevIndex + 1];
56
+ if (hiddenCells[currentRow.id]) {
57
+ hiddenCells[currentRow.id][colDef.field] = true;
58
+ } else {
59
+ hiddenCells[currentRow.id] = {
60
+ [colDef.field]: true
61
+ };
62
+ }
63
+ backwardsHiddenCells.push(index);
64
+ rowSpan += 1;
65
+ spannedRowId = prevRowEntry.id;
66
+ spannedRowIndex = prevIndex;
67
+ prevIndex -= 1;
68
+ }
69
+ }
70
+ backwardsHiddenCells.forEach(hiddenCellIndex => {
71
+ if (hiddenCellOriginMap[hiddenCellIndex]) {
72
+ hiddenCellOriginMap[hiddenCellIndex][colDef.field] = spannedRowIndex;
73
+ } else {
74
+ hiddenCellOriginMap[hiddenCellIndex] = {
75
+ [colDef.field]: spannedRowIndex
76
+ };
77
+ }
78
+ });
79
+
80
+ // Scan the next rows
81
+ let relativeIndex = index + 1;
82
+ while (relativeIndex <= range.lastRowIndex && visibleRows[relativeIndex] && getCellValue(visibleRows[relativeIndex].model, colDef, apiRef) === cellValue) {
83
+ const currentRow = visibleRows[relativeIndex];
84
+ if (hiddenCells[currentRow.id]) {
85
+ hiddenCells[currentRow.id][colDef.field] = true;
86
+ } else {
87
+ hiddenCells[currentRow.id] = {
88
+ [colDef.field]: true
89
+ };
90
+ }
91
+ if (hiddenCellOriginMap[relativeIndex]) {
92
+ hiddenCellOriginMap[relativeIndex][colDef.field] = spannedRowIndex;
93
+ } else {
94
+ hiddenCellOriginMap[relativeIndex] = {
95
+ [colDef.field]: spannedRowIndex
96
+ };
97
+ }
98
+ relativeIndex += 1;
99
+ rowSpan += 1;
100
+ }
101
+ if (rowSpan > 0) {
102
+ if (spannedCells[spannedRowId]) {
103
+ spannedCells[spannedRowId][colDef.field] = rowSpan + 1;
104
+ } else {
105
+ spannedCells[spannedRowId] = {
106
+ [colDef.field]: rowSpan + 1
107
+ };
108
+ }
109
+ }
110
+ }
111
+ processedRange = {
112
+ firstRowIndex: Math.min(processedRange.firstRowIndex, rangeToProcess.firstRowIndex),
113
+ lastRowIndex: Math.max(processedRange.lastRowIndex, rangeToProcess.lastRowIndex)
114
+ };
115
+ });
116
+ return {
117
+ spannedCells,
118
+ hiddenCells,
119
+ hiddenCellOriginMap,
120
+ processedRange
121
+ };
122
+ };
123
+
124
+ /**
125
+ * @requires columnsStateInitializer (method) - should be initialized before
126
+ * @requires rowsStateInitializer (method) - should be initialized before
127
+ * @requires filterStateInitializer (method) - should be initialized before
128
+ */
129
+ export const rowSpanningStateInitializer = (state, props, apiRef) => {
130
+ if (props.unstable_rowSpanning) {
131
+ const rowIds = state.rows.dataRowIds || [];
132
+ const orderedFields = state.columns.orderedFields || [];
133
+ const dataRowIdToModelLookup = state.rows.dataRowIdToModelLookup;
134
+ const columnsLookup = state.columns.lookup;
135
+ const isFilteringPending = Boolean(state.filter.filterModel.items.length) || Boolean(state.filter.filterModel.quickFilterValues?.length);
136
+ if (!rowIds.length || !orderedFields.length || !dataRowIdToModelLookup || !columnsLookup || isFilteringPending) {
137
+ return _extends({}, state, {
138
+ rowSpanning: EMPTY_STATE
139
+ });
140
+ }
141
+ const rangeToProcess = {
142
+ firstRowIndex: 0,
143
+ lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS - 1, Math.max(rowIds.length - 1, 0))
144
+ };
145
+ const rows = rowIds.map(id => ({
146
+ id,
147
+ model: dataRowIdToModelLookup[id]
148
+ }));
149
+ const colDefs = orderedFields.map(field => columnsLookup[field]);
150
+ const {
151
+ spannedCells,
152
+ hiddenCells,
153
+ hiddenCellOriginMap
154
+ } = computeRowSpanningState(apiRef, colDefs, rows, rangeToProcess, rangeToProcess, true, EMPTY_RANGE);
155
+ return _extends({}, state, {
156
+ rowSpanning: {
157
+ spannedCells,
158
+ hiddenCells,
159
+ hiddenCellOriginMap
160
+ }
161
+ });
162
+ }
163
+ return _extends({}, state, {
164
+ rowSpanning: EMPTY_STATE
165
+ });
166
+ };
167
+ export const useGridRowSpanning = (apiRef, props) => {
168
+ const {
169
+ range,
170
+ rows: visibleRows
171
+ } = useGridVisibleRows(apiRef, props);
172
+ const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
173
+ const colDefs = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
174
+ const processedRange = useLazyRef(() => {
175
+ return Object.keys(apiRef.current.state.rowSpanning.spannedCells).length > 0 ? {
176
+ firstRowIndex: 0,
177
+ lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS - 1, Math.max(apiRef.current.state.rows.dataRowIds.length - 1, 0))
178
+ } : EMPTY_RANGE;
179
+ });
180
+ const lastRange = React.useRef(EMPTY_RANGE);
181
+ const updateRowSpanningState = React.useCallback(
182
+ // A reset needs to occur when:
183
+ // - The `unstable_rowSpanning` prop is updated (feature flag)
184
+ // - The filtering is applied
185
+ // - The sorting is applied
186
+ // - The `paginationModel` is updated
187
+ // - The rows are updated
188
+ (resetState = true) => {
189
+ if (!props.unstable_rowSpanning) {
190
+ if (apiRef.current.state.rowSpanning !== EMPTY_STATE) {
191
+ apiRef.current.setState(state => _extends({}, state, {
192
+ rowSpanning: EMPTY_STATE
193
+ }));
194
+ }
195
+ return;
196
+ }
197
+ if (range === null || !isRowContextInitialized(renderContext)) {
198
+ return;
199
+ }
200
+ if (resetState) {
201
+ processedRange.current = EMPTY_RANGE;
202
+ }
203
+ const rangeToProcess = getUnprocessedRange({
204
+ firstRowIndex: renderContext.firstRowIndex,
205
+ lastRowIndex: renderContext.lastRowIndex - 1
206
+ }, processedRange.current);
207
+ if (rangeToProcess === null) {
208
+ return;
209
+ }
210
+ const {
211
+ spannedCells,
212
+ hiddenCells,
213
+ hiddenCellOriginMap,
214
+ processedRange: newProcessedRange
215
+ } = computeRowSpanningState(apiRef, colDefs, visibleRows, range, rangeToProcess, resetState, processedRange.current);
216
+ processedRange.current = newProcessedRange;
217
+ const newSpannedCellsCount = Object.keys(spannedCells).length;
218
+ const newHiddenCellsCount = Object.keys(hiddenCells).length;
219
+ const currentSpannedCellsCount = Object.keys(apiRef.current.state.rowSpanning.spannedCells).length;
220
+ const currentHiddenCellsCount = Object.keys(apiRef.current.state.rowSpanning.hiddenCells).length;
221
+ const shouldUpdateState = resetState || newSpannedCellsCount !== currentSpannedCellsCount || newHiddenCellsCount !== currentHiddenCellsCount;
222
+ if (!shouldUpdateState) {
223
+ return;
224
+ }
225
+ apiRef.current.setState(state => {
226
+ return _extends({}, state, {
227
+ rowSpanning: {
228
+ spannedCells,
229
+ hiddenCells,
230
+ hiddenCellOriginMap
231
+ }
232
+ });
233
+ });
234
+ }, [apiRef, props.unstable_rowSpanning, range, renderContext, visibleRows, colDefs, processedRange]);
235
+ const prevRenderContext = React.useRef(renderContext);
236
+ const isFirstRender = React.useRef(true);
237
+ const shouldResetState = React.useRef(false);
238
+ React.useEffect(() => {
239
+ const firstRender = isFirstRender.current;
240
+ if (isFirstRender.current) {
241
+ isFirstRender.current = false;
242
+ }
243
+ if (range && lastRange.current && isRowRangeUpdated(range, lastRange.current)) {
244
+ lastRange.current = range;
245
+ shouldResetState.current = true;
246
+ }
247
+ if (!firstRender && prevRenderContext.current !== renderContext) {
248
+ if (isRowRangeUpdated(prevRenderContext.current, renderContext)) {
249
+ updateRowSpanningState(shouldResetState.current);
250
+ shouldResetState.current = false;
251
+ }
252
+ prevRenderContext.current = renderContext;
253
+ return;
254
+ }
255
+ updateRowSpanningState();
256
+ }, [updateRowSpanningState, renderContext, range, lastRange]);
257
+ };
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
+ import useLazyRef from '@mui/utils/useLazyRef';
3
4
  import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
4
5
  import { useGridLogger } from "../../utils/useGridLogger.js";
5
6
  import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridDataRowIdsSelector, gridRowsDataRowIdToIdLookupSelector, gridRowMaximumTreeDepthSelector, gridRowGroupsToFetchSelector } from "./gridRowsSelector.js";
@@ -367,11 +368,16 @@ export const useGridRows = (apiRef, props) => {
367
368
  throttle: false
368
369
  });
369
370
  }, [logger, apiRef, props.rows, props.getRowId, props.loading, props.rowCount, throttledRowsChange]);
371
+ const previousDataSource = useLazyRef(() => props.unstable_dataSource);
370
372
  const handleStrategyProcessorChange = React.useCallback(methodName => {
373
+ if (props.unstable_dataSource && props.unstable_dataSource !== previousDataSource.current) {
374
+ previousDataSource.current = props.unstable_dataSource;
375
+ return;
376
+ }
371
377
  if (methodName === 'rowTreeCreation') {
372
378
  groupRows();
373
379
  }
374
- }, [groupRows]);
380
+ }, [groupRows, previousDataSource, props.unstable_dataSource]);
375
381
  const handleStrategyActivityChange = React.useCallback(() => {
376
382
  // `rowTreeCreation` is the only processor ran when `strategyAvailabilityChange` is fired.
377
383
  // All the other processors listen to `rowsSet` which will be published by the `groupRows` method below.
@@ -14,22 +14,22 @@ import { gridDimensionsSelector } from "../dimensions/index.js";
14
14
  // Similar to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
15
15
  function scrollIntoView(dimensions) {
16
16
  const {
17
- clientHeight,
18
- scrollTop,
19
- offsetHeight,
20
- offsetTop
17
+ containerSize,
18
+ scrollPosition,
19
+ elementSize,
20
+ elementOffset
21
21
  } = dimensions;
22
- const elementBottom = offsetTop + offsetHeight;
22
+ const elementEnd = elementOffset + elementSize;
23
23
  // Always scroll to top when cell is higher than viewport to avoid scroll jump
24
24
  // See https://github.com/mui/mui-x/issues/4513 and https://github.com/mui/mui-x/issues/4514
25
- if (offsetHeight > clientHeight) {
26
- return offsetTop;
25
+ if (elementSize > containerSize) {
26
+ return elementOffset;
27
27
  }
28
- if (elementBottom - clientHeight > scrollTop) {
29
- return elementBottom - clientHeight;
28
+ if (elementEnd - containerSize > scrollPosition) {
29
+ return elementEnd - containerSize;
30
30
  }
31
- if (offsetTop < scrollTop) {
32
- return offsetTop;
31
+ if (elementOffset < scrollPosition) {
32
+ return elementOffset;
33
33
  }
34
34
  return undefined;
35
35
  }
@@ -73,10 +73,10 @@ export const useGridScroll = (apiRef, props) => {
73
73
  }
74
74
  // When using RTL, `scrollLeft` becomes negative, so we must ensure that we only compare values.
75
75
  scrollCoordinates.left = scrollIntoView({
76
- clientHeight: dimensions.viewportInnerSize.width,
77
- scrollTop: Math.abs(virtualScrollerRef.current.scrollLeft),
78
- offsetHeight: cellWidth,
79
- offsetTop: columnPositions[params.colIndex]
76
+ containerSize: dimensions.viewportOuterSize.width,
77
+ scrollPosition: Math.abs(virtualScrollerRef.current.scrollLeft),
78
+ elementSize: cellWidth,
79
+ elementOffset: columnPositions[params.colIndex]
80
80
  });
81
81
  }
82
82
  if (params.rowIndex !== undefined) {
@@ -86,10 +86,10 @@ export const useGridScroll = (apiRef, props) => {
86
86
  const elementIndex = !props.pagination ? params.rowIndex : params.rowIndex - page * pageSize;
87
87
  const targetOffsetHeight = rowsMeta.positions[elementIndex + 1] ? rowsMeta.positions[elementIndex + 1] - rowsMeta.positions[elementIndex] : rowsMeta.currentPageTotalHeight - rowsMeta.positions[elementIndex];
88
88
  scrollCoordinates.top = scrollIntoView({
89
- clientHeight: dimensions.viewportInnerSize.height,
90
- scrollTop: virtualScrollerRef.current.scrollTop,
91
- offsetHeight: targetOffsetHeight,
92
- offsetTop: rowsMeta.positions[elementIndex]
89
+ containerSize: dimensions.viewportInnerSize.height,
90
+ scrollPosition: virtualScrollerRef.current.scrollTop,
91
+ elementSize: targetOffsetHeight,
92
+ elementOffset: rowsMeta.positions[elementIndex]
93
93
  });
94
94
  }
95
95
  scrollCoordinates = apiRef.current.unstable_applyPipeProcessors('scrollToIndexes', scrollCoordinates, params);
@@ -24,6 +24,7 @@ import { getFirstNonSpannedColumnToRender } from "../columns/gridColumnsUtils.js
24
24
  import { getMinimalContentHeight } from "../rows/gridRowsUtils.js";
25
25
  import { gridRenderContextSelector, gridVirtualizationRowEnabledSelector, gridVirtualizationColumnEnabledSelector } from "./gridVirtualizationSelectors.js";
26
26
  import { EMPTY_RENDER_CONTEXT } from "./useGridVirtualization.js";
27
+ import { gridRowSpanningHiddenCellsOriginMapSelector } from "../rows/gridRowSpanningSelectors.js";
27
28
  import { jsx as _jsx } from "react/jsx-runtime";
28
29
  const MINIMUM_COLUMN_WIDTH = 50;
29
30
  var ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
@@ -325,7 +326,7 @@ export const useGridVirtualScroller = () => {
325
326
  if (!isPinnedSection && frozenContext.current && rowIndexInPage >= frozenContext.current.firstRowIndex && rowIndexInPage < frozenContext.current.lastRowIndex) {
326
327
  currentRenderContext = frozenContext.current;
327
328
  }
328
- const offsetLeft = computeOffsetLeft(columnPositions, currentRenderContext, isRtl, pinnedColumns.left.length);
329
+ const offsetLeft = computeOffsetLeft(columnPositions, currentRenderContext, pinnedColumns.left.length);
329
330
  const showBottomBorder = isLastVisibleInSection && params.position === 'top';
330
331
  rows.push(/*#__PURE__*/_jsx(rootProps.slots.row, _extends({
331
332
  row: model,
@@ -353,7 +354,7 @@ export const useGridVirtualScroller = () => {
353
354
  if (panel) {
354
355
  rows.push(panel);
355
356
  }
356
- if (isLastVisible) {
357
+ if (params.position === undefined && isLastVisibleInSection) {
357
358
  rows.push(apiRef.current.getInfiniteLoadingTriggerElement?.({
358
359
  lastRowId: id
359
360
  }));
@@ -447,6 +448,7 @@ function inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns) {
447
448
  const dimensions = gridDimensionsSelector(apiRef.current.state);
448
449
  const currentPage = getVisibleRows(apiRef, rootProps);
449
450
  const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
451
+ const hiddenCellsOriginMap = gridRowSpanningHiddenCellsOriginMapSelector(apiRef);
450
452
  const lastRowId = apiRef.current.state.rows.dataRowIds.at(-1);
451
453
  const lastColumn = visibleColumns.at(-1);
452
454
  return {
@@ -467,7 +469,8 @@ function inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns) {
467
469
  rows: currentPage.rows,
468
470
  range: currentPage.range,
469
471
  pinnedColumns: gridVisiblePinnedColumnDefinitionsSelector(apiRef),
470
- visibleColumns
472
+ visibleColumns,
473
+ hiddenCellsOriginMap
471
474
  };
472
475
  }
473
476
  function computeRenderContext(inputs, scrollPosition, scrollCache) {
@@ -485,10 +488,18 @@ function computeRenderContext(inputs, scrollPosition, scrollCache) {
485
488
  if (inputs.enabledForRows) {
486
489
  // Clamp the value because the search may return an index out of bounds.
487
490
  // In the last index, this is not needed because Array.slice doesn't include it.
488
- const firstRowIndex = Math.min(getNearestIndexToRender(inputs, top, {
491
+ let firstRowIndex = Math.min(getNearestIndexToRender(inputs, top, {
489
492
  atStart: true,
490
493
  lastPosition: inputs.rowsMeta.positions[inputs.rowsMeta.positions.length - 1] + inputs.lastRowHeight
491
494
  }), inputs.rowsMeta.positions.length - 1);
495
+
496
+ // If any of the cells in the `firstRowIndex` is hidden due to an extended row span,
497
+ // Make sure the row from where the rowSpan is originated is visible.
498
+ const rowSpanHiddenCellOrigin = inputs.hiddenCellsOriginMap[firstRowIndex];
499
+ if (rowSpanHiddenCellOrigin) {
500
+ const minSpannedRowIndex = Math.min(...Object.values(rowSpanHiddenCellOrigin));
501
+ firstRowIndex = Math.min(firstRowIndex, minSpannedRowIndex);
502
+ }
492
503
  const lastRowIndex = inputs.autoHeight ? firstRowIndex + inputs.rows.length : getNearestIndexToRender(inputs, top + inputs.viewportInnerHeight);
493
504
  renderContext.firstRowIndex = firstRowIndex;
494
505
  renderContext.lastRowIndex = lastRowIndex;
@@ -642,9 +653,8 @@ export function areRenderContextsEqual(context1, context2) {
642
653
  }
643
654
  return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
644
655
  }
645
- export function computeOffsetLeft(columnPositions, renderContext, isRtl, pinnedLeftLength) {
646
- const factor = isRtl ? -1 : 1;
647
- const left = factor * (columnPositions[renderContext.firstColumnIndex] ?? 0) - (columnPositions[pinnedLeftLength] ?? 0);
656
+ export function computeOffsetLeft(columnPositions, renderContext, pinnedLeftLength) {
657
+ const left = (columnPositions[renderContext.firstColumnIndex] ?? 0) - (columnPositions[pinnedLeftLength] ?? 0);
648
658
  return Math.abs(left);
649
659
  }
650
660
  function directionForDelta(dx, dy) {
@@ -90,7 +90,6 @@ const optionsSubscriberOptions = {
90
90
  isFirst: true
91
91
  };
92
92
  export function useGridApiOptionHandler(apiRef, eventName, handler) {
93
- // Validate that only one per event name?
94
93
  useGridApiEventHandler(apiRef, eventName, handler, optionsSubscriberOptions);
95
94
  }
96
95
  export { GridSignature };
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.17.0
2
+ * @mui/x-data-grid v7.19.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -32,6 +32,7 @@ export { useGridPreferencesPanel, preferencePanelStateInitializer } from "../hoo
32
32
  export { useGridEditing, editingStateInitializer } from "../hooks/features/editing/useGridEditing.js";
33
33
  export { gridEditRowsStateSelector } from "../hooks/features/editing/gridEditingSelectors.js";
34
34
  export { useGridRows, rowsStateInitializer } from "../hooks/features/rows/useGridRows.js";
35
+ export { useGridRowSpanning, rowSpanningStateInitializer } from "../hooks/features/rows/useGridRowSpanning.js";
35
36
  export { useGridAriaAttributes } from "../hooks/utils/useGridAriaAttributes.js";
36
37
  export { useGridRowAriaAttributes } from "../hooks/features/rows/useGridRowAriaAttributes.js";
37
38
  export { useGridRowsPreProcessors } from "../hooks/features/rows/useGridRowsPreProcessors.js";
@@ -52,6 +53,7 @@ export { useGridStatePersistence } from "../hooks/features/statePersistence/useG
52
53
  export { useGridVirtualScroller, EMPTY_DETAIL_PANELS } from "../hooks/features/virtualization/useGridVirtualScroller.js";
53
54
  export * from "../hooks/features/virtualization/index.js";
54
55
  export { useGridColumnResize, columnResizeStateInitializer } from "../hooks/features/columnResize/useGridColumnResize.js";
56
+ export { ROW_SELECTION_PROPAGATION_DEFAULT } from "../hooks/features/rowSelection/utils.js";
55
57
  export { useTimeout } from "../hooks/utils/useTimeout.js";
56
58
  export { useGridVisibleRows, getVisibleRows } from "../hooks/utils/useGridVisibleRows.js";
57
59
  export { useGridInitializeState } from "../hooks/utils/useGridInitializeState.js";
@@ -30,11 +30,10 @@ const bgBGGrid = {
30
30
  toolbarExportPrint: 'Принтиране',
31
31
  toolbarExportExcel: 'Изтегли като Excel',
32
32
  // Columns management text
33
- // columnsManagementSearchTitle: 'Search',
34
- // columnsManagementNoColumns: 'No columns',
35
- // columnsManagementShowHideAllText: 'Show/Hide All',
36
- // columnsManagementReset: 'Reset',
37
-
33
+ columnsManagementSearchTitle: 'Търсене',
34
+ columnsManagementNoColumns: 'Няма колони',
35
+ columnsManagementShowHideAllText: 'Покажи/Скрий Всичко',
36
+ columnsManagementReset: 'Нулирай',
38
37
  // Filter panel text
39
38
  filterPanelAddFilter: 'Добави Филтър',
40
39
  filterPanelRemoveAll: 'Премахни всички',
@@ -48,9 +47,9 @@ const bgBGGrid = {
48
47
  filterPanelInputPlaceholder: 'Стойност на филтъра',
49
48
  // Filter operators text
50
49
  filterOperatorContains: 'съдържа',
51
- // filterOperatorDoesNotContain: 'does not contain',
50
+ filterOperatorDoesNotContain: 'не съдържа',
52
51
  filterOperatorEquals: 'равно',
53
- // filterOperatorDoesNotEqual: 'does not equal',
52
+ filterOperatorDoesNotEqual: 'не е равно',
54
53
  filterOperatorStartsWith: 'започва с',
55
54
  filterOperatorEndsWith: 'завършва с',
56
55
  filterOperatorIs: 'е',
@@ -70,9 +69,9 @@ const bgBGGrid = {
70
69
  'filterOperator<=': '<=',
71
70
  // Header filter operators text
72
71
  headerFilterOperatorContains: 'Съдържа',
73
- // headerFilterOperatorDoesNotContain: 'Does not contain',
72
+ headerFilterOperatorDoesNotContain: 'Не съдържа',
74
73
  headerFilterOperatorEquals: 'Равнo',
75
- // headerFilterOperatorDoesNotEqual: 'Does not equal',
74
+ headerFilterOperatorDoesNotEqual: 'Не е равно',
76
75
  headerFilterOperatorStartsWith: 'Започва с',
77
76
  headerFilterOperatorEndsWith: 'Завършва с',
78
77
  headerFilterOperatorIs: 'Равно е на',
@@ -47,9 +47,9 @@ const deDEGrid = {
47
47
  filterPanelInputPlaceholder: 'Wert filtern',
48
48
  // Filter operators text
49
49
  filterOperatorContains: 'enthält',
50
- // filterOperatorDoesNotContain: 'does not contain',
50
+ filterOperatorDoesNotContain: 'enthält nicht',
51
51
  filterOperatorEquals: 'ist gleich',
52
- // filterOperatorDoesNotEqual: 'does not equal',
52
+ filterOperatorDoesNotEqual: 'ist ungleich',
53
53
  filterOperatorStartsWith: 'beginnt mit',
54
54
  filterOperatorEndsWith: 'endet mit',
55
55
  filterOperatorIs: 'ist',
@@ -69,9 +69,9 @@ const deDEGrid = {
69
69
  'filterOperator<=': '<=',
70
70
  // Header filter operators text
71
71
  headerFilterOperatorContains: 'Enthält',
72
- // headerFilterOperatorDoesNotContain: 'Does not contain',
72
+ headerFilterOperatorDoesNotContain: 'Enthält nicht',
73
73
  headerFilterOperatorEquals: 'Gleich',
74
- // headerFilterOperatorDoesNotEqual: 'Does not equal',
74
+ headerFilterOperatorDoesNotEqual: 'Ungleich',
75
75
  headerFilterOperatorStartsWith: 'Beginnt mit',
76
76
  headerFilterOperatorEndsWith: 'Endet mit',
77
77
  headerFilterOperatorIs: 'Ist',
@@ -47,9 +47,9 @@ const frFRGrid = {
47
47
  filterPanelInputPlaceholder: 'Filtrer la valeur',
48
48
  // Filter operators text
49
49
  filterOperatorContains: 'contient',
50
- // filterOperatorDoesNotContain: 'does not contain',
50
+ filterOperatorDoesNotContain: 'ne contient pas',
51
51
  filterOperatorEquals: 'est égal à',
52
- // filterOperatorDoesNotEqual: 'does not equal',
52
+ filterOperatorDoesNotEqual: "n'est pas égal à",
53
53
  filterOperatorStartsWith: 'commence par',
54
54
  filterOperatorEndsWith: 'se termine par',
55
55
  filterOperatorIs: 'est',
@@ -69,9 +69,9 @@ const frFRGrid = {
69
69
  'filterOperator<=': '<=',
70
70
  // Header filter operators text
71
71
  headerFilterOperatorContains: 'Contient',
72
- // headerFilterOperatorDoesNotContain: 'Does not contain',
72
+ headerFilterOperatorDoesNotContain: 'Ne contient pas',
73
73
  headerFilterOperatorEquals: 'Est égal à',
74
- // headerFilterOperatorDoesNotEqual: 'Does not equal',
74
+ headerFilterOperatorDoesNotEqual: "N'est pas égal à",
75
75
  headerFilterOperatorStartsWith: 'Commence par',
76
76
  headerFilterOperatorEndsWith: 'Se termine par',
77
77
  headerFilterOperatorIs: 'Est',