@mui/x-data-grid 8.9.1 → 8.9.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 (126) hide show
  1. package/CHANGELOG.md +96 -2
  2. package/DataGrid/DataGrid.js +5 -0
  3. package/DataGrid/useDataGridComponent.js +2 -0
  4. package/colDef/gridCheckboxSelectionColDef.js +1 -0
  5. package/components/GridDetailPanels.d.ts +2 -2
  6. package/components/GridPinnedRows.d.ts +2 -2
  7. package/components/GridRow.js +5 -0
  8. package/components/cell/GridCell.js +7 -5
  9. package/components/cell/GridEditSingleSelectCell.js +1 -1
  10. package/components/columnsManagement/GridColumnsManagement.d.ts +6 -0
  11. package/components/columnsManagement/GridColumnsManagement.js +17 -5
  12. package/components/containers/GridRootStyles.d.ts +1 -1
  13. package/components/toolbarV8/Toolbar.d.ts +1 -1
  14. package/components/virtualization/GridVirtualScroller.js +5 -5
  15. package/constants/dataGridPropsDefaultValues.js +1 -0
  16. package/esm/DataGrid/DataGrid.js +5 -0
  17. package/esm/DataGrid/useDataGridComponent.js +2 -0
  18. package/esm/colDef/gridCheckboxSelectionColDef.js +1 -0
  19. package/esm/components/GridDetailPanels.d.ts +2 -2
  20. package/esm/components/GridPinnedRows.d.ts +2 -2
  21. package/esm/components/GridRow.js +5 -0
  22. package/esm/components/cell/GridCell.js +7 -5
  23. package/esm/components/cell/GridEditSingleSelectCell.js +1 -1
  24. package/esm/components/columnsManagement/GridColumnsManagement.d.ts +6 -0
  25. package/esm/components/columnsManagement/GridColumnsManagement.js +17 -5
  26. package/esm/components/containers/GridRootStyles.d.ts +1 -1
  27. package/esm/components/toolbarV8/Toolbar.d.ts +1 -1
  28. package/esm/components/virtualization/GridVirtualScroller.js +5 -5
  29. package/esm/constants/dataGridPropsDefaultValues.js +1 -0
  30. package/esm/hooks/core/useGridVirtualizer.d.ts +9 -0
  31. package/esm/hooks/core/useGridVirtualizer.js +223 -0
  32. package/esm/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -1
  33. package/esm/hooks/features/columnHeaders/useGridColumnHeaders.js +3 -2
  34. package/esm/hooks/features/columns/useGridColumnSpanning.js +5 -90
  35. package/esm/hooks/features/dimensions/useGridDimensions.js +18 -188
  36. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +1 -1
  37. package/esm/hooks/features/keyboardNavigation/utils.d.ts +3 -3
  38. package/esm/hooks/features/keyboardNavigation/utils.js +5 -5
  39. package/esm/hooks/features/pivoting/gridPivotingInterfaces.d.ts +0 -1
  40. package/esm/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -4
  41. package/esm/hooks/features/pivoting/gridPivotingSelectors.js +1 -2
  42. package/esm/hooks/features/rows/gridRowsMetaInterfaces.d.ts +2 -8
  43. package/esm/hooks/features/rows/gridRowsMetaState.d.ts +2 -18
  44. package/esm/hooks/features/rows/useGridRowAriaAttributes.js +3 -1
  45. package/esm/hooks/features/rows/useGridRowSpanning.d.ts +2 -12
  46. package/esm/hooks/features/rows/useGridRowSpanning.js +54 -85
  47. package/esm/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
  48. package/esm/hooks/features/rows/useGridRowsMeta.js +17 -187
  49. package/esm/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  50. package/esm/hooks/features/virtualization/index.d.ts +1 -0
  51. package/esm/hooks/features/virtualization/index.js +1 -0
  52. package/esm/hooks/features/virtualization/useGridVirtualization.d.ts +5 -16
  53. package/esm/hooks/features/virtualization/useGridVirtualization.js +41 -22
  54. package/esm/hooks/utils/index.d.ts +1 -1
  55. package/esm/hooks/utils/index.js +1 -1
  56. package/esm/hooks/utils/useFirstRender.d.ts +1 -1
  57. package/esm/hooks/utils/useFirstRender.js +1 -8
  58. package/esm/index.js +1 -1
  59. package/esm/internals/index.d.ts +1 -1
  60. package/esm/internals/index.js +1 -1
  61. package/esm/internals/utils/getPinnedCellOffset.js +5 -0
  62. package/esm/locales/frFR.js +18 -21
  63. package/esm/locales/heIL.js +12 -12
  64. package/esm/locales/plPL.js +22 -24
  65. package/esm/models/api/gridApiCommon.d.ts +4 -1
  66. package/esm/models/api/gridColumnSpanning.d.ts +5 -11
  67. package/esm/models/props/DataGridProps.d.ts +5 -0
  68. package/esm/utils/roundToDecimalPlaces.d.ts +1 -1
  69. package/esm/utils/roundToDecimalPlaces.js +1 -3
  70. package/hooks/core/useGridVirtualizer.d.ts +9 -0
  71. package/hooks/core/useGridVirtualizer.js +231 -0
  72. package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -1
  73. package/hooks/features/columnHeaders/useGridColumnHeaders.js +4 -3
  74. package/hooks/features/columns/useGridColumnSpanning.js +5 -91
  75. package/hooks/features/dimensions/useGridDimensions.js +18 -188
  76. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +1 -1
  77. package/hooks/features/keyboardNavigation/utils.d.ts +3 -3
  78. package/hooks/features/keyboardNavigation/utils.js +5 -5
  79. package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +0 -1
  80. package/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -4
  81. package/hooks/features/pivoting/gridPivotingSelectors.js +2 -3
  82. package/hooks/features/rows/gridRowsMetaInterfaces.d.ts +2 -8
  83. package/hooks/features/rows/gridRowsMetaState.d.ts +2 -18
  84. package/hooks/features/rows/useGridRowAriaAttributes.js +3 -1
  85. package/hooks/features/rows/useGridRowSpanning.d.ts +2 -12
  86. package/hooks/features/rows/useGridRowSpanning.js +54 -85
  87. package/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
  88. package/hooks/features/rows/useGridRowsMeta.js +15 -186
  89. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  90. package/hooks/features/virtualization/index.d.ts +1 -0
  91. package/hooks/features/virtualization/index.js +12 -0
  92. package/hooks/features/virtualization/useGridVirtualization.d.ts +5 -16
  93. package/hooks/features/virtualization/useGridVirtualization.js +42 -24
  94. package/hooks/utils/index.d.ts +1 -1
  95. package/hooks/utils/index.js +12 -12
  96. package/hooks/utils/useFirstRender.d.ts +1 -1
  97. package/hooks/utils/useFirstRender.js +11 -11
  98. package/index.js +1 -1
  99. package/internals/index.d.ts +1 -1
  100. package/internals/index.js +4 -11
  101. package/internals/utils/getPinnedCellOffset.js +5 -0
  102. package/locales/frFR.js +18 -21
  103. package/locales/heIL.js +12 -12
  104. package/locales/plPL.js +22 -24
  105. package/models/api/gridApiCommon.d.ts +4 -1
  106. package/models/api/gridColumnSpanning.d.ts +5 -11
  107. package/models/props/DataGridProps.d.ts +5 -0
  108. package/package.json +5 -5
  109. package/utils/roundToDecimalPlaces.d.ts +1 -1
  110. package/utils/roundToDecimalPlaces.js +7 -4
  111. package/esm/hooks/features/rows/gridRowSpanningSelectors.d.ts +0 -10
  112. package/esm/hooks/features/rows/gridRowSpanningSelectors.js +0 -5
  113. package/esm/hooks/features/virtualization/useGridVirtualScroller.d.ts +0 -56
  114. package/esm/hooks/features/virtualization/useGridVirtualScroller.js +0 -843
  115. package/esm/hooks/utils/useRunOnce.d.ts +0 -5
  116. package/esm/hooks/utils/useRunOnce.js +0 -18
  117. package/esm/utils/platform.d.ts +0 -1
  118. package/esm/utils/platform.js +0 -2
  119. package/hooks/features/rows/gridRowSpanningSelectors.d.ts +0 -10
  120. package/hooks/features/rows/gridRowSpanningSelectors.js +0 -11
  121. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +0 -56
  122. package/hooks/features/virtualization/useGridVirtualScroller.js +0 -854
  123. package/hooks/utils/useRunOnce.d.ts +0 -5
  124. package/hooks/utils/useRunOnce.js +0 -27
  125. package/utils/platform.d.ts +0 -1
  126. package/utils/platform.js +0 -8
@@ -2,11 +2,8 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import useEventCallback from '@mui/utils/useEventCallback';
6
- import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
7
- import ownerDocument from '@mui/utils/ownerDocument';
8
- import { throttle } from '@mui/x-internals/throttle';
9
- import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
5
+ import { useStoreEffect } from '@mui/x-internals/store';
6
+ import { Dimensions } from '@mui/x-virtualizer';
10
7
  import { useGridEventPriority } from "../../utils/useGridEvent.js";
11
8
  import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
12
9
  import { createSelector } from "../../../utils/createSelector.js";
@@ -14,10 +11,6 @@ import { useGridLogger } from "../../utils/useGridLogger.js";
14
11
  import { gridColumnPositionsSelector, gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector } from "../columns/index.js";
15
12
  import { gridDimensionsSelector } from "./gridDimensionsSelectors.js";
16
13
  import { gridDensityFactorSelector } from "../density/index.js";
17
- import { gridRenderContextSelector } from "../virtualization/index.js";
18
- import { useGridSelector } from "../../utils/index.js";
19
- import { getVisibleRows } from "../../utils/useGridVisibleRows.js";
20
- import { gridRowsMetaSelector } from "../rows/gridRowsMetaSelector.js";
21
14
  import { getValidRowHeight, rowHeightWarning } from "../rows/gridRowsUtils.js";
22
15
  import { getTotalHeaderHeight } from "../columns/gridColumnsUtils.js";
23
16
  import { DATA_GRID_PROPS_DEFAULT_VALUES } from "../../../constants/dataGridPropsDefaultValues.js";
@@ -66,148 +59,10 @@ const columnsTotalWidthSelector = createSelector(gridVisibleColumnDefinitionsSel
66
59
  export function useGridDimensions(apiRef, props) {
67
60
  const logger = useGridLogger(apiRef, 'useResizeContainer');
68
61
  const errorShown = React.useRef(false);
69
- const rootDimensionsRef = React.useRef(EMPTY_SIZE);
70
- const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
71
- const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector);
72
- const columnsTotalWidth = useGridSelector(apiRef, columnsTotalWidthSelector);
73
- const isFirstSizing = React.useRef(true);
74
- const {
75
- rowHeight,
76
- headerHeight,
77
- groupHeaderHeight,
78
- headerFilterHeight,
79
- headersTotalHeight,
80
- leftPinnedWidth,
81
- rightPinnedWidth
82
- } = getStaticDimensions(props, apiRef, densityFactor, pinnedColumns);
62
+ const virtualizer = apiRef.current.virtualizer;
63
+ const updateDimensions = virtualizer.api.updateDimensions;
64
+ const getViewportPageSize = virtualizer.api.getViewportPageSize;
83
65
  const getRootDimensions = React.useCallback(() => gridDimensionsSelector(apiRef), [apiRef]);
84
- const setDimensions = React.useCallback(dimensions => {
85
- apiRef.current.setState(state => _extends({}, state, {
86
- dimensions
87
- }));
88
- if (apiRef.current.rootElementRef.current) {
89
- setCSSVariables(apiRef.current.rootElementRef.current, gridDimensionsSelector(apiRef));
90
- }
91
- }, [apiRef]);
92
- const getViewportPageSize = React.useCallback(() => {
93
- const dimensions = gridDimensionsSelector(apiRef);
94
- if (!dimensions.isReady) {
95
- return 0;
96
- }
97
- const currentPage = getVisibleRows(apiRef);
98
-
99
- // TODO: Use a combination of scrollTop, dimensions.viewportInnerSize.height and rowsMeta.possitions
100
- // to find out the maximum number of rows that can fit in the visible part of the grid
101
- if (props.getRowHeight) {
102
- const renderContext = gridRenderContextSelector(apiRef);
103
- const viewportPageSize = renderContext.lastRowIndex - renderContext.firstRowIndex;
104
- return Math.min(viewportPageSize - 1, currentPage.rows.length);
105
- }
106
- const maximumPageSizeWithoutScrollBar = Math.floor(dimensions.viewportInnerSize.height / rowHeight);
107
- return Math.min(maximumPageSizeWithoutScrollBar, currentPage.rows.length);
108
- }, [apiRef, props.getRowHeight, rowHeight]);
109
- const updateDimensions = React.useCallback(() => {
110
- if (isFirstSizing.current) {
111
- return;
112
- }
113
- // All the floating point dimensions should be rounded to .1 decimal places to avoid subpixel rendering issues
114
- // https://github.com/mui/mui-x/issues/9550#issuecomment-1619020477
115
- // https://github.com/mui/mui-x/issues/15721
116
- const scrollbarSize = measureScrollbarSize(apiRef.current.mainElementRef.current, props.scrollbarSize);
117
- const rowsMeta = gridRowsMetaSelector(apiRef);
118
- const topContainerHeight = headersTotalHeight + rowsMeta.pinnedTopRowsTotalHeight;
119
- const bottomContainerHeight = rowsMeta.pinnedBottomRowsTotalHeight;
120
- const contentSize = {
121
- width: columnsTotalWidth,
122
- height: roundToDecimalPlaces(rowsMeta.currentPageTotalHeight, 1)
123
- };
124
- let viewportOuterSize;
125
- let viewportInnerSize;
126
- let hasScrollX = false;
127
- let hasScrollY = false;
128
- if (props.autoHeight) {
129
- hasScrollY = false;
130
- hasScrollX = Math.round(columnsTotalWidth) > Math.round(rootDimensionsRef.current.width);
131
- viewportOuterSize = {
132
- width: rootDimensionsRef.current.width,
133
- height: topContainerHeight + bottomContainerHeight + contentSize.height
134
- };
135
- viewportInnerSize = {
136
- width: Math.max(0, viewportOuterSize.width - (hasScrollY ? scrollbarSize : 0)),
137
- height: Math.max(0, viewportOuterSize.height - (hasScrollX ? scrollbarSize : 0))
138
- };
139
- } else {
140
- viewportOuterSize = {
141
- width: rootDimensionsRef.current.width,
142
- height: rootDimensionsRef.current.height
143
- };
144
- viewportInnerSize = {
145
- width: Math.max(0, viewportOuterSize.width),
146
- height: Math.max(0, viewportOuterSize.height - topContainerHeight - bottomContainerHeight)
147
- };
148
- const content = contentSize;
149
- const container = viewportInnerSize;
150
- const hasScrollXIfNoYScrollBar = content.width > container.width;
151
- const hasScrollYIfNoXScrollBar = content.height > container.height;
152
- if (hasScrollXIfNoYScrollBar || hasScrollYIfNoXScrollBar) {
153
- hasScrollY = hasScrollYIfNoXScrollBar;
154
- hasScrollX = content.width + (hasScrollY ? scrollbarSize : 0) > container.width;
155
-
156
- // We recalculate the scroll y to consider the size of the x scrollbar.
157
- if (hasScrollX) {
158
- hasScrollY = content.height + scrollbarSize > container.height;
159
- }
160
- }
161
- if (hasScrollY) {
162
- viewportInnerSize.width -= scrollbarSize;
163
- }
164
- if (hasScrollX) {
165
- viewportInnerSize.height -= scrollbarSize;
166
- }
167
- }
168
- const rowWidth = Math.max(viewportOuterSize.width, columnsTotalWidth + (hasScrollY ? scrollbarSize : 0));
169
- const minimumSize = {
170
- width: columnsTotalWidth,
171
- height: topContainerHeight + contentSize.height + bottomContainerHeight
172
- };
173
- const newDimensions = {
174
- isReady: true,
175
- root: rootDimensionsRef.current,
176
- viewportOuterSize,
177
- viewportInnerSize,
178
- contentSize,
179
- minimumSize,
180
- hasScrollX,
181
- hasScrollY,
182
- scrollbarSize,
183
- headerHeight,
184
- groupHeaderHeight,
185
- headerFilterHeight,
186
- rowWidth,
187
- rowHeight,
188
- columnsTotalWidth,
189
- leftPinnedWidth,
190
- rightPinnedWidth,
191
- headersTotalHeight,
192
- topContainerHeight,
193
- bottomContainerHeight
194
- };
195
- const prevDimensions = apiRef.current.state.dimensions;
196
- if (isDeepEqual(prevDimensions, newDimensions)) {
197
- return;
198
- }
199
- setDimensions(newDimensions);
200
- if (!areElementSizesEqual(newDimensions.viewportInnerSize, prevDimensions.viewportInnerSize)) {
201
- apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize);
202
- }
203
- apiRef.current.updateRenderContext?.();
204
- }, [apiRef, setDimensions, props.scrollbarSize, props.autoHeight, rowHeight, headerHeight, groupHeaderHeight, headerFilterHeight, columnsTotalWidth, headersTotalHeight, leftPinnedWidth, rightPinnedWidth]);
205
- const updateDimensionCallback = useEventCallback(updateDimensions);
206
- const debouncedUpdateDimensions = React.useMemo(() => props.resizeThrottleMs > 0 ? throttle(() => {
207
- updateDimensionCallback();
208
- apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current);
209
- }, props.resizeThrottleMs) : undefined, [apiRef, props.resizeThrottleMs, updateDimensionCallback]);
210
- React.useEffect(() => debouncedUpdateDimensions?.clear, [debouncedUpdateDimensions]);
211
66
  const apiPublic = {
212
67
  getRootDimensions
213
68
  };
@@ -215,14 +70,12 @@ export function useGridDimensions(apiRef, props) {
215
70
  updateDimensions,
216
71
  getViewportPageSize
217
72
  };
218
- useEnhancedEffect(updateDimensions, [updateDimensions]);
219
73
  useGridApiMethod(apiRef, apiPublic, 'public');
220
74
  useGridApiMethod(apiRef, apiPrivate, 'private');
221
- const handleRootMount = React.useCallback(root => {
75
+ const handleRootMount = root => {
222
76
  setCSSVariables(root, gridDimensionsSelector(apiRef));
223
- }, [apiRef]);
224
- const handleResize = React.useCallback(size => {
225
- rootDimensionsRef.current = size;
77
+ };
78
+ const handleResize = size => {
226
79
  if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
227
80
  logger.error(['The parent DOM element of the Data Grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
228
81
  errorShown.current = true;
@@ -231,17 +84,19 @@ export function useGridDimensions(apiRef, props) {
231
84
  logger.error(['The parent DOM element of the Data Grid has an empty width.', 'Please make sure that this element has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
232
85
  errorShown.current = true;
233
86
  }
234
- if (isFirstSizing.current || !debouncedUpdateDimensions) {
235
- // We want to initialize the grid dimensions as soon as possible to avoid flickering
236
- isFirstSizing.current = false;
237
- updateDimensions();
238
- return;
239
- }
240
- debouncedUpdateDimensions();
241
- }, [updateDimensions, props.autoHeight, debouncedUpdateDimensions, logger]);
87
+ };
242
88
  useGridEventPriority(apiRef, 'rootMount', handleRootMount);
243
89
  useGridEventPriority(apiRef, 'resize', handleResize);
244
90
  useGridEventPriority(apiRef, 'debouncedResize', props.onResize);
91
+ useStoreEffect(virtualizer.store, Dimensions.selectors.dimensions, (previous, next) => {
92
+ if (apiRef.current.rootElementRef.current) {
93
+ setCSSVariables(apiRef.current.rootElementRef.current, next);
94
+ }
95
+ if (!areElementSizesEqual(next.viewportInnerSize, previous.viewportInnerSize)) {
96
+ apiRef.current.publishEvent('viewportInnerSizeChange', next.viewportInnerSize);
97
+ }
98
+ apiRef.current.publishEvent('debouncedResize', next.root);
99
+ });
245
100
  }
246
101
  function setCSSVariables(root, dimensions) {
247
102
  const set = (k, v) => root.style.setProperty(k, v);
@@ -271,31 +126,6 @@ function getStaticDimensions(props, apiRef, density, pinnedColumnns) {
271
126
  rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0)
272
127
  };
273
128
  }
274
- const scrollbarSizeCache = new WeakMap();
275
- function measureScrollbarSize(element, scrollbarSize) {
276
- if (scrollbarSize !== undefined) {
277
- return scrollbarSize;
278
- }
279
- if (element === null) {
280
- return 0;
281
- }
282
- const cachedSize = scrollbarSizeCache.get(element);
283
- if (cachedSize !== undefined) {
284
- return cachedSize;
285
- }
286
- const doc = ownerDocument(element);
287
- const scrollDiv = doc.createElement('div');
288
- scrollDiv.style.width = '99px';
289
- scrollDiv.style.height = '99px';
290
- scrollDiv.style.position = 'absolute';
291
- scrollDiv.style.overflow = 'scroll';
292
- scrollDiv.className = 'scrollDiv';
293
- element.appendChild(scrollDiv);
294
- const size = scrollDiv.offsetWidth - scrollDiv.clientWidth;
295
- element.removeChild(scrollDiv);
296
- scrollbarSizeCache.set(element, size);
297
- return size;
298
- }
299
129
  function areElementSizesEqual(a, b) {
300
130
  return a.width === b.width && a.height === b.height;
301
131
  }
@@ -58,7 +58,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
58
58
  }
59
59
  }
60
60
  const field = gridVisibleColumnFieldsSelector(apiRef)[colIndex];
61
- const nonRowSpannedRowId = findNonRowSpannedCell(apiRef, rowId, field, rowSpanScanDirection);
61
+ const nonRowSpannedRowId = findNonRowSpannedCell(apiRef, rowId, colIndex, rowSpanScanDirection);
62
62
  // `scrollToIndexes` requires a rowIndex relative to all visible rows.
63
63
  // Those rows do not include pinned rows, but pinned rows do not need scroll anyway.
64
64
  const rowIndexRelativeToAllRows = visibleSortedRows.findIndex(row => row.id === nonRowSpannedRowId);
@@ -1,6 +1,6 @@
1
1
  import { RefObject } from '@mui/x-internals/types';
2
- import { GridColDef, GridRowId } from "../../../models/index.js";
3
- import { GridApiCommunity } from "../../../models/api/gridApiCommunity.js";
2
+ import { GridRowId } from "../../../models/index.js";
3
+ import { GridPrivateApiCommunity } from "../../../models/api/gridApiCommunity.js";
4
4
  export declare const getLeftColumnIndex: ({
5
5
  currentColIndex,
6
6
  firstColIndex,
@@ -23,4 +23,4 @@ export declare const getRightColumnIndex: ({
23
23
  lastColIndex: number;
24
24
  isRtl: boolean;
25
25
  }) => number | null;
26
- export declare function findNonRowSpannedCell(apiRef: RefObject<GridApiCommunity>, rowId: GridRowId, field: GridColDef['field'], rowSpanScanDirection: 'up' | 'down'): GridRowId;
26
+ export declare function findNonRowSpannedCell(apiRef: RefObject<GridPrivateApiCommunity>, rowId: GridRowId, colIndex: number, rowSpanScanDirection: 'up' | 'down'): GridRowId;
@@ -1,5 +1,5 @@
1
+ import { Rowspan } from '@mui/x-virtualizer';
1
2
  import { gridFilteredSortedRowIdsSelector } from "../filter/gridFilterSelector.js";
2
- import { gridRowSpanningHiddenCellsSelector } from "../rows/gridRowSpanningSelectors.js";
3
3
  export const getLeftColumnIndex = ({
4
4
  currentColIndex,
5
5
  firstColIndex,
@@ -34,9 +34,9 @@ export const getRightColumnIndex = ({
34
34
  }
35
35
  return null;
36
36
  };
37
- export function findNonRowSpannedCell(apiRef, rowId, field, rowSpanScanDirection) {
38
- const rowSpanHiddenCells = gridRowSpanningHiddenCellsSelector(apiRef);
39
- if (!rowSpanHiddenCells[rowId]?.[field]) {
37
+ export function findNonRowSpannedCell(apiRef, rowId, colIndex, rowSpanScanDirection) {
38
+ const rowSpanHiddenCells = Rowspan.selectors.hiddenCells(apiRef.current.virtualizer.store.state);
39
+ if (!rowSpanHiddenCells[rowId]?.[colIndex]) {
40
40
  return rowId;
41
41
  }
42
42
  const filteredSortedRowIds = gridFilteredSortedRowIdsSelector(apiRef);
@@ -44,7 +44,7 @@ export function findNonRowSpannedCell(apiRef, rowId, field, rowSpanScanDirection
44
44
  let nextRowIndex = filteredSortedRowIds.indexOf(rowId) + (rowSpanScanDirection === 'down' ? 1 : -1);
45
45
  while (nextRowIndex >= 0 && nextRowIndex < filteredSortedRowIds.length) {
46
46
  const nextRowId = filteredSortedRowIds[nextRowIndex];
47
- if (!rowSpanHiddenCells[nextRowId]?.[field]) {
47
+ if (!rowSpanHiddenCells[nextRowId]?.[colIndex]) {
48
48
  return nextRowId;
49
49
  }
50
50
  nextRowIndex += rowSpanScanDirection === 'down' ? 1 : -1;
@@ -2,7 +2,6 @@ import type { GridRowModelUpdate } from '@mui/x-data-grid';
2
2
  import type { GridColDef } from "../../../models/colDef/index.js";
3
3
  export interface GridPivotingStatePartial {
4
4
  active: boolean;
5
- panelOpen: boolean;
6
5
  initialColumns: Map<string, GridColDef> | undefined;
7
6
  }
8
7
  export interface GridPivotingPrivateApiCommunity {
@@ -5,7 +5,4 @@ export declare const gridPivotActiveSelector: (args_0: import("react").RefObject
5
5
  } | null>) => boolean;
6
6
  export declare const gridPivotInitialColumnsSelector: (args_0: import("react").RefObject<{
7
7
  state: GridStateCommunity;
8
- } | null>) => Map<string, GridColDef>;
9
- export declare const gridPivotPanelOpenSelector: (args_0: import("react").RefObject<{
10
- state: GridStateCommunity;
11
- } | null>) => boolean;
8
+ } | null>) => Map<string, GridColDef>;
@@ -4,5 +4,4 @@ const gridPivotingStateSelector = createRootSelector(
4
4
  state => state.pivoting);
5
5
  export const gridPivotActiveSelector = createSelector(gridPivotingStateSelector, pivoting => pivoting?.active);
6
6
  const emptyColumns = new Map();
7
- export const gridPivotInitialColumnsSelector = createSelector(gridPivotingStateSelector, pivoting => pivoting?.initialColumns || emptyColumns);
8
- export const gridPivotPanelOpenSelector = createSelector(gridPivotingStateSelector, pivoting => pivoting?.panelOpen);
7
+ export const gridPivotInitialColumnsSelector = createSelector(gridPivotingStateSelector, pivoting => pivoting?.initialColumns || emptyColumns);
@@ -1,12 +1,6 @@
1
+ import type { HeightEntry } from '@mui/x-virtualizer/models';
1
2
  import { GridRowId } from "../../../models/gridRows.js";
2
- export type HeightEntry = {
3
- content: number;
4
- spacingTop: number;
5
- spacingBottom: number;
6
- detail: number;
7
- autoHeight: boolean;
8
- needsFirstMeasurement: boolean;
9
- };
3
+ export type { HeightEntry } from '@mui/x-virtualizer/models';
10
4
  export type HeightCache = Map<GridRowId, HeightEntry>;
11
5
  export interface GridRowsMetaInternalCache {
12
6
  /**
@@ -1,21 +1,5 @@
1
+ import { RowsMetaState } from '@mui/x-virtualizer/models';
1
2
  /**
2
3
  * The grid rows total height and row positions.
3
4
  */
4
- export interface GridRowsMetaState {
5
- /**
6
- * The sum of all visible grid rows in the current rows.
7
- */
8
- currentPageTotalHeight: number;
9
- /**
10
- * The grid rows positions.
11
- */
12
- positions: number[];
13
- /**
14
- * The total height of the pinned top rows.
15
- */
16
- pinnedTopRowsTotalHeight: number;
17
- /**
18
- * The total height of the pinned bottom rows.
19
- */
20
- pinnedBottomRowsTotalHeight: number;
21
- }
5
+ export interface GridRowsMetaState extends RowsMetaState {}
@@ -9,7 +9,9 @@ export const useGridRowAriaAttributes = () => {
9
9
  const ariaAttributes = {};
10
10
  const ariaRowIndex = index + headerGroupingMaxDepth + 2; // 1 for the header row and 1 as it's 1-based
11
11
  ariaAttributes['aria-rowindex'] = ariaRowIndex;
12
- if (apiRef.current.isRowSelectable(rowNode.id)) {
12
+
13
+ // XXX: fix this properly
14
+ if (rowNode && apiRef.current.isRowSelectable(rowNode.id)) {
13
15
  ariaAttributes['aria-selected'] = apiRef.current.isRowSelected(rowNode.id);
14
16
  }
15
17
  return ariaAttributes;
@@ -1,19 +1,9 @@
1
1
  import { RefObject } from '@mui/x-internals/types';
2
- import type { GridColDef } from "../../../models/colDef/index.js";
3
- import type { GridRowId } from "../../../models/gridRows.js";
2
+ import { RowSpanningState } from '@mui/x-virtualizer/models';
4
3
  import type { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
5
4
  import type { GridPrivateApiCommunity } from "../../../models/api/gridApiCommunity.js";
6
5
  import type { GridStateInitializer } from "../../utils/useGridInitializeState.js";
7
- export interface GridRowSpanningState {
8
- spannedCells: Record<GridRowId, Record<GridColDef['field'], number>>;
9
- hiddenCells: Record<GridRowId, Record<GridColDef['field'], boolean>>;
10
- /**
11
- * For each hidden cell, it contains the row index corresponding to the cell that is
12
- * the origin of the hidden cell. i.e. the cell which is spanned.
13
- * Used by the virtualization to properly keep the spanned cells in view.
14
- */
15
- hiddenCellOriginMap: Record<number, Record<GridColDef['field'], number>>;
16
- }
6
+ export interface GridRowSpanningState extends RowSpanningState {}
17
7
  export type RowRange = {
18
8
  firstRowIndex: number;
19
9
  lastRowIndex: number;
@@ -2,18 +2,16 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import useLazyRef from '@mui/utils/useLazyRef';
6
- import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from "../../../internals/constants.js";
5
+ import { Rowspan } from '@mui/x-virtualizer/features';
7
6
  import { gridVisibleColumnDefinitionsSelector } from "../columns/gridColumnsSelector.js";
8
7
  import { getVisibleRows } from "../../utils/useGridVisibleRows.js";
9
8
  import { gridRenderContextSelector } from "../virtualization/gridVirtualizationSelectors.js";
10
9
  import { getUnprocessedRange, isRowContextInitialized, getCellValue } from "./gridRowSpanningUtils.js";
11
- import { GRID_CHECKBOX_SELECTION_FIELD } from "../../../colDef/gridCheckboxSelectionColDef.js";
12
10
  import { useGridEvent } from "../../utils/useGridEvent.js";
13
11
  import { runIf } from "../../../utils/utils.js";
14
12
  import { gridPageSizeSelector } from "../pagination/index.js";
15
13
  import { gridDataRowIdsSelector } from "./gridRowsSelector.js";
16
- const EMPTY_STATE = {
14
+ const EMPTY_CACHES = {
17
15
  spannedCells: {},
18
16
  hiddenCells: {},
19
17
  hiddenCellOriginMap: {}
@@ -22,27 +20,31 @@ const EMPTY_RANGE = {
22
20
  firstRowIndex: 0,
23
21
  lastRowIndex: 0
24
22
  };
25
- const skippedFields = new Set([GRID_CHECKBOX_SELECTION_FIELD, '__reorder__', GRID_DETAIL_PANEL_TOGGLE_FIELD]);
23
+ const EMPTY_STATE = {
24
+ caches: EMPTY_CACHES,
25
+ processedRange: EMPTY_RANGE
26
+ };
27
+
26
28
  /**
27
29
  * Default number of rows to process during state initialization to avoid flickering.
28
30
  * Number `20` is arbitrarily chosen to be large enough to cover most of the cases without
29
31
  * compromising performance.
30
32
  */
31
33
  const DEFAULT_ROWS_TO_PROCESS = 20;
32
- const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToProcess, resetState, processedRange) => {
33
- const spannedCells = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.spannedCells);
34
- const hiddenCells = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.hiddenCells);
35
- const hiddenCellOriginMap = resetState ? {} : _extends({}, apiRef.current.state.rowSpanning.hiddenCellOriginMap);
36
- if (resetState) {
37
- processedRange = EMPTY_RANGE;
38
- }
39
- colDefs.forEach(colDef => {
40
- if (skippedFields.has(colDef.field)) {
41
- return;
42
- }
34
+ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToProcess, resetState) => {
35
+ const virtualizer = apiRef.current.virtualizer;
36
+ const previousState = resetState ? EMPTY_STATE : Rowspan.selectors.state(virtualizer.store.state);
37
+ const spannedCells = _extends({}, previousState.caches.spannedCells);
38
+ const hiddenCells = _extends({}, previousState.caches.hiddenCells);
39
+ const hiddenCellOriginMap = _extends({}, previousState.caches.hiddenCellOriginMap);
40
+ const processedRange = {
41
+ firstRowIndex: Math.min(previousState.processedRange.firstRowIndex, rangeToProcess.firstRowIndex),
42
+ lastRowIndex: Math.max(previousState.processedRange.lastRowIndex, rangeToProcess.lastRowIndex)
43
+ };
44
+ colDefs.forEach((colDef, columnIndex) => {
43
45
  for (let index = rangeToProcess.firstRowIndex; index < rangeToProcess.lastRowIndex; index += 1) {
44
46
  const row = visibleRows[index];
45
- if (hiddenCells[row.id]?.[colDef.field]) {
47
+ if (hiddenCells[row.id]?.[columnIndex]) {
46
48
  continue;
47
49
  }
48
50
  const cellValue = getCellValue(row.model, colDef, apiRef);
@@ -61,10 +63,10 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
61
63
  while (prevIndex >= range.firstRowIndex && prevRowEntry && getCellValue(prevRowEntry.model, colDef, apiRef) === cellValue) {
62
64
  const currentRow = visibleRows[prevIndex + 1];
63
65
  if (hiddenCells[currentRow.id]) {
64
- hiddenCells[currentRow.id][colDef.field] = true;
66
+ hiddenCells[currentRow.id][columnIndex] = true;
65
67
  } else {
66
68
  hiddenCells[currentRow.id] = {
67
- [colDef.field]: true
69
+ [columnIndex]: true
68
70
  };
69
71
  }
70
72
  backwardsHiddenCells.push(index);
@@ -77,10 +79,10 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
77
79
  }
78
80
  backwardsHiddenCells.forEach(hiddenCellIndex => {
79
81
  if (hiddenCellOriginMap[hiddenCellIndex]) {
80
- hiddenCellOriginMap[hiddenCellIndex][colDef.field] = spannedRowIndex;
82
+ hiddenCellOriginMap[hiddenCellIndex][columnIndex] = spannedRowIndex;
81
83
  } else {
82
84
  hiddenCellOriginMap[hiddenCellIndex] = {
83
- [colDef.field]: spannedRowIndex
85
+ [columnIndex]: spannedRowIndex
84
86
  };
85
87
  }
86
88
  });
@@ -90,17 +92,17 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
90
92
  while (relativeIndex <= range.lastRowIndex && visibleRows[relativeIndex] && getCellValue(visibleRows[relativeIndex].model, colDef, apiRef) === cellValue) {
91
93
  const currentRow = visibleRows[relativeIndex];
92
94
  if (hiddenCells[currentRow.id]) {
93
- hiddenCells[currentRow.id][colDef.field] = true;
95
+ hiddenCells[currentRow.id][columnIndex] = true;
94
96
  } else {
95
97
  hiddenCells[currentRow.id] = {
96
- [colDef.field]: true
98
+ [columnIndex]: true
97
99
  };
98
100
  }
99
101
  if (hiddenCellOriginMap[relativeIndex]) {
100
- hiddenCellOriginMap[relativeIndex][colDef.field] = spannedRowIndex;
102
+ hiddenCellOriginMap[relativeIndex][columnIndex] = spannedRowIndex;
101
103
  } else {
102
104
  hiddenCellOriginMap[relativeIndex] = {
103
- [colDef.field]: spannedRowIndex
105
+ [columnIndex]: spannedRowIndex
104
106
  };
105
107
  }
106
108
  relativeIndex += 1;
@@ -108,23 +110,21 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
108
110
  }
109
111
  if (rowSpan > 0) {
110
112
  if (spannedCells[spannedRowId]) {
111
- spannedCells[spannedRowId][colDef.field] = rowSpan + 1;
113
+ spannedCells[spannedRowId][columnIndex] = rowSpan + 1;
112
114
  } else {
113
115
  spannedCells[spannedRowId] = {
114
- [colDef.field]: rowSpan + 1
116
+ [columnIndex]: rowSpan + 1
115
117
  };
116
118
  }
117
119
  }
118
120
  }
119
- processedRange = {
120
- firstRowIndex: Math.min(processedRange.firstRowIndex, rangeToProcess.firstRowIndex),
121
- lastRowIndex: Math.max(processedRange.lastRowIndex, rangeToProcess.lastRowIndex)
122
- };
123
121
  });
124
122
  return {
125
- spannedCells,
126
- hiddenCells,
127
- hiddenCellOriginMap,
123
+ caches: {
124
+ spannedCells,
125
+ hiddenCells,
126
+ hiddenCellOriginMap
127
+ },
128
128
  processedRange
129
129
  };
130
130
  };
@@ -174,71 +174,42 @@ export const rowSpanningStateInitializer = (state, props, apiRef) => {
174
174
  model: dataRowIdToModelLookup[id]
175
175
  }));
176
176
  const colDefs = orderedFields.map(field => columnsLookup[field]);
177
- const {
178
- spannedCells,
179
- hiddenCells,
180
- hiddenCellOriginMap
181
- } = computeRowSpanningState(apiRef, colDefs, rows, rangeToProcess, rangeToProcess, true, EMPTY_RANGE);
177
+ const rowSpanning = computeRowSpanningState(apiRef, colDefs, rows, rangeToProcess, rangeToProcess, true);
182
178
  return _extends({}, state, {
183
- rowSpanning: {
184
- spannedCells,
185
- hiddenCells,
186
- hiddenCellOriginMap
187
- }
179
+ rowSpanning
188
180
  });
189
181
  };
190
182
  export const useGridRowSpanning = (apiRef, props) => {
191
- const processedRange = useLazyRef(() => {
192
- return apiRef.current.state.rowSpanning !== EMPTY_STATE ? getInitialRangeToProcess(props, apiRef) : EMPTY_RANGE;
193
- });
183
+ const store = apiRef.current.virtualizer.store;
194
184
  const updateRowSpanningState = React.useCallback((renderContext, resetState = false) => {
195
185
  const {
196
186
  range,
197
187
  rows: visibleRows
198
- } = getVisibleRows(apiRef, {
199
- pagination: props.pagination,
200
- paginationMode: props.paginationMode
201
- });
188
+ } = getVisibleRows(apiRef);
202
189
  if (range === null || !isRowContextInitialized(renderContext)) {
203
190
  return;
204
191
  }
205
- if (resetState) {
206
- processedRange.current = EMPTY_RANGE;
207
- }
192
+ const previousState = resetState ? EMPTY_STATE : Rowspan.selectors.state(store.state);
208
193
  const rangeToProcess = getUnprocessedRange({
209
194
  firstRowIndex: renderContext.firstRowIndex,
210
- lastRowIndex: Math.min(renderContext.lastRowIndex, range.lastRowIndex + 1)
211
- }, processedRange.current);
195
+ lastRowIndex: Math.min(renderContext.lastRowIndex, range.lastRowIndex - range.firstRowIndex + 1)
196
+ }, previousState.processedRange);
212
197
  if (rangeToProcess === null) {
213
198
  return;
214
199
  }
215
200
  const colDefs = gridVisibleColumnDefinitionsSelector(apiRef);
216
- const {
217
- spannedCells,
218
- hiddenCells,
219
- hiddenCellOriginMap,
220
- processedRange: newProcessedRange
221
- } = computeRowSpanningState(apiRef, colDefs, visibleRows, range, rangeToProcess, resetState, processedRange.current);
222
- processedRange.current = newProcessedRange;
223
- const newSpannedCellsCount = Object.keys(spannedCells).length;
224
- const newHiddenCellsCount = Object.keys(hiddenCells).length;
225
- const currentSpannedCellsCount = Object.keys(apiRef.current.state.rowSpanning.spannedCells).length;
226
- const currentHiddenCellsCount = Object.keys(apiRef.current.state.rowSpanning.hiddenCells).length;
227
- const shouldUpdateState = resetState || newSpannedCellsCount !== currentSpannedCellsCount || newHiddenCellsCount !== currentHiddenCellsCount;
228
- const hasNoSpannedCells = newSpannedCellsCount === 0 && currentSpannedCellsCount === 0;
201
+ const newState = computeRowSpanningState(apiRef, colDefs, visibleRows, range, rangeToProcess, resetState);
202
+ const newSpannedCellsCount = Object.keys(newState.caches.spannedCells).length;
203
+ const newHiddenCellsCount = Object.keys(newState.caches.hiddenCells).length;
204
+ const previousSpannedCellsCount = Object.keys(previousState.caches.spannedCells).length;
205
+ const previousHiddenCellsCount = Object.keys(previousState.caches.hiddenCells).length;
206
+ const shouldUpdateState = resetState || newSpannedCellsCount !== previousSpannedCellsCount || newHiddenCellsCount !== previousHiddenCellsCount;
207
+ const hasNoSpannedCells = newSpannedCellsCount === 0 && previousSpannedCellsCount === 0;
229
208
  if (!shouldUpdateState || hasNoSpannedCells) {
230
209
  return;
231
210
  }
232
- apiRef.current.setState(state => {
233
- return _extends({}, state, {
234
- rowSpanning: {
235
- spannedCells,
236
- hiddenCells,
237
- hiddenCellOriginMap
238
- }
239
- });
240
- });
241
- }, [apiRef, processedRange, props.pagination, props.paginationMode]);
211
+ store.set('rowSpanning', newState);
212
+ }, [apiRef, store]);
242
213
 
243
214
  // Reset events trigger a full re-computation of the row spanning state:
244
215
  // - The `unstable_rowSpanning` prop is updated (feature flag)
@@ -260,13 +231,11 @@ export const useGridRowSpanning = (apiRef, props) => {
260
231
  useGridEvent(apiRef, 'columnsChange', runIf(props.rowSpanning, resetRowSpanningState));
261
232
  React.useEffect(() => {
262
233
  if (!props.rowSpanning) {
263
- if (apiRef.current.state.rowSpanning !== EMPTY_STATE) {
264
- apiRef.current.setState(state => _extends({}, state, {
265
- rowSpanning: EMPTY_STATE
266
- }));
234
+ if (store.state.rowSpanning !== EMPTY_STATE) {
235
+ store.set('rowSpanning', EMPTY_STATE);
267
236
  }
268
- } else if (apiRef.current.state.rowSpanning === EMPTY_STATE) {
237
+ } else if (store.state.rowSpanning.caches === EMPTY_CACHES) {
269
238
  resetRowSpanningState();
270
239
  }
271
- }, [apiRef, resetRowSpanningState, props.rowSpanning]);
240
+ }, [apiRef, store, resetRowSpanningState, props.rowSpanning]);
272
241
  };