@mui/x-data-grid 7.24.1 → 7.25.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 (118) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/DataGrid/DataGrid.js +1 -7
  3. package/components/GridRow.d.ts +0 -1
  4. package/components/GridRow.js +25 -19
  5. package/components/cell/GridCell.d.ts +9 -6
  6. package/components/cell/GridCell.js +29 -52
  7. package/components/containers/GridRootStyles.js +135 -37
  8. package/components/toolbar/GridToolbarColumnsButton.js +5 -4
  9. package/components/toolbar/GridToolbarDensitySelector.js +2 -2
  10. package/components/toolbar/GridToolbarExportContainer.js +2 -2
  11. package/components/toolbar/GridToolbarFilterButton.js +4 -3
  12. package/components/virtualization/GridMainContainer.d.ts +10 -0
  13. package/components/virtualization/GridMainContainer.js +10 -2
  14. package/components/virtualization/GridVirtualScrollbar.d.ts +4 -0
  15. package/components/virtualization/GridVirtualScrollbar.js +5 -5
  16. package/components/virtualization/GridVirtualScroller.js +18 -5
  17. package/components/virtualization/GridVirtualScrollerContent.js +11 -2
  18. package/hooks/features/columnResize/useGridColumnResize.js +2 -1
  19. package/hooks/features/columns/useGridColumns.js +7 -3
  20. package/hooks/features/dimensions/useGridDimensions.js +6 -8
  21. package/hooks/features/editing/gridEditingSelectors.d.ts +6 -0
  22. package/hooks/features/editing/gridEditingSelectors.js +7 -1
  23. package/hooks/features/editing/index.d.ts +1 -1
  24. package/hooks/features/editing/index.js +1 -1
  25. package/hooks/features/editing/useGridCellEditing.js +3 -3
  26. package/hooks/features/editing/useGridRowEditing.js +5 -6
  27. package/hooks/features/focus/useGridFocus.js +3 -2
  28. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +24 -16
  29. package/hooks/features/keyboardNavigation/utils.d.ts +1 -2
  30. package/hooks/features/keyboardNavigation/utils.js +0 -5
  31. package/hooks/features/listView/useGridListView.js +2 -1
  32. package/hooks/features/rowSelection/useGridRowSelection.js +3 -3
  33. package/hooks/features/rows/useGridParamsApi.d.ts +1 -1
  34. package/hooks/features/rows/useGridParamsApi.js +33 -14
  35. package/hooks/features/rows/useGridRowSpanning.js +94 -91
  36. package/hooks/features/rows/useGridRows.js +7 -8
  37. package/hooks/features/rows/useGridRowsMeta.js +3 -2
  38. package/hooks/features/virtualization/gridFocusedVirtualCellSelector.js +2 -2
  39. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +9 -1
  40. package/hooks/features/virtualization/useGridVirtualScroller.js +31 -45
  41. package/index.js +1 -1
  42. package/models/api/gridApiCommon.d.ts +2 -2
  43. package/models/api/gridParamsApi.d.ts +29 -2
  44. package/models/api/index.d.ts +1 -1
  45. package/models/api/index.js +0 -1
  46. package/modern/DataGrid/DataGrid.js +1 -7
  47. package/modern/components/GridRow.js +25 -19
  48. package/modern/components/cell/GridCell.js +29 -52
  49. package/modern/components/containers/GridRootStyles.js +135 -37
  50. package/modern/components/toolbar/GridToolbarColumnsButton.js +5 -4
  51. package/modern/components/toolbar/GridToolbarDensitySelector.js +2 -2
  52. package/modern/components/toolbar/GridToolbarExportContainer.js +2 -2
  53. package/modern/components/toolbar/GridToolbarFilterButton.js +4 -3
  54. package/modern/components/virtualization/GridMainContainer.js +10 -2
  55. package/modern/components/virtualization/GridVirtualScrollbar.js +5 -5
  56. package/modern/components/virtualization/GridVirtualScroller.js +18 -5
  57. package/modern/components/virtualization/GridVirtualScrollerContent.js +11 -2
  58. package/modern/hooks/features/columnResize/useGridColumnResize.js +2 -1
  59. package/modern/hooks/features/columns/useGridColumns.js +7 -3
  60. package/modern/hooks/features/dimensions/useGridDimensions.js +6 -8
  61. package/modern/hooks/features/editing/gridEditingSelectors.js +7 -1
  62. package/modern/hooks/features/editing/index.js +1 -1
  63. package/modern/hooks/features/editing/useGridCellEditing.js +3 -3
  64. package/modern/hooks/features/editing/useGridRowEditing.js +5 -6
  65. package/modern/hooks/features/focus/useGridFocus.js +3 -2
  66. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +24 -16
  67. package/modern/hooks/features/keyboardNavigation/utils.js +0 -5
  68. package/modern/hooks/features/listView/useGridListView.js +2 -1
  69. package/modern/hooks/features/rowSelection/useGridRowSelection.js +3 -3
  70. package/modern/hooks/features/rows/useGridParamsApi.js +33 -14
  71. package/modern/hooks/features/rows/useGridRowSpanning.js +94 -91
  72. package/modern/hooks/features/rows/useGridRows.js +7 -8
  73. package/modern/hooks/features/rows/useGridRowsMeta.js +3 -2
  74. package/modern/hooks/features/virtualization/gridFocusedVirtualCellSelector.js +2 -2
  75. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +31 -45
  76. package/modern/index.js +1 -1
  77. package/modern/models/api/index.js +0 -1
  78. package/modern/utils/roundToDecimalPlaces.js +3 -0
  79. package/modern/utils/utils.js +6 -1
  80. package/node/DataGrid/DataGrid.js +1 -7
  81. package/node/components/GridRow.js +22 -16
  82. package/node/components/cell/GridCell.js +27 -50
  83. package/node/components/containers/GridRootStyles.js +135 -37
  84. package/node/components/toolbar/GridToolbarColumnsButton.js +5 -4
  85. package/node/components/toolbar/GridToolbarDensitySelector.js +2 -2
  86. package/node/components/toolbar/GridToolbarExportContainer.js +2 -2
  87. package/node/components/toolbar/GridToolbarFilterButton.js +4 -3
  88. package/node/components/virtualization/GridMainContainer.js +10 -2
  89. package/node/components/virtualization/GridVirtualScrollbar.js +5 -5
  90. package/node/components/virtualization/GridVirtualScroller.js +18 -5
  91. package/node/components/virtualization/GridVirtualScrollerContent.js +11 -2
  92. package/node/hooks/features/columnResize/useGridColumnResize.js +2 -1
  93. package/node/hooks/features/columns/useGridColumns.js +7 -3
  94. package/node/hooks/features/dimensions/useGridDimensions.js +6 -8
  95. package/node/hooks/features/editing/gridEditingSelectors.js +8 -2
  96. package/node/hooks/features/editing/index.js +7 -11
  97. package/node/hooks/features/editing/useGridCellEditing.js +2 -2
  98. package/node/hooks/features/editing/useGridRowEditing.js +3 -4
  99. package/node/hooks/features/focus/useGridFocus.js +3 -2
  100. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +24 -15
  101. package/node/hooks/features/keyboardNavigation/utils.js +0 -6
  102. package/node/hooks/features/listView/useGridListView.js +2 -1
  103. package/node/hooks/features/rowSelection/useGridRowSelection.js +2 -2
  104. package/node/hooks/features/rows/useGridParamsApi.js +33 -14
  105. package/node/hooks/features/rows/useGridRowSpanning.js +92 -89
  106. package/node/hooks/features/rows/useGridRows.js +7 -8
  107. package/node/hooks/features/rows/useGridRowsMeta.js +5 -4
  108. package/node/hooks/features/virtualization/gridFocusedVirtualCellSelector.js +2 -2
  109. package/node/hooks/features/virtualization/useGridVirtualScroller.js +31 -45
  110. package/node/index.js +1 -1
  111. package/node/models/api/index.js +0 -11
  112. package/node/utils/roundToDecimalPlaces.js +9 -0
  113. package/node/utils/utils.js +8 -1
  114. package/package.json +2 -2
  115. package/utils/roundToDecimalPlaces.d.ts +1 -0
  116. package/utils/roundToDecimalPlaces.js +3 -0
  117. package/utils/utils.d.ts +1 -0
  118. package/utils/utils.js +6 -1
@@ -243,8 +243,7 @@ const useGridRowEditing = (apiRef, props) => {
243
243
  if (props.editMode === _gridEditRowModel.GridEditModes.Cell) {
244
244
  return _gridEditRowModel.GridRowModes.View;
245
245
  }
246
- const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
247
- const isEditing = editingState[id] && Object.keys(editingState[id]).length > 0;
246
+ const isEditing = (0, _gridEditingSelectors.gridRowIsEditingSelector)(apiRef, id);
248
247
  return isEditing ? _gridEditRowModel.GridRowModes.Edit : _gridEditRowModel.GridRowModes.View;
249
248
  }, [apiRef, props.editMode]);
250
249
  const updateRowModesModel = (0, _utils.unstable_useEventCallback)(newModel => {
@@ -579,7 +578,7 @@ const useGridRowEditing = (apiRef, props) => {
579
578
 
580
579
  // Run this effect synchronously so that the keyboard event can impact the yet-to-be-rendered input.
581
580
  (0, _utils.unstable_useEnhancedEffect)(() => {
582
- const idToIdLookup = (0, _gridRowsSelector.gridRowsDataRowIdToIdLookupSelector)(apiRef);
581
+ const rowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
583
582
 
584
583
  // Update the ref here because updateStateToStopRowEditMode may change it later
585
584
  const copyOfPrevRowModesModel = prevRowModesModel.current;
@@ -591,7 +590,7 @@ const useGridRowEditing = (apiRef, props) => {
591
590
  mode: _gridEditRowModel.GridRowModes.View
592
591
  };
593
592
  const prevMode = copyOfPrevRowModesModel[id]?.mode || _gridEditRowModel.GridRowModes.View;
594
- const originalId = idToIdLookup[id] ?? id;
593
+ const originalId = rowsLookup[id] ? apiRef.current.getRowId(rowsLookup[id]) : id;
595
594
  if (params.mode === _gridEditRowModel.GridRowModes.Edit && prevMode === _gridEditRowModel.GridRowModes.View) {
596
595
  updateStateToStartRowEditMode((0, _extends2.default)({
597
596
  id: originalId
@@ -335,10 +335,11 @@ const useGridFocus = (apiRef, props) => {
335
335
  // If the focused cell is in a row which does not exist anymore,
336
336
  // focus previous row or remove the focus
337
337
  if (cell && !apiRef.current.getRow(cell.id)) {
338
- const lastFocusedRowId = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef)?.id;
338
+ const lastFocusedRowId = cell.id;
339
339
  let nextRowId = null;
340
340
  if (typeof lastFocusedRowId !== 'undefined') {
341
- const lastFocusedRowIndex = apiRef.current.getRowIndexRelativeToVisibleRows(lastFocusedRowId);
341
+ const rowEl = apiRef.current.getRowElement(lastFocusedRowId);
342
+ const lastFocusedRowIndex = rowEl?.dataset.rowindex ? Number(rowEl?.dataset.rowindex) : 0;
342
343
  const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, {
343
344
  pagination: props.pagination,
344
345
  paginationMode: props.paginationMode
@@ -13,7 +13,6 @@ var _gridColumnsSelector = require("../columns/gridColumnsSelector");
13
13
  var _useGridLogger = require("../../utils/useGridLogger");
14
14
  var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
15
15
  var _gridFilterSelector = require("../filter/gridFilterSelector");
16
- var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
17
16
  var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectionColDef");
18
17
  var _gridClasses = require("../../../constants/gridClasses");
19
18
  var _gridEditRowModel = require("../../../models/gridEditRowModel");
@@ -25,6 +24,13 @@ var _pipeProcessing = require("../../core/pipeProcessing");
25
24
  var _domUtils = require("../../../utils/domUtils");
26
25
  var _utils = require("./utils");
27
26
  var _gridListViewSelectors = require("../listView/gridListViewSelectors");
27
+ var _createSelector = require("../../../utils/createSelector");
28
+ var _pagination = require("../pagination");
29
+ var _gridRowsSelector = require("../rows/gridRowsSelector");
30
+ const gridVisibleRowsWithPinnedRowsSelector = (0, _createSelector.createSelectorMemoized)(_pagination.gridVisibleRowsSelector, _gridRowsSelector.gridPinnedRowsSelector, (visibleRows, pinnedRows) => {
31
+ return (pinnedRows.top || []).concat(visibleRows.rows, pinnedRows.bottom || []);
32
+ });
33
+
28
34
  /**
29
35
  * @requires useGridSorting (method) - can be after
30
36
  * @requires useGridFilter (state) - can be after
@@ -36,10 +42,11 @@ var _gridListViewSelectors = require("../listView/gridListViewSelectors");
36
42
  */
37
43
  const useGridKeyboardNavigation = (apiRef, props) => {
38
44
  const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridKeyboardNavigation');
39
- const initialCurrentPageRows = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props).rows;
40
45
  const isRtl = (0, _RtlProvider.useRtl)();
41
46
  const listView = props.unstable_listView;
42
- const currentPageRows = React.useMemo(() => (0, _utils.enrichPageRowsWithPinnedRows)(apiRef, initialCurrentPageRows), [apiRef, initialCurrentPageRows]);
47
+ const getCurrentPageRows = React.useCallback(() => {
48
+ return gridVisibleRowsWithPinnedRowsSelector(apiRef);
49
+ }, [apiRef]);
43
50
  const headerFilteringEnabled = props.signature !== 'DataGrid' && props.headerFilters;
44
51
 
45
52
  /**
@@ -98,8 +105,8 @@ const useGridKeyboardNavigation = (apiRef, props) => {
98
105
  apiRef.current.setColumnGroupHeaderFocus(field, depth, event);
99
106
  }, [apiRef, logger]);
100
107
  const getRowIdFromIndex = React.useCallback(rowIndex => {
101
- return currentPageRows[rowIndex]?.id;
102
- }, [currentPageRows]);
108
+ return getCurrentPageRows()[rowIndex]?.id;
109
+ }, [getCurrentPageRows]);
103
110
  const handleColumnHeaderKeyDown = React.useCallback((params, event) => {
104
111
  const headerTitleNode = event.currentTarget.querySelector(`.${_gridClasses.gridClasses.columnHeaderTitleContainerContent}`);
105
112
  const isFromInsideContent = !!headerTitleNode && headerTitleNode.contains(event.target);
@@ -108,6 +115,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
108
115
  // There is one exception for the checkBoxHeader
109
116
  return;
110
117
  }
118
+ const currentPageRows = getCurrentPageRows();
111
119
  const viewportPageSize = apiRef.current.getViewportPageSize();
112
120
  const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
113
121
  const firstRowIndexInPage = currentPageRows.length > 0 ? 0 : null;
@@ -119,12 +127,10 @@ const useGridKeyboardNavigation = (apiRef, props) => {
119
127
  switch (event.key) {
120
128
  case 'ArrowDown':
121
129
  {
122
- if (firstRowIndexInPage !== null) {
123
- if (headerFilteringEnabled) {
124
- goToHeaderFilter(colIndexBefore, event);
125
- } else {
126
- goToCell(colIndexBefore, getRowIdFromIndex(firstRowIndexInPage));
127
- }
130
+ if (headerFilteringEnabled) {
131
+ goToHeaderFilter(colIndexBefore, event);
132
+ } else if (firstRowIndexInPage !== null) {
133
+ goToCell(colIndexBefore, getRowIdFromIndex(firstRowIndexInPage));
128
134
  }
129
135
  break;
130
136
  }
@@ -198,13 +204,14 @@ const useGridKeyboardNavigation = (apiRef, props) => {
198
204
  if (shouldPreventDefault) {
199
205
  event.preventDefault();
200
206
  }
201
- }, [apiRef, currentPageRows.length, headerFilteringEnabled, goToHeaderFilter, goToCell, getRowIdFromIndex, isRtl, goToHeader, goToGroupHeader]);
207
+ }, [apiRef, getCurrentPageRows, headerFilteringEnabled, goToHeaderFilter, goToCell, getRowIdFromIndex, isRtl, goToHeader, goToGroupHeader]);
202
208
  const handleHeaderFilterKeyDown = React.useCallback((params, event) => {
203
209
  const isEditing = (0, _gridHeaderFilteringSelectors.gridHeaderFilteringEditFieldSelector)(apiRef) === params.field;
204
210
  const isHeaderMenuOpen = (0, _gridHeaderFilteringSelectors.gridHeaderFilteringMenuSelector)(apiRef) === params.field;
205
211
  if (isEditing || isHeaderMenuOpen || !(0, _keyboardUtils.isNavigationKey)(event.key)) {
206
212
  return;
207
213
  }
214
+ const currentPageRows = getCurrentPageRows();
208
215
  const viewportPageSize = apiRef.current.getViewportPageSize();
209
216
  const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
210
217
  const firstRowIndexInPage = 0;
@@ -284,7 +291,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
284
291
  if (shouldPreventDefault) {
285
292
  event.preventDefault();
286
293
  }
287
- }, [apiRef, currentPageRows.length, goToHeaderFilter, isRtl, goToHeader, goToCell, getRowIdFromIndex]);
294
+ }, [apiRef, getCurrentPageRows, goToHeaderFilter, isRtl, goToHeader, goToCell, getRowIdFromIndex]);
288
295
  const handleColumnGroupHeaderKeyDown = React.useCallback((params, event) => {
289
296
  const focusedColumnGroup = (0, _focus.gridFocusColumnGroupHeaderSelector)(apiRef);
290
297
  if (focusedColumnGroup === null) {
@@ -299,6 +306,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
299
306
  depth,
300
307
  maxDepth
301
308
  } = params;
309
+ const currentPageRows = getCurrentPageRows();
302
310
  const viewportPageSize = apiRef.current.getViewportPageSize();
303
311
  const currentColIndex = apiRef.current.getColumnIndex(currentField);
304
312
  const colIndexBefore = currentField ? apiRef.current.getColumnIndex(currentField) : 0;
@@ -370,7 +378,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
370
378
  if (shouldPreventDefault) {
371
379
  event.preventDefault();
372
380
  }
373
- }, [apiRef, currentPageRows.length, goToHeader, goToGroupHeader, goToCell, getRowIdFromIndex]);
381
+ }, [apiRef, getCurrentPageRows, goToHeader, goToGroupHeader, goToCell, getRowIdFromIndex]);
374
382
  const handleCellKeyDown = React.useCallback((params, event) => {
375
383
  // Ignore portal
376
384
  if ((0, _domUtils.isEventTargetInPortal)(event)) {
@@ -389,6 +397,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
389
397
  if (!canUpdateFocus) {
390
398
  return;
391
399
  }
400
+ const currentPageRows = getCurrentPageRows();
392
401
  if (currentPageRows.length === 0) {
393
402
  return;
394
403
  }
@@ -517,7 +526,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
517
526
  if (shouldPreventDefault) {
518
527
  event.preventDefault();
519
528
  }
520
- }, [apiRef, currentPageRows, isRtl, goToCell, getRowIdFromIndex, headerFilteringEnabled, goToHeaderFilter, goToHeader, listView]);
529
+ }, [apiRef, getCurrentPageRows, isRtl, goToCell, getRowIdFromIndex, headerFilteringEnabled, goToHeaderFilter, goToHeader, listView]);
521
530
  const checkIfCanStartEditing = React.useCallback((initialValue, {
522
531
  event
523
532
  }) => {
@@ -3,16 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.enrichPageRowsWithPinnedRows = enrichPageRowsWithPinnedRows;
7
6
  exports.findNonRowSpannedCell = findNonRowSpannedCell;
8
7
  exports.getRightColumnIndex = exports.getLeftColumnIndex = void 0;
9
8
  var _gridFilterSelector = require("../filter/gridFilterSelector");
10
9
  var _gridRowSpanningSelectors = require("../rows/gridRowSpanningSelectors");
11
- var _gridRowsSelector = require("../rows/gridRowsSelector");
12
- function enrichPageRowsWithPinnedRows(apiRef, rows) {
13
- const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef) || {};
14
- return [...(pinnedRows.top || []), ...rows, ...(pinnedRows.bottom || [])];
15
- }
16
10
  const getLeftColumnIndex = ({
17
11
  currentColIndex,
18
12
  firstColIndex,
@@ -9,6 +9,7 @@ exports.listViewStateInitializer = void 0;
9
9
  exports.useGridListView = useGridListView;
10
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
11
  var React = _interopRequireWildcard(require("react"));
12
+ var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
12
13
  var _warning = require("@mui/x-internals/warning");
13
14
  var _dimensions = require("../dimensions");
14
15
  var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
@@ -47,7 +48,7 @@ function useGridListView(apiRef, props) {
47
48
  /*
48
49
  * EFFECTS
49
50
  */
50
- React.useEffect(() => {
51
+ (0, _useEnhancedEffect.default)(() => {
51
52
  const listColumn = props.unstable_listColumn;
52
53
  if (listColumn) {
53
54
  apiRef.current.setState(state => {
@@ -73,7 +73,6 @@ const useGridRowSelection = (apiRef, props) => {
73
73
  isRowSelectable: propIsRowSelectable
74
74
  } = props;
75
75
  const canHaveMultipleSelection = (0, _utils.isMultipleRowSelectionEnabled)(props);
76
- const visibleRows = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props);
77
76
  const tree = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridRowTreeSelector);
78
77
  const isNestedData = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridRowMaximumTreeDepthSelector) > 1;
79
78
  const expandMouseRowRangeSelection = React.useCallback(id => {
@@ -421,6 +420,7 @@ const useGridRowSelection = (apiRef, props) => {
421
420
  end = previousRowIndex;
422
421
  }
423
422
  }
423
+ const visibleRows = (0, _useGridVisibleRows.getVisibleRows)(apiRef);
424
424
  const rowsBetweenStartAndEnd = visibleRows.rows.slice(start, end + 1).map(row => row.id);
425
425
  apiRef.current.selectRows(rowsBetweenStartAndEnd, !isNextRowSelected);
426
426
  return;
@@ -435,7 +435,7 @@ const useGridRowSelection = (apiRef, props) => {
435
435
  event.preventDefault();
436
436
  selectRows(apiRef.current.getAllRowIds(), true);
437
437
  }
438
- }, [apiRef, handleSingleRowSelection, selectRows, visibleRows.rows, canHaveMultipleSelection]);
438
+ }, [apiRef, handleSingleRowSelection, selectRows, canHaveMultipleSelection]);
439
439
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'sortedRowsSet', runIfRowSelectionIsEnabled(() => removeOutdatedSelection(true)));
440
440
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'filteredRowsSet', runIfRowSelectionIsEnabled(removeOutdatedSelection));
441
441
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick));
@@ -39,37 +39,52 @@ function useGridParamsApi(apiRef, props) {
39
39
  };
40
40
  return params;
41
41
  }, [apiRef]);
42
- const getCellParams = React.useCallback((id, field) => {
43
- const colDef = props.unstable_listView ? (0, _gridListViewSelectors.gridListColumnSelector)(apiRef.current.state) : apiRef.current.getColumn(field);
44
- const row = apiRef.current.getRow(id);
45
- const rowNode = apiRef.current.getRowNode(id);
46
- if (!row || !rowNode) {
47
- throw new MissingRowIdError(`No row with id #${id} found`);
48
- }
42
+ const getCellParamsForRow = React.useCallback((id, field, row, {
43
+ cellMode,
44
+ colDef,
45
+ hasFocus,
46
+ rowNode,
47
+ tabIndex
48
+ }) => {
49
49
  const rawValue = row[field];
50
50
  const value = colDef?.valueGetter ? colDef.valueGetter(rawValue, row, colDef, apiRef) : rawValue;
51
- const cellFocus = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
52
- const cellTabIndex = (0, _gridFocusStateSelector.gridTabIndexCellSelector)(apiRef);
53
51
  const params = {
54
52
  id,
55
53
  field,
56
54
  row,
57
55
  rowNode,
58
56
  colDef,
59
- cellMode: apiRef.current.getCellMode(id, field),
60
- hasFocus: cellFocus !== null && cellFocus.field === field && cellFocus.id === id,
61
- tabIndex: cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === id ? 0 : -1,
57
+ cellMode,
58
+ hasFocus,
59
+ tabIndex,
62
60
  value,
63
61
  formattedValue: value,
64
62
  isEditable: false,
65
- api: {}
63
+ api: null
66
64
  };
67
65
  if (colDef && colDef.valueFormatter) {
68
66
  params.formattedValue = colDef.valueFormatter(value, row, colDef, apiRef);
69
67
  }
70
68
  params.isEditable = colDef && apiRef.current.isCellEditable(params);
71
69
  return params;
72
- }, [apiRef, props.unstable_listView]);
70
+ }, [apiRef]);
71
+ const getCellParams = React.useCallback((id, field) => {
72
+ const row = apiRef.current.getRow(id);
73
+ const rowNode = apiRef.current.getRowNode(id);
74
+ if (!row || !rowNode) {
75
+ throw new MissingRowIdError(`No row with id #${id} found`);
76
+ }
77
+ const cellFocus = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
78
+ const cellTabIndex = (0, _gridFocusStateSelector.gridTabIndexCellSelector)(apiRef);
79
+ const cellMode = apiRef.current.getCellMode(id, field);
80
+ return apiRef.current.getCellParamsForRow(id, field, row, {
81
+ colDef: props.unstable_listView && props.unstable_listColumn?.field === field ? (0, _gridListViewSelectors.gridListColumnSelector)(apiRef.current.state) : apiRef.current.getColumn(field),
82
+ rowNode,
83
+ hasFocus: cellFocus !== null && cellFocus.field === field && cellFocus.id === id,
84
+ tabIndex: cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === id ? 0 : -1,
85
+ cellMode
86
+ });
87
+ }, [apiRef, props.unstable_listView, props.unstable_listColumn?.field]);
73
88
  const getCellValue = React.useCallback((id, field) => {
74
89
  const colDef = apiRef.current.getColumn(field);
75
90
  const row = apiRef.current.getRow(id);
@@ -128,5 +143,9 @@ function useGridParamsApi(apiRef, props) {
128
143
  getColumnHeaderParams,
129
144
  getColumnHeaderElement
130
145
  };
146
+ const paramsPrivateApi = {
147
+ getCellParamsForRow
148
+ };
131
149
  (0, _useGridApiMethod.useGridApiMethod)(apiRef, paramsApi, 'public');
150
+ (0, _useGridApiMethod.useGridApiMethod)(apiRef, paramsPrivateApi, 'private');
132
151
  }
@@ -13,10 +13,12 @@ var _constants = require("../../../internals/constants");
13
13
  var _gridColumnsSelector = require("../columns/gridColumnsSelector");
14
14
  var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
15
15
  var _gridVirtualizationSelectors = require("../virtualization/gridVirtualizationSelectors");
16
- var _useGridSelector = require("../../utils/useGridSelector");
17
- var _gridRowsSelector = require("./gridRowsSelector");
18
16
  var _gridRowSpanningUtils = require("./gridRowSpanningUtils");
19
17
  var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectionColDef");
18
+ var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
19
+ var _utils = require("../../../utils/utils");
20
+ var _pagination = require("../pagination");
21
+ var _gridRowsSelector = require("./gridRowsSelector");
20
22
  const EMPTY_STATE = {
21
23
  spannedCells: {},
22
24
  hiddenCells: {},
@@ -61,8 +63,8 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
61
63
  const backwardsHiddenCells = [];
62
64
  if (index === rangeToProcess.firstRowIndex) {
63
65
  let prevIndex = index - 1;
64
- const prevRowEntry = visibleRows[prevIndex];
65
- while (prevIndex >= range.firstRowIndex && (0, _gridRowSpanningUtils.getCellValue)(prevRowEntry.model, colDef, apiRef) === cellValue) {
66
+ let prevRowEntry = visibleRows[prevIndex];
67
+ while (prevIndex >= range.firstRowIndex && prevRowEntry && (0, _gridRowSpanningUtils.getCellValue)(prevRowEntry.model, colDef, apiRef) === cellValue) {
66
68
  const currentRow = visibleRows[prevIndex + 1];
67
69
  if (hiddenCells[currentRow.id]) {
68
70
  hiddenCells[currentRow.id][colDef.field] = true;
@@ -76,6 +78,7 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
76
78
  spannedRowId = prevRowEntry.id;
77
79
  spannedRowIndex = prevIndex;
78
80
  prevIndex -= 1;
81
+ prevRowEntry = visibleRows[prevIndex];
79
82
  }
80
83
  }
81
84
  backwardsHiddenCells.forEach(hiddenCellIndex => {
@@ -131,6 +134,24 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
131
134
  processedRange
132
135
  };
133
136
  };
137
+ const getInitialRangeToProcess = (props, apiRef) => {
138
+ const rowCount = (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef).length;
139
+ if (props.pagination) {
140
+ const pageSize = (0, _pagination.gridPageSizeSelector)(apiRef);
141
+ let paginationLastRowIndex = DEFAULT_ROWS_TO_PROCESS;
142
+ if (pageSize > 0) {
143
+ paginationLastRowIndex = pageSize - 1;
144
+ }
145
+ return {
146
+ firstRowIndex: 0,
147
+ lastRowIndex: Math.min(paginationLastRowIndex, rowCount)
148
+ };
149
+ }
150
+ return {
151
+ firstRowIndex: 0,
152
+ lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS, rowCount)
153
+ };
154
+ };
134
155
 
135
156
  /**
136
157
  * @requires columnsStateInitializer (method) - should be initialized before
@@ -138,75 +159,53 @@ const computeRowSpanningState = (apiRef, colDefs, visibleRows, range, rangeToPro
138
159
  * @requires filterStateInitializer (method) - should be initialized before
139
160
  */
140
161
  const rowSpanningStateInitializer = (state, props, apiRef) => {
141
- if (props.unstable_rowSpanning) {
142
- const rowIds = state.rows.dataRowIds || [];
143
- const orderedFields = state.columns.orderedFields || [];
144
- const dataRowIdToModelLookup = state.rows.dataRowIdToModelLookup;
145
- const columnsLookup = state.columns.lookup;
146
- const isFilteringPending = Boolean(state.filter.filterModel.items.length) || Boolean(state.filter.filterModel.quickFilterValues?.length);
147
- if (!rowIds.length || !orderedFields.length || !dataRowIdToModelLookup || !columnsLookup || isFilteringPending) {
148
- return (0, _extends2.default)({}, state, {
149
- rowSpanning: EMPTY_STATE
150
- });
151
- }
152
- const rangeToProcess = {
153
- firstRowIndex: 0,
154
- lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS, Math.max(rowIds.length, 0))
155
- };
156
- const rows = rowIds.map(id => ({
157
- id,
158
- model: dataRowIdToModelLookup[id]
159
- }));
160
- const colDefs = orderedFields.map(field => columnsLookup[field]);
161
- const {
162
- spannedCells,
163
- hiddenCells,
164
- hiddenCellOriginMap
165
- } = computeRowSpanningState(apiRef, colDefs, rows, rangeToProcess, rangeToProcess, true, EMPTY_RANGE);
162
+ if (!props.unstable_rowSpanning) {
166
163
  return (0, _extends2.default)({}, state, {
167
- rowSpanning: {
168
- spannedCells,
169
- hiddenCells,
170
- hiddenCellOriginMap
171
- }
164
+ rowSpanning: EMPTY_STATE
165
+ });
166
+ }
167
+ const rowIds = state.rows.dataRowIds || [];
168
+ const orderedFields = state.columns.orderedFields || [];
169
+ const dataRowIdToModelLookup = state.rows.dataRowIdToModelLookup;
170
+ const columnsLookup = state.columns.lookup;
171
+ const isFilteringPending = Boolean(state.filter.filterModel.items.length) || Boolean(state.filter.filterModel.quickFilterValues?.length);
172
+ if (!rowIds.length || !orderedFields.length || !dataRowIdToModelLookup || !columnsLookup || isFilteringPending) {
173
+ return (0, _extends2.default)({}, state, {
174
+ rowSpanning: EMPTY_STATE
172
175
  });
173
176
  }
177
+ const rangeToProcess = getInitialRangeToProcess(props, apiRef);
178
+ const rows = rowIds.map(id => ({
179
+ id,
180
+ model: dataRowIdToModelLookup[id]
181
+ }));
182
+ const colDefs = orderedFields.map(field => columnsLookup[field]);
183
+ const {
184
+ spannedCells,
185
+ hiddenCells,
186
+ hiddenCellOriginMap
187
+ } = computeRowSpanningState(apiRef, colDefs, rows, rangeToProcess, rangeToProcess, true, EMPTY_RANGE);
174
188
  return (0, _extends2.default)({}, state, {
175
- rowSpanning: EMPTY_STATE
189
+ rowSpanning: {
190
+ spannedCells,
191
+ hiddenCells,
192
+ hiddenCellOriginMap
193
+ }
176
194
  });
177
195
  };
178
196
  exports.rowSpanningStateInitializer = rowSpanningStateInitializer;
179
197
  const useGridRowSpanning = (apiRef, props) => {
180
- const {
181
- range,
182
- rows: visibleRows
183
- } = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef, props);
184
- const renderContext = (0, _useGridSelector.useGridSelector)(apiRef, _gridVirtualizationSelectors.gridRenderContextSelector);
185
- const colDefs = (0, _useGridSelector.useGridSelector)(apiRef, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector);
186
- const tree = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridRowTreeSelector);
187
198
  const processedRange = (0, _useLazyRef.default)(() => {
188
- return Object.keys(apiRef.current.state.rowSpanning.spannedCells).length > 0 ? {
189
- firstRowIndex: 0,
190
- lastRowIndex: Math.min(DEFAULT_ROWS_TO_PROCESS, Math.max(apiRef.current.state.rows.dataRowIds.length, 0))
191
- } : EMPTY_RANGE;
199
+ return apiRef.current.state.rowSpanning !== EMPTY_STATE ? getInitialRangeToProcess(props, apiRef) : EMPTY_RANGE;
192
200
  });
193
- const lastRange = React.useRef(EMPTY_RANGE);
194
- const updateRowSpanningState = React.useCallback(
195
- // A reset needs to occur when:
196
- // - The `unstable_rowSpanning` prop is updated (feature flag)
197
- // - The filtering is applied
198
- // - The sorting is applied
199
- // - The `paginationModel` is updated
200
- // - The rows are updated
201
- (resetState = true) => {
202
- if (!props.unstable_rowSpanning) {
203
- if (apiRef.current.state.rowSpanning !== EMPTY_STATE) {
204
- apiRef.current.setState(state => (0, _extends2.default)({}, state, {
205
- rowSpanning: EMPTY_STATE
206
- }));
207
- }
208
- return;
209
- }
201
+ const updateRowSpanningState = React.useCallback((renderContext, resetState = false) => {
202
+ const {
203
+ range,
204
+ rows: visibleRows
205
+ } = (0, _useGridVisibleRows.getVisibleRows)(apiRef, {
206
+ pagination: props.pagination,
207
+ paginationMode: props.paginationMode
208
+ });
210
209
  if (range === null || !(0, _gridRowSpanningUtils.isRowContextInitialized)(renderContext)) {
211
210
  return;
212
211
  }
@@ -220,6 +219,7 @@ const useGridRowSpanning = (apiRef, props) => {
220
219
  if (rangeToProcess === null) {
221
220
  return;
222
221
  }
222
+ const colDefs = (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef);
223
223
  const {
224
224
  spannedCells,
225
225
  hiddenCells,
@@ -232,7 +232,8 @@ const useGridRowSpanning = (apiRef, props) => {
232
232
  const currentSpannedCellsCount = Object.keys(apiRef.current.state.rowSpanning.spannedCells).length;
233
233
  const currentHiddenCellsCount = Object.keys(apiRef.current.state.rowSpanning.hiddenCells).length;
234
234
  const shouldUpdateState = resetState || newSpannedCellsCount !== currentSpannedCellsCount || newHiddenCellsCount !== currentHiddenCellsCount;
235
- if (!shouldUpdateState) {
235
+ const hasNoSpannedCells = newSpannedCellsCount === 0 && currentSpannedCellsCount === 0;
236
+ if (!shouldUpdateState || hasNoSpannedCells) {
236
237
  return;
237
238
  }
238
239
  apiRef.current.setState(state => {
@@ -244,34 +245,36 @@ const useGridRowSpanning = (apiRef, props) => {
244
245
  }
245
246
  });
246
247
  });
247
- }, [apiRef, props.unstable_rowSpanning, range, renderContext, visibleRows, colDefs, processedRange]);
248
- const prevRenderContext = React.useRef(renderContext);
249
- const isFirstRender = React.useRef(true);
250
- const shouldResetState = React.useRef(false);
251
- const previousTree = React.useRef(tree);
252
- React.useEffect(() => {
253
- const firstRender = isFirstRender.current;
254
- if (isFirstRender.current) {
255
- isFirstRender.current = false;
256
- }
257
- if (tree !== previousTree.current) {
258
- previousTree.current = tree;
259
- updateRowSpanningState(true);
248
+ }, [apiRef, processedRange, props.pagination, props.paginationMode]);
249
+
250
+ // Reset events trigger a full re-computation of the row spanning state:
251
+ // - The `unstable_rowSpanning` prop is updated (feature flag)
252
+ // - The filtering is applied
253
+ // - The sorting is applied
254
+ // - The `paginationModel` is updated
255
+ // - The rows are updated
256
+ const resetRowSpanningState = React.useCallback(() => {
257
+ const renderContext = (0, _gridVirtualizationSelectors.gridRenderContextSelector)(apiRef);
258
+ if (!(0, _gridRowSpanningUtils.isRowContextInitialized)(renderContext)) {
260
259
  return;
261
260
  }
262
- if (range && lastRange.current && (0, _gridRowSpanningUtils.isRowRangeUpdated)(range, lastRange.current)) {
263
- lastRange.current = range;
264
- shouldResetState.current = true;
265
- }
266
- if (!firstRender && prevRenderContext.current !== renderContext) {
267
- if ((0, _gridRowSpanningUtils.isRowRangeUpdated)(prevRenderContext.current, renderContext)) {
268
- updateRowSpanningState(shouldResetState.current);
269
- shouldResetState.current = false;
261
+ updateRowSpanningState(renderContext, true);
262
+ }, [apiRef, updateRowSpanningState]);
263
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'renderedRowsIntervalChange', (0, _utils.runIf)(props.unstable_rowSpanning, updateRowSpanningState));
264
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'sortedRowsSet', (0, _utils.runIf)(props.unstable_rowSpanning, resetRowSpanningState));
265
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'paginationModelChange', (0, _utils.runIf)(props.unstable_rowSpanning, resetRowSpanningState));
266
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'filteredRowsSet', (0, _utils.runIf)(props.unstable_rowSpanning, resetRowSpanningState));
267
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnsChange', (0, _utils.runIf)(props.unstable_rowSpanning, resetRowSpanningState));
268
+ React.useEffect(() => {
269
+ if (!props.unstable_rowSpanning) {
270
+ if (apiRef.current.state.rowSpanning !== EMPTY_STATE) {
271
+ apiRef.current.setState(state => (0, _extends2.default)({}, state, {
272
+ rowSpanning: EMPTY_STATE
273
+ }));
270
274
  }
271
- prevRenderContext.current = renderContext;
272
- return;
275
+ } else if (apiRef.current.state.rowSpanning === EMPTY_STATE) {
276
+ resetRowSpanningState();
273
277
  }
274
- updateRowSpanningState();
275
- }, [updateRowSpanningState, renderContext, range, lastRange, tree]);
278
+ }, [apiRef, resetRowSpanningState, props.unstable_rowSpanning]);
276
279
  };
277
280
  exports.useGridRowSpanning = useGridRowSpanning;
@@ -48,7 +48,6 @@ const useGridRows = (apiRef, props) => {
48
48
  }
49
49
  }
50
50
  const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridRows');
51
- const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef);
52
51
  const lastUpdateMs = React.useRef(Date.now());
53
52
  const lastRowCount = React.useRef(props.rowCount);
54
53
  const timeout = (0, _useTimeout.useTimeout)();
@@ -75,12 +74,6 @@ const useGridRows = (apiRef, props) => {
75
74
  }
76
75
  return row.id;
77
76
  }, [getRowIdProp]);
78
- const lookup = React.useMemo(() => currentPage.rows.reduce((acc, {
79
- id
80
- }, index) => {
81
- acc[id] = index;
82
- return acc;
83
- }, {}), [currentPage.rows]);
84
77
  const throttledRowsChange = React.useCallback(({
85
78
  cache,
86
79
  throttle
@@ -179,7 +172,13 @@ const useGridRows = (apiRef, props) => {
179
172
  }, [apiRef]);
180
173
  const getRowsCount = React.useCallback(() => (0, _gridRowsSelector.gridRowCountSelector)(apiRef), [apiRef]);
181
174
  const getAllRowIds = React.useCallback(() => (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef), [apiRef]);
182
- const getRowIndexRelativeToVisibleRows = React.useCallback(id => lookup[id], [lookup]);
175
+ const getRowIndexRelativeToVisibleRows = React.useCallback(id => {
176
+ const row = apiRef.current.getRow(id);
177
+ const {
178
+ rowToIndexMap
179
+ } = (0, _useGridVisibleRows.getVisibleRows)(apiRef);
180
+ return rowToIndexMap.get(row);
181
+ }, [apiRef]);
183
182
  const setRowChildrenExpansion = React.useCallback((id, isExpanded) => {
184
183
  const currentNode = apiRef.current.getRowNode(id);
185
184
  if (!currentNode) {
@@ -9,9 +9,10 @@ exports.useGridRowsMeta = exports.rowsMetaStateInitializer = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
10
  var React = _interopRequireWildcard(require("react"));
11
11
  var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
12
+ var _utils = require("@mui/utils");
12
13
  var _ResizeObserver = require("../../../utils/ResizeObserver");
13
14
  var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
14
- var _utils = require("../../../utils/utils");
15
+ var _utils2 = require("../../../utils/utils");
15
16
  var _useGridApiMethod = require("../../utils/useGridApiMethod");
16
17
  var _useGridSelector = require("../../utils/useGridSelector");
17
18
  var _densitySelector = require("../density/densitySelector");
@@ -77,7 +78,7 @@ const useGridRowsMeta = (apiRef, props) => {
77
78
  // HACK: rowHeight trails behind the most up-to-date value just enough to
78
79
  // mess the initial rowsMeta hydration :/
79
80
  const baseRowHeight = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef.current.state).rowHeight;
80
- (0, _utils.eslintUseValue)(rowHeight);
81
+ (0, _utils2.eslintUseValue)(rowHeight);
81
82
  const entry = apiRef.current.getRowHeightEntry(row.id);
82
83
  if (!getRowHeightProp) {
83
84
  entry.content = baseRowHeight;
@@ -119,7 +120,7 @@ const useGridRowsMeta = (apiRef, props) => {
119
120
  }
120
121
  apiRef.current.unstable_applyPipeProcessors('rowHeight', entry, row);
121
122
  return entry;
122
- }, [apiRef, currentPage.rows.length, getRowHeightProp, getEstimatedRowHeight, rowHeight, getRowSpacing, densityFactor]);
123
+ }, [apiRef, currentPage.rows, getRowHeightProp, getEstimatedRowHeight, rowHeight, getRowSpacing, densityFactor]);
123
124
  const hydrateRowsMeta = React.useCallback(() => {
124
125
  hasRowWithAutoHeight.current = false;
125
126
  pinnedRows.top.forEach(processHeightEntry);
@@ -190,7 +191,7 @@ const useGridRowsMeta = (apiRef, props) => {
190
191
 
191
192
  // The effect is used to build the rows meta data - currentPageTotalHeight and positions.
192
193
  // Because of variable row height this is needed for the virtualization
193
- React.useEffect(() => {
194
+ (0, _utils.unstable_useEnhancedEffect)(() => {
194
195
  hydrateRowsMeta();
195
196
  }, [filterModel, paginationState, sortModel, hydrateRowsMeta]);
196
197
  const rowsMetaApi = {