@mui/x-data-grid 8.0.0-alpha.2 → 8.0.0-alpha.4

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 (138) hide show
  1. package/CHANGELOG.md +376 -0
  2. package/DataGrid/DataGrid.js +5 -13
  3. package/README.md +1 -1
  4. package/components/GridRow.js +1 -1
  5. package/components/cell/GridActionsCell.js +8 -1
  6. package/components/cell/GridCell.js +1 -1
  7. package/components/columnSelection/GridHeaderCheckbox.js +4 -1
  8. package/components/panel/GridColumnsPanel.js +1 -2
  9. package/components/panel/GridPanelContent.js +7 -3
  10. package/components/panel/GridPanelFooter.d.ts +1 -1
  11. package/components/panel/GridPanelFooter.js +4 -3
  12. package/components/panel/filterPanel/GridFilterForm.js +15 -15
  13. package/constants/dataGridPropsDefaultValues.js +1 -2
  14. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.ts +25 -9
  15. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.js +5 -1
  16. package/hooks/core/strategyProcessing/useGridStrategyProcessing.d.ts +3 -6
  17. package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +7 -8
  18. package/hooks/core/useGridStateInitialization.js +3 -3
  19. package/hooks/features/columnGrouping/gridColumnGroupsSelector.d.ts +4 -4
  20. package/hooks/features/columnResize/columnResizeSelector.d.ts +1 -1
  21. package/hooks/features/columnResize/useGridColumnResize.js +2 -1
  22. package/hooks/features/columns/gridColumnsSelector.d.ts +12 -12
  23. package/hooks/features/density/densitySelector.d.ts +1 -1
  24. package/hooks/features/editing/useGridCellEditing.js +3 -3
  25. package/hooks/features/editing/useGridRowEditing.js +3 -3
  26. package/hooks/features/filter/gridFilterSelector.d.ts +17 -17
  27. package/hooks/features/filter/useGridFilter.js +1 -1
  28. package/hooks/features/focus/gridFocusStateSelector.d.ts +8 -8
  29. package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.d.ts +3 -3
  30. package/hooks/features/overlays/useGridOverlays.js +3 -1
  31. package/hooks/features/pagination/gridPaginationSelector.d.ts +15 -9
  32. package/hooks/features/rowSelection/gridRowSelectionSelector.d.ts +3 -3
  33. package/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  34. package/hooks/features/rowSelection/utils.d.ts +1 -1
  35. package/hooks/features/rows/gridRowSpanningSelectors.d.ts +3 -3
  36. package/hooks/features/rows/gridRowsInterfaces.d.ts +1 -8
  37. package/hooks/features/rows/gridRowsSelector.d.ts +23 -13
  38. package/hooks/features/rows/gridRowsSelector.js +0 -1
  39. package/hooks/features/rows/gridRowsUtils.js +0 -9
  40. package/hooks/features/rows/index.d.ts +1 -1
  41. package/hooks/features/rows/index.js +1 -1
  42. package/hooks/features/rows/useGridRowSpanning.d.ts +1 -1
  43. package/hooks/features/rows/useGridRowSpanning.js +16 -8
  44. package/hooks/features/rows/useGridRows.js +16 -18
  45. package/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
  46. package/hooks/features/sorting/gridSortingSelector.d.ts +10 -5
  47. package/hooks/features/sorting/gridSortingSelector.js +11 -0
  48. package/hooks/features/sorting/index.d.ts +2 -1
  49. package/hooks/features/sorting/index.js +1 -1
  50. package/hooks/features/sorting/useGridSorting.js +1 -1
  51. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +5 -5
  52. package/hooks/features/virtualization/useGridVirtualScroller.js +11 -8
  53. package/hooks/utils/useGridSelector.d.ts +4 -6
  54. package/hooks/utils/useGridSelector.js +6 -44
  55. package/index.js +1 -1
  56. package/internals/index.d.ts +3 -3
  57. package/internals/index.js +3 -3
  58. package/locales/heIL.js +14 -16
  59. package/locales/roRO.js +18 -20
  60. package/locales/trTR.js +12 -14
  61. package/models/api/gridStateApi.d.ts +1 -1
  62. package/models/controlStateItem.d.ts +2 -2
  63. package/models/events/gridEventLookup.d.ts +1 -0
  64. package/models/gridDataSource.d.ts +1 -1
  65. package/models/props/DataGridProps.d.ts +1 -9
  66. package/modern/DataGrid/DataGrid.js +5 -13
  67. package/modern/components/GridRow.js +1 -1
  68. package/modern/components/cell/GridActionsCell.js +8 -1
  69. package/modern/components/cell/GridCell.js +1 -1
  70. package/modern/components/columnSelection/GridHeaderCheckbox.js +4 -1
  71. package/modern/components/panel/GridColumnsPanel.js +1 -2
  72. package/modern/components/panel/GridPanelContent.js +7 -3
  73. package/modern/components/panel/GridPanelFooter.js +4 -3
  74. package/modern/components/panel/filterPanel/GridFilterForm.js +15 -15
  75. package/modern/constants/dataGridPropsDefaultValues.js +1 -2
  76. package/modern/hooks/core/strategyProcessing/gridStrategyProcessingApi.js +5 -1
  77. package/modern/hooks/core/strategyProcessing/useGridStrategyProcessing.js +7 -8
  78. package/modern/hooks/core/useGridStateInitialization.js +3 -3
  79. package/modern/hooks/features/columnResize/useGridColumnResize.js +2 -1
  80. package/modern/hooks/features/editing/useGridCellEditing.js +3 -3
  81. package/modern/hooks/features/editing/useGridRowEditing.js +3 -3
  82. package/modern/hooks/features/filter/useGridFilter.js +1 -1
  83. package/modern/hooks/features/overlays/useGridOverlays.js +3 -1
  84. package/modern/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  85. package/modern/hooks/features/rows/gridRowsSelector.js +0 -1
  86. package/modern/hooks/features/rows/gridRowsUtils.js +0 -9
  87. package/modern/hooks/features/rows/index.js +1 -1
  88. package/modern/hooks/features/rows/useGridRowSpanning.js +16 -8
  89. package/modern/hooks/features/rows/useGridRows.js +16 -18
  90. package/modern/hooks/features/sorting/gridSortingSelector.js +11 -0
  91. package/modern/hooks/features/sorting/index.js +1 -1
  92. package/modern/hooks/features/sorting/useGridSorting.js +1 -1
  93. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +11 -8
  94. package/modern/hooks/utils/useGridSelector.js +6 -44
  95. package/modern/index.js +1 -1
  96. package/modern/internals/index.js +3 -3
  97. package/modern/locales/heIL.js +14 -16
  98. package/modern/locales/roRO.js +18 -20
  99. package/modern/locales/trTR.js +12 -14
  100. package/modern/utils/createSelector.js +1 -120
  101. package/node/DataGrid/DataGrid.js +5 -13
  102. package/node/components/GridRow.js +1 -1
  103. package/node/components/cell/GridActionsCell.js +8 -1
  104. package/node/components/cell/GridCell.js +1 -1
  105. package/node/components/columnSelection/GridHeaderCheckbox.js +4 -1
  106. package/node/components/panel/GridColumnsPanel.js +1 -2
  107. package/node/components/panel/GridPanelContent.js +7 -3
  108. package/node/components/panel/GridPanelFooter.js +5 -4
  109. package/node/components/panel/filterPanel/GridFilterForm.js +15 -15
  110. package/node/constants/dataGridPropsDefaultValues.js +1 -2
  111. package/node/hooks/core/strategyProcessing/gridStrategyProcessingApi.js +7 -1
  112. package/node/hooks/core/strategyProcessing/useGridStrategyProcessing.js +7 -8
  113. package/node/hooks/core/useGridStateInitialization.js +3 -3
  114. package/node/hooks/features/columnResize/useGridColumnResize.js +2 -1
  115. package/node/hooks/features/editing/useGridCellEditing.js +2 -2
  116. package/node/hooks/features/editing/useGridRowEditing.js +2 -2
  117. package/node/hooks/features/filter/useGridFilter.js +1 -1
  118. package/node/hooks/features/overlays/useGridOverlays.js +3 -1
  119. package/node/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  120. package/node/hooks/features/rows/gridRowsSelector.js +1 -2
  121. package/node/hooks/features/rows/gridRowsUtils.js +0 -9
  122. package/node/hooks/features/rows/index.js +0 -7
  123. package/node/hooks/features/rows/useGridRowSpanning.js +16 -8
  124. package/node/hooks/features/rows/useGridRows.js +15 -17
  125. package/node/hooks/features/sorting/gridSortingSelector.js +12 -1
  126. package/node/hooks/features/sorting/index.js +24 -16
  127. package/node/hooks/features/sorting/useGridSorting.js +1 -1
  128. package/node/hooks/features/virtualization/useGridVirtualScroller.js +11 -8
  129. package/node/hooks/utils/useGridSelector.js +8 -47
  130. package/node/index.js +1 -1
  131. package/node/internals/index.js +15 -22
  132. package/node/locales/heIL.js +14 -16
  133. package/node/locales/roRO.js +18 -20
  134. package/node/locales/trTR.js +12 -14
  135. package/node/utils/createSelector.js +4 -125
  136. package/package.json +1 -1
  137. package/utils/createSelector.d.ts +4 -16
  138. package/utils/createSelector.js +1 -120
@@ -39,27 +39,22 @@ const GridFilterFormRoot = styled('div', {
39
39
  theme
40
40
  }) => ({
41
41
  display: 'flex',
42
- padding: theme.spacing(1)
42
+ gap: theme.spacing(1.5)
43
43
  }));
44
44
  const FilterFormDeleteIcon = styled('div', {
45
45
  name: 'MuiDataGrid',
46
46
  slot: 'FilterFormDeleteIcon',
47
47
  overridesResolver: (_, styles) => styles.filterFormDeleteIcon
48
- })(({
49
- theme
50
- }) => ({
48
+ })({
51
49
  flexShrink: 0,
52
- justifyContent: 'flex-end',
53
- marginRight: theme.spacing(0.5),
54
- marginBottom: theme.spacing(0.2)
55
- }));
50
+ justifyContent: 'center'
51
+ });
56
52
  const FilterFormLogicOperatorInput = styled('div', {
57
53
  name: 'MuiDataGrid',
58
54
  slot: 'FilterFormLogicOperatorInput',
59
55
  overridesResolver: (_, styles) => styles.filterFormLogicOperatorInput
60
56
  })({
61
- minWidth: 55,
62
- marginRight: 5,
57
+ minWidth: 75,
63
58
  justifyContent: 'end'
64
59
  });
65
60
  const FilterFormColumnInput = styled('div', {
@@ -261,7 +256,6 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
261
256
  ownerState: rootProps
262
257
  }, other, {
263
258
  children: [/*#__PURE__*/_jsx(FilterFormDeleteIcon, _extends({
264
- variant: "standard",
265
259
  as: rootProps.slots.baseFormControl
266
260
  }, baseFormControlProps, deleteIconProps, {
267
261
  className: clsx(classes.deleteIcon, baseFormControlProps.className, deleteIconProps.className),
@@ -278,7 +272,8 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
278
272
  })
279
273
  }))
280
274
  })), /*#__PURE__*/_jsx(FilterFormLogicOperatorInput, _extends({
281
- variant: "standard",
275
+ variant: "outlined",
276
+ size: "small",
282
277
  as: rootProps.slots.baseFormControl
283
278
  }, baseFormControlProps, logicOperatorInputProps, {
284
279
  sx: [hasLogicOperatorColumn ? {
@@ -308,7 +303,8 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
308
303
  }), apiRef.current.getLocaleText(getLogicOperatorLocaleKey(logicOperator))))
309
304
  }))
310
305
  })), /*#__PURE__*/_jsxs(FilterFormColumnInput, _extends({
311
- variant: "standard",
306
+ variant: "outlined",
307
+ size: "small",
312
308
  as: rootProps.slots.baseFormControl
313
309
  }, baseFormControlProps, columnInputProps, {
314
310
  className: clsx(classes.columnInput, baseFormControlProps.className, columnInputProps.className),
@@ -333,7 +329,8 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
333
329
  }), getColumnLabel(col)))
334
330
  }))]
335
331
  })), /*#__PURE__*/_jsxs(FilterFormOperatorInput, _extends({
336
- variant: "standard",
332
+ variant: "outlined",
333
+ size: "small",
337
334
  as: rootProps.slots.baseFormControl
338
335
  }, baseFormControlProps, operatorInputProps, {
339
336
  className: clsx(classes.operatorInput, baseFormControlProps.className, operatorInputProps.className),
@@ -359,12 +356,15 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
359
356
  }), operator.label || apiRef.current.getLocaleText(`filterOperator${capitalize(operator.value)}`)))
360
357
  }))]
361
358
  })), /*#__PURE__*/_jsx(FilterFormValueInput, _extends({
362
- variant: "standard",
359
+ variant: "outlined",
360
+ size: "small",
363
361
  as: rootProps.slots.baseFormControl
364
362
  }, baseFormControlProps, valueInputPropsOther, {
365
363
  className: clsx(classes.valueInput, baseFormControlProps.className, valueInputPropsOther.className),
366
364
  ownerState: rootProps,
367
365
  children: currentOperator?.InputComponent ? /*#__PURE__*/_jsx(currentOperator.InputComponent, _extends({
366
+ variant: "outlined",
367
+ size: "small",
368
368
  apiRef: apiRef,
369
369
  item: item,
370
370
  applyValue: applyFilterChanges,
@@ -45,15 +45,14 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES = {
45
45
  resizeThrottleMs: 60,
46
46
  rowBufferPx: 150,
47
47
  rowHeight: 52,
48
- rowPositionsDebounceMs: 166,
49
48
  rows: [],
50
49
  rowSelection: true,
51
50
  rowSpacingType: 'margin',
51
+ rowSpanning: false,
52
52
  showCellVerticalBorder: false,
53
53
  showColumnVerticalBorder: false,
54
54
  sortingMode: 'client',
55
55
  sortingOrder: ['asc', 'desc', null],
56
56
  throttleRowsMs: 0,
57
- unstable_rowSpanning: false,
58
57
  virtualizeColumnsWithAutoRowHeight: false
59
58
  };
@@ -1 +1,5 @@
1
- export {};
1
+ export let GridStrategyGroup = /*#__PURE__*/function (GridStrategyGroup) {
2
+ GridStrategyGroup["DataSource"] = "dataSource";
3
+ GridStrategyGroup["RowTree"] = "rowTree";
4
+ return GridStrategyGroup;
5
+ }({});
@@ -1,13 +1,15 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _toPropertyKey from "@babel/runtime/helpers/esm/toPropertyKey";
3
3
  import * as React from 'react';
4
+ import { GridStrategyGroup } from "./gridStrategyProcessingApi.js";
4
5
  import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
5
6
  export const GRID_DEFAULT_STRATEGY = 'none';
6
7
  export const GRID_STRATEGIES_PROCESSORS = {
7
- rowTreeCreation: 'rowTree',
8
- filtering: 'rowTree',
9
- sorting: 'rowTree',
10
- visibleRowsLookupCreation: 'rowTree'
8
+ dataSourceRowsUpdate: GridStrategyGroup.DataSource,
9
+ rowTreeCreation: GridStrategyGroup.RowTree,
10
+ filtering: GridStrategyGroup.RowTree,
11
+ sorting: GridStrategyGroup.RowTree,
12
+ visibleRowsLookupCreation: GridStrategyGroup.RowTree
11
13
  };
12
14
  /**
13
15
  * Implements a variant of the Strategy Pattern (see https://en.wikipedia.org/wiki/Strategy_pattern)
@@ -44,10 +46,7 @@ export const GRID_STRATEGIES_PROCESSORS = {
44
46
  * =====================================================================================================================
45
47
  *
46
48
  * Each processor name is part of a strategy group which can only have one active strategy at the time.
47
- * For now, there is only one strategy group named `rowTree` which customize
48
- * - row tree creation algorithm.
49
- * - sorting algorithm.
50
- * - filtering algorithm.
49
+ * There are two active groups named `rowTree` and `dataSource`.
51
50
  */
52
51
  export const useGridStrategyProcessing = apiRef => {
53
52
  const availableStrategies = React.useRef(new Map());
@@ -24,8 +24,8 @@ export const useGridStateInitialization = apiRef => {
24
24
  const updatedControlStateIds = [];
25
25
  Object.keys(controlStateMapRef.current).forEach(stateId => {
26
26
  const controlState = controlStateMapRef.current[stateId];
27
- const oldSubState = controlState.stateSelector(apiRef.current.state, apiRef.current.instanceId);
28
- const newSubState = controlState.stateSelector(newState, apiRef.current.instanceId);
27
+ const oldSubState = controlState.stateSelector(apiRef.current.state, undefined, apiRef.current.instanceId);
28
+ const newSubState = controlState.stateSelector(newState, undefined, apiRef.current.instanceId);
29
29
  if (newSubState === oldSubState) {
30
30
  return;
31
31
  }
@@ -57,7 +57,7 @@ export const useGridStateInitialization = apiRef => {
57
57
  hasPropChanged
58
58
  } = updatedControlStateIds[0];
59
59
  const controlState = controlStateMapRef.current[stateId];
60
- const model = controlState.stateSelector(newState, apiRef.current.instanceId);
60
+ const model = controlState.stateSelector(newState, undefined, apiRef.current.instanceId);
61
61
  if (controlState.propOnChange && hasPropChanged) {
62
62
  controlState.propOnChange(model, {
63
63
  reason,
@@ -491,7 +491,8 @@ export const useGridColumnResize = (apiRef, props) => {
491
491
  const widthByField = extractColumnWidths(apiRef, options, columns);
492
492
  const newColumns = columns.map(column => _extends({}, column, {
493
493
  width: widthByField[column.field],
494
- computedWidth: widthByField[column.field]
494
+ computedWidth: widthByField[column.field],
495
+ flex: 0
495
496
  }));
496
497
  if (options.expand) {
497
498
  const visibleColumns = state.orderedFields.map(field => state.lookup[field]).filter(c => state.columnVisibilityModel[c.field] !== false);
@@ -11,7 +11,7 @@ import { GridEditModes, GridCellModes } from "../../../models/gridEditRowModel.j
11
11
  import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
12
12
  import { gridEditRowsStateSelector } from "./gridEditingSelectors.js";
13
13
  import { isPrintableKey, isPasteShortcut } from "../../../utils/keyboardUtils.js";
14
- import { gridRowsDataRowIdToIdLookupSelector } from "../rows/gridRowsSelector.js";
14
+ import { gridRowsLookupSelector } from "../rows/gridRowsSelector.js";
15
15
  import { deepClone } from "../../../utils/utils.js";
16
16
  import { GridCellEditStartReasons, GridCellEditStopReasons } from "../../../models/params/gridEditCellParams.js";
17
17
  import { getDefaultCellValue } from "./utils.js";
@@ -442,7 +442,7 @@ export const useGridCellEditing = (apiRef, props) => {
442
442
 
443
443
  // Run this effect synchronously so that the keyboard event can impact the yet-to-be-rendered input.
444
444
  useEnhancedEffect(() => {
445
- const idToIdLookup = gridRowsDataRowIdToIdLookupSelector(apiRef);
445
+ const rowsLookup = gridRowsLookupSelector(apiRef);
446
446
 
447
447
  // Update the ref here because updateStateToStopCellEditMode may change it later
448
448
  const copyOfPrevCellModes = prevCellModesModel.current;
@@ -451,7 +451,7 @@ export const useGridCellEditing = (apiRef, props) => {
451
451
  Object.entries(cellModesModel).forEach(([id, fields]) => {
452
452
  Object.entries(fields).forEach(([field, params]) => {
453
453
  const prevMode = copyOfPrevCellModes[id]?.[field]?.mode || GridCellModes.View;
454
- const originalId = idToIdLookup[id] ?? id;
454
+ const originalId = apiRef.current.getRowId(rowsLookup[id]) ?? id;
455
455
  if (params.mode === GridCellModes.Edit && prevMode === GridCellModes.View) {
456
456
  updateStateToStartCellEditMode(_extends({
457
457
  id: originalId,
@@ -12,7 +12,7 @@ import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
12
12
  import { gridEditRowsStateSelector } from "./gridEditingSelectors.js";
13
13
  import { isPrintableKey, isPasteShortcut } from "../../../utils/keyboardUtils.js";
14
14
  import { gridColumnFieldsSelector, gridVisibleColumnFieldsSelector } from "../columns/gridColumnsSelector.js";
15
- import { gridRowsDataRowIdToIdLookupSelector } from "../rows/gridRowsSelector.js";
15
+ import { gridRowsLookupSelector } from "../rows/gridRowsSelector.js";
16
16
  import { deepClone } from "../../../utils/utils.js";
17
17
  import { GridRowEditStopReasons, GridRowEditStartReasons } from "../../../models/params/gridRowParams.js";
18
18
  import { GRID_ACTIONS_COLUMN_TYPE } from "../../../colDef/index.js";
@@ -571,7 +571,7 @@ export const useGridRowEditing = (apiRef, props) => {
571
571
 
572
572
  // Run this effect synchronously so that the keyboard event can impact the yet-to-be-rendered input.
573
573
  useEnhancedEffect(() => {
574
- const idToIdLookup = gridRowsDataRowIdToIdLookupSelector(apiRef);
574
+ const rowsLookup = gridRowsLookupSelector(apiRef);
575
575
 
576
576
  // Update the ref here because updateStateToStopRowEditMode may change it later
577
577
  const copyOfPrevRowModesModel = prevRowModesModel.current;
@@ -583,7 +583,7 @@ export const useGridRowEditing = (apiRef, props) => {
583
583
  mode: GridRowModes.View
584
584
  };
585
585
  const prevMode = copyOfPrevRowModesModel[id]?.mode || GridRowModes.View;
586
- const originalId = idToIdLookup[id] ?? id;
586
+ const originalId = apiRef.current.getRowId(rowsLookup[id]) ?? id;
587
587
  if (params.mode === GridRowModes.Edit && prevMode === GridRowModes.View) {
588
588
  updateStateToStartRowEditMode(_extends({
589
589
  id: originalId
@@ -59,7 +59,7 @@ export const useGridFilter = (apiRef, props) => {
59
59
  });
60
60
  const updateFilteredRows = React.useCallback(() => {
61
61
  apiRef.current.setState(state => {
62
- const filterModel = gridFilterModelSelector(state, apiRef.current.instanceId);
62
+ const filterModel = gridFilterModelSelector(state, undefined, apiRef.current.instanceId);
63
63
  const filterState = apiRef.current.getFilterState(filterModel);
64
64
  const newState = _extends({}, state, {
65
65
  filter: _extends({}, state.filter, filterState)
@@ -5,6 +5,7 @@ import { useGridApiContext } from "../../utils/useGridApiContext.js";
5
5
  import { useGridRootProps } from "../../utils/useGridRootProps.js";
6
6
  import { gridExpandedRowCountSelector } from "../filter/index.js";
7
7
  import { gridRowCountSelector, gridRowsLoadingSelector } from "../rows/index.js";
8
+ import { gridPinnedRowsCountSelector } from "../rows/gridRowsSelector.js";
8
9
  import { GridOverlayWrapper } from "../../../components/base/GridOverlays.js";
9
10
  import { jsx as _jsx } from "react/jsx-runtime";
10
11
  /**
@@ -16,7 +17,8 @@ export const useGridOverlays = () => {
16
17
  const rootProps = useGridRootProps();
17
18
  const totalRowCount = useGridSelector(apiRef, gridRowCountSelector);
18
19
  const visibleRowCount = useGridSelector(apiRef, gridExpandedRowCountSelector);
19
- const noRows = totalRowCount === 0;
20
+ const pinnedRowsCount = useGridSelector(apiRef, gridPinnedRowsCountSelector);
21
+ const noRows = totalRowCount === 0 && pinnedRowsCount === 0;
20
22
  const loading = useGridSelector(apiRef, gridRowsLoadingSelector);
21
23
  const showNoRowsOverlay = !loading && noRows;
22
24
  const showNoResultsOverlay = !loading && totalRowCount > 0 && visibleRowCount === 0;
@@ -313,11 +313,12 @@ export const useGridRowSelection = (apiRef, props) => {
313
313
 
314
314
  const isMultipleSelectionDisabled = !checkboxSelection && !hasCtrlKey && !isKeyboardEvent(event);
315
315
  const resetSelection = !canHaveMultipleSelection || isMultipleSelectionDisabled;
316
- const isSelected = apiRef.current.isRowSelected(id);
317
- if (resetSelection) {
318
- apiRef.current.selectRow(id, !isMultipleSelectionDisabled ? !isSelected : true, true);
316
+ const selectedRowsCount = apiRef.current.getSelectedRows().size;
317
+ if (canHaveMultipleSelection && selectedRowsCount > 1 && !hasCtrlKey) {
318
+ apiRef.current.selectRow(id, true, resetSelection);
319
319
  } else {
320
- apiRef.current.selectRow(id, !isSelected, false);
320
+ const isSelected = apiRef.current.isRowSelected(id);
321
+ apiRef.current.selectRow(id, !isSelected, resetSelection);
321
322
  }
322
323
  }, [apiRef, canHaveMultipleSelection, checkboxSelection]);
323
324
  const handleRowClick = React.useCallback((params, event) => {
@@ -6,7 +6,6 @@ export const gridTopLevelRowCountSelector = createSelector(gridRowsStateSelector
6
6
 
7
7
  // TODO rows v6: Rename
8
8
  export const gridRowsLookupSelector = createSelector(gridRowsStateSelector, rows => rows.dataRowIdToModelLookup);
9
- export const gridRowsDataRowIdToIdLookupSelector = createSelector(gridRowsStateSelector, rows => rows.dataRowIdToIdLookup);
10
9
  export const gridRowTreeSelector = createSelector(gridRowsStateSelector, rows => rows.tree);
11
10
  export const gridRowGroupsToFetchSelector = createSelector(gridRowsStateSelector, rows => rows.groupsToFetch);
12
11
  export const gridRowGroupingNameSelector = createSelector(gridRowsStateSelector, rows => rows.groupingName);
@@ -42,12 +42,10 @@ export const createRowsInternalCache = ({
42
42
  rows: []
43
43
  };
44
44
  const dataRowIdToModelLookup = {};
45
- const dataRowIdToIdLookup = {};
46
45
  for (let i = 0; i < rows.length; i += 1) {
47
46
  const model = rows[i];
48
47
  const id = getRowIdFromRowModel(model, getRowId);
49
48
  dataRowIdToModelLookup[id] = model;
50
- dataRowIdToIdLookup[id] = id;
51
49
  updates.rows.push(id);
52
50
  }
53
51
  return {
@@ -55,7 +53,6 @@ export const createRowsInternalCache = ({
55
53
  loadingPropBeforePartialUpdates: loading,
56
54
  rowCountPropBeforePartialUpdates: rowCount,
57
55
  updates,
58
- dataRowIdToIdLookup,
59
56
  dataRowIdToModelLookup
60
57
  };
61
58
  };
@@ -87,7 +84,6 @@ export const getRowsStateFromCache = ({
87
84
  previousTree,
88
85
  previousTreeDepths,
89
86
  updates: cache.updates,
90
- dataRowIdToIdLookup: cache.dataRowIdToIdLookup,
91
87
  dataRowIdToModelLookup: cache.dataRowIdToModelLookup,
92
88
  previousGroupsToFetch
93
89
  });
@@ -96,7 +92,6 @@ export const getRowsStateFromCache = ({
96
92
  const groupingParamsWithHydrateRows = apiRef.current.unstable_applyPipeProcessors('hydrateRows', {
97
93
  tree: unProcessedTree,
98
94
  treeDepths: unProcessedTreeDepths,
99
- dataRowIdToIdLookup: cache.dataRowIdToIdLookup,
100
95
  dataRowIds: unProcessedDataRowIds,
101
96
  dataRowIdToModelLookup: cache.dataRowIdToModelLookup
102
97
  });
@@ -177,7 +172,6 @@ export const updateCacheWithNewRows = ({
177
172
  groupKeys
178
173
  };
179
174
  const dataRowIdToModelLookup = _extends({}, previousCache.dataRowIdToModelLookup);
180
- const dataRowIdToIdLookup = _extends({}, previousCache.dataRowIdToIdLookup);
181
175
  const alreadyAppliedActionsToRemove = {
182
176
  insert: {},
183
177
  modify: {},
@@ -210,7 +204,6 @@ export const updateCacheWithNewRows = ({
210
204
  // Remove the data row from the lookups and add it to the "delete" update.
211
205
  partialUpdates.actions.remove.push(id);
212
206
  delete dataRowIdToModelLookup[id];
213
- delete dataRowIdToIdLookup[id];
214
207
  return;
215
208
  }
216
209
  const oldRow = dataRowIdToModelLookup[id];
@@ -250,7 +243,6 @@ export const updateCacheWithNewRows = ({
250
243
 
251
244
  // Update the data row lookups.
252
245
  dataRowIdToModelLookup[id] = partialRow;
253
- dataRowIdToIdLookup[id] = id;
254
246
  });
255
247
  const actionTypeWithActionsToRemove = Object.keys(alreadyAppliedActionsToRemove);
256
248
  for (let i = 0; i < actionTypeWithActionsToRemove.length; i += 1) {
@@ -262,7 +254,6 @@ export const updateCacheWithNewRows = ({
262
254
  }
263
255
  return {
264
256
  dataRowIdToModelLookup,
265
- dataRowIdToIdLookup,
266
257
  updates: partialUpdates,
267
258
  rowsBeforePartialUpdates: previousCache.rowsBeforePartialUpdates,
268
259
  loadingPropBeforePartialUpdates: previousCache.loadingPropBeforePartialUpdates,
@@ -1,4 +1,4 @@
1
1
  export * from "./gridRowsMetaSelector.js";
2
2
  export * from "./gridRowsMetaState.js";
3
- export { gridRowCountSelector, gridRowsLoadingSelector, gridTopLevelRowCountSelector, gridRowsLookupSelector, gridRowsDataRowIdToIdLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridRowMaximumTreeDepthSelector, gridDataRowIdsSelector } from "./gridRowsSelector.js";
3
+ export { gridRowCountSelector, gridRowsLoadingSelector, gridTopLevelRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridRowMaximumTreeDepthSelector, gridDataRowIdsSelector } from "./gridRowsSelector.js";
4
4
  export { GRID_ROOT_GROUP_ID, checkGridRowIdIsValid, isAutogeneratedRow } from "./gridRowsUtils.js";
@@ -6,6 +6,7 @@ import { gridVisibleColumnDefinitionsSelector } from "../columns/gridColumnsSele
6
6
  import { useGridVisibleRows } from "../../utils/useGridVisibleRows.js";
7
7
  import { gridRenderContextSelector } from "../virtualization/gridVirtualizationSelectors.js";
8
8
  import { useGridSelector } from "../../utils/useGridSelector.js";
9
+ import { gridRowTreeSelector } from "./gridRowsSelector.js";
9
10
  import { getUnprocessedRange, isRowRangeUpdated, isRowContextInitialized, getCellValue } from "./gridRowSpanningUtils.js";
10
11
  import { GRID_CHECKBOX_SELECTION_FIELD } from "../../../colDef/gridCheckboxSelectionColDef.js";
11
12
  const EMPTY_STATE = {
@@ -35,7 +36,7 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
35
36
  if (skippedFields.has(colDef.field)) {
36
37
  return;
37
38
  }
38
- for (let index = rangeToProcess.firstRowIndex; index <= rangeToProcess.lastRowIndex; index += 1) {
39
+ for (let index = rangeToProcess.firstRowIndex; index < rangeToProcess.lastRowIndex; index += 1) {
39
40
  const row = visibleRows[index];
40
41
  if (hiddenCells[row.id]?.[colDef.field]) {
41
42
  continue;
@@ -129,7 +130,7 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
129
130
  * @requires filterStateInitializer (method) - should be initialized before
130
131
  */
131
132
  export const rowSpanningStateInitializer = (state, props, apiRef) => {
132
- if (props.unstable_rowSpanning) {
133
+ if (props.rowSpanning) {
133
134
  const rowIds = state.rows.dataRowIds || [];
134
135
  const orderedFields = state.columns.orderedFields || [];
135
136
  const dataRowIdToModelLookup = state.rows.dataRowIdToModelLookup;
@@ -142,7 +143,7 @@ export const rowSpanningStateInitializer = (state, props, apiRef) => {
142
143
  }
143
144
  const rangeToProcess = {
144
145
  firstRowIndex: 0,
145
- lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS - 1, Math.max(rowIds.length - 1, 0))
146
+ lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS, Math.max(rowIds.length, 0))
146
147
  };
147
148
  const rows = rowIds.map(id => ({
148
149
  id,
@@ -173,10 +174,11 @@ export const useGridRowSpanning = (apiRef, props) => {
173
174
  } = useGridVisibleRows(apiRef, props);
174
175
  const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
175
176
  const colDefs = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
177
+ const tree = useGridSelector(apiRef, gridRowTreeSelector);
176
178
  const processedRange = useLazyRef(() => {
177
179
  return Object.keys(apiRef.current.state.rowSpanning.spannedCells).length > 0 ? {
178
180
  firstRowIndex: 0,
179
- lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS - 1, Math.max(apiRef.current.state.rows.dataRowIds.length - 1, 0))
181
+ lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS, Math.max(apiRef.current.state.rows.dataRowIds.length, 0))
180
182
  } : EMPTY_RANGE;
181
183
  });
182
184
  const lastRange = React.useRef(EMPTY_RANGE);
@@ -188,7 +190,7 @@ export const useGridRowSpanning = (apiRef, props) => {
188
190
  // - The `paginationModel` is updated
189
191
  // - The rows are updated
190
192
  (resetState = true) => {
191
- if (!props.unstable_rowSpanning) {
193
+ if (!props.rowSpanning) {
192
194
  if (apiRef.current.state.rowSpanning !== EMPTY_STATE) {
193
195
  apiRef.current.setState(state => _extends({}, state, {
194
196
  rowSpanning: EMPTY_STATE
@@ -204,7 +206,7 @@ export const useGridRowSpanning = (apiRef, props) => {
204
206
  }
205
207
  const rangeToProcess = getUnprocessedRange({
206
208
  firstRowIndex: renderContext.firstRowIndex,
207
- lastRowIndex: Math.min(renderContext.lastRowIndex - 1, range.lastRowIndex)
209
+ lastRowIndex: Math.min(renderContext.lastRowIndex, range.lastRowIndex + 1)
208
210
  }, processedRange.current);
209
211
  if (rangeToProcess === null) {
210
212
  return;
@@ -233,15 +235,21 @@ export const useGridRowSpanning = (apiRef, props) => {
233
235
  }
234
236
  });
235
237
  });
236
- }, [apiRef, props.unstable_rowSpanning, range, renderContext, visibleRows, colDefs, processedRange]);
238
+ }, [apiRef, props.rowSpanning, range, renderContext, visibleRows, colDefs, processedRange]);
237
239
  const prevRenderContext = React.useRef(renderContext);
238
240
  const isFirstRender = React.useRef(true);
239
241
  const shouldResetState = React.useRef(false);
242
+ const previousTree = React.useRef(tree);
240
243
  React.useEffect(() => {
241
244
  const firstRender = isFirstRender.current;
242
245
  if (isFirstRender.current) {
243
246
  isFirstRender.current = false;
244
247
  }
248
+ if (tree !== previousTree.current) {
249
+ previousTree.current = tree;
250
+ updateRowSpanningState(true);
251
+ return;
252
+ }
245
253
  if (range && lastRange.current && isRowRangeUpdated(range, lastRange.current)) {
246
254
  lastRange.current = range;
247
255
  shouldResetState.current = true;
@@ -255,5 +263,5 @@ export const useGridRowSpanning = (apiRef, props) => {
255
263
  return;
256
264
  }
257
265
  updateRowSpanningState();
258
- }, [updateRowSpanningState, renderContext, range, lastRange]);
266
+ }, [updateRowSpanningState, renderContext, range, lastRange, tree]);
259
267
  };
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import useLazyRef from '@mui/utils/useLazyRef';
4
4
  import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
5
5
  import { useGridLogger } from "../../utils/useGridLogger.js";
6
- import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridDataRowIdsSelector, gridRowsDataRowIdToIdLookupSelector, gridRowMaximumTreeDepthSelector, gridRowGroupsToFetchSelector } from "./gridRowsSelector.js";
6
+ import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowGroupingNameSelector, gridRowTreeDepthsSelector, gridDataRowIdsSelector, gridRowMaximumTreeDepthSelector, gridRowGroupsToFetchSelector } from "./gridRowsSelector.js";
7
7
  import { useTimeout } from "../../utils/useTimeout.js";
8
8
  import { GridSignature, useGridApiEventHandler } from "../../utils/useGridApiEventHandler.js";
9
9
  import { useGridVisibleRows } from "../../utils/useGridVisibleRows.js";
@@ -11,6 +11,7 @@ import { gridSortedRowIdsSelector } from "../sorting/gridSortingSelector.js";
11
11
  import { gridFilteredRowsLookupSelector } from "../filter/gridFilterSelector.js";
12
12
  import { getTreeNodeDescendants, createRowsInternalCache, getRowsStateFromCache, isAutogeneratedRowNode, GRID_ROOT_GROUP_ID, GRID_ID_AUTOGENERATED, updateCacheWithNewRows, getTopLevelRowCount, getRowIdFromRowModel, computeRowsUpdates } from "./gridRowsUtils.js";
13
13
  import { useGridRegisterPipeApplier } from "../../core/pipeProcessing/index.js";
14
+ import { GridStrategyGroup } from "../../core/strategyProcessing/index.js";
14
15
  export const rowsStateInitializer = (state, props, apiRef) => {
15
16
  const isDataSourceAvailable = !!props.unstable_dataSource;
16
17
  apiRef.current.caches.rows = createRowsInternalCache({
@@ -238,7 +239,7 @@ export const useGridRows = (apiRef, props) => {
238
239
  throw new Error(`MUI X: The row reordering do not support reordering of footer or grouping rows.`);
239
240
  }
240
241
  apiRef.current.setState(state => {
241
- const group = gridRowTreeSelector(state, apiRef.current.instanceId)[GRID_ROOT_GROUP_ID];
242
+ const group = gridRowTreeSelector(state, undefined, apiRef.current.instanceId)[GRID_ROOT_GROUP_ID];
242
243
  const allRows = group.children;
243
244
  const oldIndex = allRows.findIndex(row => row === rowId);
244
245
  if (oldIndex === -1 || oldIndex === targetIndex) {
@@ -272,7 +273,6 @@ export const useGridRows = (apiRef, props) => {
272
273
  }
273
274
  const tree = _extends({}, gridRowTreeSelector(apiRef));
274
275
  const dataRowIdToModelLookup = _extends({}, gridRowsLookupSelector(apiRef));
275
- const dataRowIdToIdLookup = _extends({}, gridRowsDataRowIdToIdLookupSelector(apiRef));
276
276
  const rootGroup = tree[GRID_ROOT_GROUP_ID];
277
277
  const rootGroupChildren = [...rootGroup.children];
278
278
  const seenIds = new Set();
@@ -282,7 +282,6 @@ export const useGridRows = (apiRef, props) => {
282
282
  const [removedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
283
283
  if (!seenIds.has(removedRowId)) {
284
284
  delete dataRowIdToModelLookup[removedRowId];
285
- delete dataRowIdToIdLookup[removedRowId];
286
285
  delete tree[removedRowId];
287
286
  }
288
287
  const rowTreeNodeConfig = {
@@ -293,7 +292,6 @@ export const useGridRows = (apiRef, props) => {
293
292
  groupingKey: null
294
293
  };
295
294
  dataRowIdToModelLookup[rowId] = rowModel;
296
- dataRowIdToIdLookup[rowId] = rowId;
297
295
  tree[rowId] = rowTreeNodeConfig;
298
296
  seenIds.add(rowId);
299
297
  }
@@ -304,17 +302,17 @@ export const useGridRows = (apiRef, props) => {
304
302
  // Removes potential remaining skeleton rows from the dataRowIds.
305
303
  const dataRowIds = rootGroupChildren.filter(childId => tree[childId]?.type === 'leaf');
306
304
  apiRef.current.caches.rows.dataRowIdToModelLookup = dataRowIdToModelLookup;
307
- apiRef.current.caches.rows.dataRowIdToIdLookup = dataRowIdToIdLookup;
308
305
  apiRef.current.setState(state => _extends({}, state, {
309
306
  rows: _extends({}, state.rows, {
307
+ loading: props.loading,
308
+ totalRowCount: Math.max(props.rowCount || 0, rootGroupChildren.length),
310
309
  dataRowIdToModelLookup,
311
- dataRowIdToIdLookup,
312
310
  dataRowIds,
313
311
  tree
314
312
  })
315
313
  }));
316
314
  apiRef.current.publishEvent('rowsSet');
317
- }, [apiRef, props.signature, props.getRowId]);
315
+ }, [apiRef, props.signature, props.getRowId, props.loading, props.rowCount]);
318
316
  const rowApi = {
319
317
  getRow,
320
318
  setLoading,
@@ -381,7 +379,7 @@ export const useGridRows = (apiRef, props) => {
381
379
  const handleStrategyActivityChange = React.useCallback(() => {
382
380
  // `rowTreeCreation` is the only processor ran when `strategyAvailabilityChange` is fired.
383
381
  // All the other processors listen to `rowsSet` which will be published by the `groupRows` method below.
384
- if (apiRef.current.getActiveStrategy('rowTree') !== gridRowGroupingNameSelector(apiRef)) {
382
+ if (apiRef.current.getActiveStrategy(GridStrategyGroup.RowTree) !== gridRowGroupingNameSelector(apiRef)) {
385
383
  groupRows();
386
384
  }
387
385
  }, [apiRef, groupRows]);
@@ -394,11 +392,10 @@ export const useGridRows = (apiRef, props) => {
394
392
  const applyHydrateRowsProcessor = React.useCallback(() => {
395
393
  apiRef.current.setState(state => {
396
394
  const response = apiRef.current.unstable_applyPipeProcessors('hydrateRows', {
397
- tree: gridRowTreeSelector(state, apiRef.current.instanceId),
398
- treeDepths: gridRowTreeDepthsSelector(state, apiRef.current.instanceId),
399
- dataRowIds: gridDataRowIdsSelector(state, apiRef.current.instanceId),
400
- dataRowIdToModelLookup: gridRowsLookupSelector(state, apiRef.current.instanceId),
401
- dataRowIdToIdLookup: gridRowsDataRowIdToIdLookupSelector(state, apiRef.current.instanceId)
395
+ tree: gridRowTreeSelector(state, undefined, apiRef.current.instanceId),
396
+ treeDepths: gridRowTreeDepthsSelector(state, undefined, apiRef.current.instanceId),
397
+ dataRowIds: gridDataRowIdsSelector(state, undefined, apiRef.current.instanceId),
398
+ dataRowIdToModelLookup: gridRowsLookupSelector(state, undefined, apiRef.current.instanceId)
402
399
  });
403
400
  return _extends({}, state, {
404
401
  rows: _extends({}, state.rows, response, {
@@ -430,7 +427,8 @@ export const useGridRows = (apiRef, props) => {
430
427
  isRowCountPropUpdated = true;
431
428
  lastRowCount.current = props.rowCount;
432
429
  }
433
- const areNewRowsAlreadyInState = apiRef.current.caches.rows.rowsBeforePartialUpdates === props.rows;
430
+ const currentRows = props.unstable_dataSource ? Array.from(apiRef.current.getRowModels().values()) : props.rows;
431
+ const areNewRowsAlreadyInState = apiRef.current.caches.rows.rowsBeforePartialUpdates === currentRows;
434
432
  const isNewLoadingAlreadyInState = apiRef.current.caches.rows.loadingPropBeforePartialUpdates === props.loading;
435
433
  const isNewRowCountAlreadyInState = apiRef.current.caches.rows.rowCountPropBeforePartialUpdates === props.rowCount;
436
434
 
@@ -460,15 +458,15 @@ export const useGridRows = (apiRef, props) => {
460
458
  return;
461
459
  }
462
460
  }
463
- logger.debug(`Updating all rows, new length ${props.rows?.length}`);
461
+ logger.debug(`Updating all rows, new length ${currentRows?.length}`);
464
462
  throttledRowsChange({
465
463
  cache: createRowsInternalCache({
466
- rows: props.rows,
464
+ rows: currentRows,
467
465
  getRowId: props.getRowId,
468
466
  loading: props.loading,
469
467
  rowCount: props.rowCount
470
468
  }),
471
469
  throttle: false
472
470
  });
473
- }, [props.rows, props.rowCount, props.getRowId, props.loading, logger, throttledRowsChange, apiRef]);
471
+ }, [props.rows, props.rowCount, props.getRowId, props.loading, props.unstable_dataSource, logger, throttledRowsChange, apiRef]);
474
472
  };
@@ -55,4 +55,15 @@ export const gridSortColumnLookupSelector = createSelectorMemoized(gridSortModel
55
55
  return res;
56
56
  }, {});
57
57
  return result;
58
+ });
59
+
60
+ /**
61
+ * @category Sorting
62
+ * @ignore - do not document.
63
+ */
64
+ export const gridSortedRowIndexLookupSelector = createSelectorMemoized(gridSortedRowIdsSelector, sortedIds => {
65
+ return sortedIds.reduce((acc, id, index) => {
66
+ acc[id] = index;
67
+ return acc;
68
+ }, Object.create(null));
58
69
  });
@@ -1,2 +1,2 @@
1
- export * from "./gridSortingSelector.js";
1
+ export { gridSortedRowIdsSelector, gridSortedRowEntriesSelector, gridSortModelSelector, gridSortColumnLookupSelector } from "./gridSortingSelector.js";
2
2
  export { gridDateComparator, gridNumberComparator, gridStringOrNumberComparator } from "./gridSortingUtils.js";
@@ -88,7 +88,7 @@ export const useGridSorting = (apiRef, props) => {
88
88
  })
89
89
  });
90
90
  }
91
- const sortModel = gridSortModelSelector(state, apiRef.current.instanceId);
91
+ const sortModel = gridSortModelSelector(state, undefined, apiRef.current.instanceId);
92
92
  const sortRowList = buildAggregatedSortingApplier(sortModel, apiRef);
93
93
  const sortedRows = apiRef.current.applyStrategyProcessor('sorting', {
94
94
  sortRowList
@@ -92,10 +92,7 @@ export const useGridVirtualScroller = () => {
92
92
  return undefined;
93
93
  }
94
94
  const initialRect = node.getBoundingClientRect();
95
- let lastSize = {
96
- width: initialRect.width,
97
- height: initialRect.height
98
- };
95
+ let lastSize = roundDimensions(initialRect);
99
96
  apiRef.current.publishEvent('resize', lastSize);
100
97
  if (typeof ResizeObserver === 'undefined') {
101
98
  return undefined;
@@ -105,10 +102,7 @@ export const useGridVirtualScroller = () => {
105
102
  if (!entry) {
106
103
  return;
107
104
  }
108
- const newSize = {
109
- width: entry.contentRect.width,
110
- height: entry.contentRect.height
111
- };
105
+ const newSize = roundDimensions(entry.contentRect);
112
106
  if (newSize.width === lastSize.width && newSize.height === lastSize.height) {
113
107
  return;
114
108
  }
@@ -784,4 +778,13 @@ function bufferForDirection(isRtl, direction, rowBufferPx, columnBufferPx, verti
784
778
  // eslint unable to figure out enum exhaustiveness
785
779
  throw new Error('unreachable');
786
780
  }
781
+ }
782
+
783
+ // Round to avoid issues with subpixel rendering
784
+ // https://github.com/mui/mui-x/issues/15721
785
+ function roundDimensions(dimensions) {
786
+ return {
787
+ width: Math.round(dimensions.width * 10) / 10,
788
+ height: Math.round(dimensions.height * 10) / 10
789
+ };
787
790
  }