@mui/x-data-grid 7.0.0-beta.4 → 7.0.0-beta.5

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 (90) hide show
  1. package/CHANGELOG.md +138 -14
  2. package/DataGrid/DataGrid.js +2 -0
  3. package/colDef/gridBooleanOperators.js +1 -1
  4. package/components/GridRow.d.ts +7 -9
  5. package/components/GridRow.js +36 -47
  6. package/components/cell/GridCell.d.ts +2 -1
  7. package/components/cell/GridCell.js +7 -3
  8. package/components/cell/GridSkeletonCell.d.ts +3 -2
  9. package/components/cell/GridSkeletonCell.js +14 -6
  10. package/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  11. package/components/columnsManagement/GridColumnsManagement.js +1 -1
  12. package/components/containers/GridRootStyles.js +9 -2
  13. package/components/virtualization/GridBottomContainer.js +1 -1
  14. package/components/virtualization/GridTopContainer.js +1 -1
  15. package/components/virtualization/GridVirtualScroller.js +2 -2
  16. package/components/virtualization/GridVirtualScrollerRenderZone.js +9 -3
  17. package/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
  18. package/hooks/features/columns/gridColumnsSelector.d.ts +6 -0
  19. package/hooks/features/columns/gridColumnsSelector.js +8 -1
  20. package/hooks/features/columns/useGridColumns.js +4 -0
  21. package/hooks/features/editing/useGridRowEditing.js +1 -2
  22. package/hooks/features/filter/useGridFilter.js +2 -2
  23. package/hooks/features/rows/useGridRows.js +8 -4
  24. package/hooks/features/rows/useGridRowsMeta.js +5 -13
  25. package/hooks/features/sorting/gridSortingUtils.js +9 -1
  26. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +0 -9
  27. package/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
  28. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +3 -0
  29. package/hooks/features/virtualization/useGridVirtualScroller.js +82 -138
  30. package/hooks/features/virtualization/useGridVirtualization.d.ts +0 -8
  31. package/hooks/features/virtualization/useGridVirtualization.js +1 -6
  32. package/hooks/utils/useTimeout.d.ts +5 -3
  33. package/hooks/utils/useTimeout.js +13 -5
  34. package/index.js +1 -1
  35. package/models/colDef/gridColDef.d.ts +7 -0
  36. package/modern/DataGrid/DataGrid.js +2 -0
  37. package/modern/colDef/gridBooleanOperators.js +1 -1
  38. package/modern/components/GridRow.js +35 -46
  39. package/modern/components/cell/GridCell.js +7 -3
  40. package/modern/components/cell/GridSkeletonCell.js +14 -6
  41. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  42. package/modern/components/columnsManagement/GridColumnsManagement.js +1 -1
  43. package/modern/components/containers/GridRootStyles.js +9 -2
  44. package/modern/components/virtualization/GridBottomContainer.js +1 -1
  45. package/modern/components/virtualization/GridTopContainer.js +1 -1
  46. package/modern/components/virtualization/GridVirtualScroller.js +2 -2
  47. package/modern/components/virtualization/GridVirtualScrollerRenderZone.js +8 -3
  48. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
  49. package/modern/hooks/features/columns/gridColumnsSelector.js +8 -1
  50. package/modern/hooks/features/columns/useGridColumns.js +2 -0
  51. package/modern/hooks/features/editing/useGridRowEditing.js +1 -2
  52. package/modern/hooks/features/filter/useGridFilter.js +2 -2
  53. package/modern/hooks/features/rows/useGridRows.js +8 -4
  54. package/modern/hooks/features/rows/useGridRowsMeta.js +5 -13
  55. package/modern/hooks/features/sorting/gridSortingUtils.js +9 -1
  56. package/modern/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
  57. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +80 -136
  58. package/modern/hooks/features/virtualization/useGridVirtualization.js +1 -6
  59. package/modern/hooks/utils/useTimeout.js +13 -5
  60. package/modern/index.js +1 -1
  61. package/modern/utils/utils.js +9 -0
  62. package/node/DataGrid/DataGrid.js +1 -0
  63. package/node/colDef/gridBooleanOperators.js +1 -1
  64. package/node/components/GridRow.js +35 -46
  65. package/node/components/cell/GridCell.js +7 -3
  66. package/node/components/cell/GridSkeletonCell.js +15 -7
  67. package/node/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  68. package/node/components/columnsManagement/GridColumnsManagement.js +1 -1
  69. package/node/components/containers/GridRootStyles.js +9 -2
  70. package/node/components/virtualization/GridBottomContainer.js +1 -1
  71. package/node/components/virtualization/GridTopContainer.js +1 -1
  72. package/node/components/virtualization/GridVirtualScroller.js +2 -2
  73. package/node/components/virtualization/GridVirtualScrollerRenderZone.js +7 -2
  74. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +8 -5
  75. package/node/hooks/features/columns/gridColumnsSelector.js +9 -2
  76. package/node/hooks/features/columns/useGridColumns.js +2 -0
  77. package/node/hooks/features/editing/useGridRowEditing.js +1 -2
  78. package/node/hooks/features/filter/useGridFilter.js +2 -2
  79. package/node/hooks/features/rows/useGridRows.js +8 -4
  80. package/node/hooks/features/rows/useGridRowsMeta.js +5 -13
  81. package/node/hooks/features/sorting/gridSortingUtils.js +9 -1
  82. package/node/hooks/features/virtualization/gridVirtualizationSelectors.js +1 -8
  83. package/node/hooks/features/virtualization/useGridVirtualScroller.js +81 -136
  84. package/node/hooks/features/virtualization/useGridVirtualization.js +2 -7
  85. package/node/hooks/utils/useTimeout.js +13 -4
  86. package/node/index.js +1 -1
  87. package/node/utils/utils.js +12 -1
  88. package/package.json +1 -1
  89. package/utils/utils.d.ts +4 -0
  90. package/utils/utils.js +9 -0
@@ -20,6 +20,7 @@ export let PinnedPosition = /*#__PURE__*/function (PinnedPosition) {
20
20
  PinnedPosition[PinnedPosition["NONE"] = 0] = "NONE";
21
21
  PinnedPosition[PinnedPosition["LEFT"] = 1] = "LEFT";
22
22
  PinnedPosition[PinnedPosition["RIGHT"] = 2] = "RIGHT";
23
+ PinnedPosition[PinnedPosition["VIRTUAL"] = 3] = "VIRTUAL";
23
24
  return PinnedPosition;
24
25
  }({});
25
26
  const EMPTY_CELL_PARAMS = {
@@ -131,10 +132,13 @@ const GridCell = /*#__PURE__*/React.forwardRef((props, ref) => {
131
132
  classes: rootClasses,
132
133
  getCellClassName
133
134
  } = rootProps;
134
- const classNames = apiRef.current.unstable_applyPipeProcessors('cellClassName', [], {
135
+
136
+ // There is a hidden grid state access in `applyPipeProcessor('cellClassName', ...)`
137
+ const pipesClassName = useGridSelector(apiRef, () => apiRef.current.unstable_applyPipeProcessors('cellClassName', [], {
135
138
  id: rowId,
136
139
  field
137
- });
140
+ }).filter(Boolean).join(' '));
141
+ const classNames = [pipesClassName];
138
142
  if (column.cellClassName) {
139
143
  classNames.push(typeof column.cellClassName === 'function' ? column.cellClassName(cellParamsWithAPI) : column.cellClassName);
140
144
  }
@@ -330,7 +334,7 @@ process.env.NODE_ENV !== "production" ? GridCell.propTypes = {
330
334
  onMouseDown: PropTypes.func,
331
335
  onMouseUp: PropTypes.func,
332
336
  pinnedOffset: PropTypes.number.isRequired,
333
- pinnedPosition: PropTypes.oneOf([0, 1, 2]).isRequired,
337
+ pinnedPosition: PropTypes.oneOf([0, 1, 2, 3]).isRequired,
334
338
  rowId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
335
339
  sectionIndex: PropTypes.number.isRequired,
336
340
  sectionLength: PropTypes.number.isRequired,
@@ -1,13 +1,16 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["field", "align", "width", "contentWidth"];
3
+ const _excluded = ["field", "align", "width", "height"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import Skeleton from '@mui/material/Skeleton';
7
7
  import { unstable_composeClasses as composeClasses, unstable_capitalize as capitalize } from '@mui/utils';
8
+ import { fastMemo } from '../../utils/fastMemo';
9
+ import { randomNumberBetween } from '../../utils/utils';
8
10
  import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
9
11
  import { getDataGridUtilityClass } from '../../constants/gridClasses';
10
12
  import { jsx as _jsx } from "react/jsx-runtime";
13
+ const randomWidth = randomNumberBetween(10000, 20, 80);
11
14
  const useUtilityClasses = ownerState => {
12
15
  const {
13
16
  align,
@@ -22,7 +25,7 @@ function GridSkeletonCell(props) {
22
25
  const {
23
26
  align,
24
27
  width,
25
- contentWidth
28
+ height
26
29
  } = props,
27
30
  other = _objectWithoutPropertiesLoose(props, _excluded);
28
31
  const rootProps = useGridRootProps();
@@ -31,14 +34,18 @@ function GridSkeletonCell(props) {
31
34
  align
32
35
  };
33
36
  const classes = useUtilityClasses(ownerState);
37
+ const contentWidth = Math.round(randomWidth());
34
38
  return /*#__PURE__*/_jsx("div", _extends({
35
39
  className: classes.root,
36
40
  style: {
37
- width
41
+ height,
42
+ maxWidth: width,
43
+ minWidth: width
38
44
  }
39
45
  }, other, {
40
46
  children: /*#__PURE__*/_jsx(Skeleton, {
41
- width: `${contentWidth}%`
47
+ width: `${contentWidth}%`,
48
+ height: 25
42
49
  })
43
50
  }));
44
51
  }
@@ -48,8 +55,9 @@ process.env.NODE_ENV !== "production" ? GridSkeletonCell.propTypes = {
48
55
  // | To update them edit the TypeScript types and run "yarn proptypes" |
49
56
  // ----------------------------------------------------------------------
50
57
  align: PropTypes.string.isRequired,
51
- contentWidth: PropTypes.number.isRequired,
52
58
  field: PropTypes.string.isRequired,
59
+ height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]).isRequired,
53
60
  width: PropTypes.number.isRequired
54
61
  } : void 0;
55
- export { GridSkeletonCell };
62
+ const Memoized = fastMemo(GridSkeletonCell);
63
+ export { Memoized as GridSkeletonCell };
@@ -36,7 +36,6 @@ const GridCellCheckboxForwardRef = /*#__PURE__*/React.forwardRef(function GridCe
36
36
  const checkboxElement = React.useRef(null);
37
37
  const rippleRef = React.useRef(null);
38
38
  const handleRef = useForkRef(checkboxElement, ref);
39
- const element = apiRef.current.getCellElement(id, field);
40
39
  const handleChange = event => {
41
40
  const params = {
42
41
  value: event.target.checked,
@@ -45,10 +44,13 @@ const GridCellCheckboxForwardRef = /*#__PURE__*/React.forwardRef(function GridCe
45
44
  apiRef.current.publishEvent('rowSelectionCheckboxChange', params, event);
46
45
  };
47
46
  React.useLayoutEffect(() => {
48
- if (tabIndex === 0 && element) {
49
- element.tabIndex = -1;
47
+ if (tabIndex === 0) {
48
+ const element = apiRef.current.getCellElement(id, field);
49
+ if (element) {
50
+ element.tabIndex = -1;
51
+ }
50
52
  }
51
- }, [element, tabIndex]);
53
+ }, [apiRef, tabIndex, id, field]);
52
54
  React.useEffect(() => {
53
55
  if (hasFocus) {
54
56
  const input = checkboxElement.current?.querySelector('input');
@@ -152,7 +152,7 @@ function GridColumnsManagement(props) {
152
152
  ownerState: rootProps,
153
153
  children: apiRef.current.getLocaleText('columnsManagementNoColumns')
154
154
  })]
155
- }), !disableShowHideToggle && !disableResetButton && currentColumns.length > 0 ? /*#__PURE__*/_jsxs(GridColumnsManagementFooter, {
155
+ }), (!disableShowHideToggle || !disableResetButton) && currentColumns.length > 0 ? /*#__PURE__*/_jsxs(GridColumnsManagementFooter, {
156
156
  ownerState: rootProps,
157
157
  className: classes.footer,
158
158
  children: [!disableShowHideToggle ? /*#__PURE__*/_jsx(FormControlLabel, {
@@ -341,7 +341,7 @@ export const GridRootStyles = styled('div', {
341
341
  [`& .${c.columnSeparator}`]: {
342
342
  visibility: 'hidden',
343
343
  position: 'absolute',
344
- zIndex: 100,
344
+ zIndex: 3,
345
345
  display: 'flex',
346
346
  flexDirection: 'column',
347
347
  justifyContent: 'center',
@@ -462,7 +462,8 @@ export const GridRootStyles = styled('div', {
462
462
  lineHeight: 'inherit'
463
463
  },
464
464
  [`& .${c.cellEmpty}`]: {
465
- padding: 0
465
+ padding: 0,
466
+ height: 'unset'
466
467
  },
467
468
  [`& .${c.cell}.${c['cell--selectionMode']}`]: {
468
469
  cursor: 'default'
@@ -578,6 +579,12 @@ export const GridRootStyles = styled('div', {
578
579
  flex: '0 0 auto',
579
580
  display: 'inline-block'
580
581
  },
582
+ [`& .${c.cellSkeleton}`]: {
583
+ flex: '0 0 auto',
584
+ height: '100%',
585
+ display: 'inline-flex',
586
+ alignItems: 'center'
587
+ },
581
588
  [`& .${c.columnHeaderDraggableContainer}`]: {
582
589
  display: 'flex',
583
590
  width: '100%',
@@ -13,7 +13,7 @@ const useUtilityClasses = () => {
13
13
  };
14
14
  const Element = styled('div')({
15
15
  position: 'sticky',
16
- zIndex: 2,
16
+ zIndex: 4,
17
17
  bottom: 'calc(var(--DataGrid-hasScrollX) * var(--DataGrid-scrollbarSize))'
18
18
  });
19
19
  export function GridBottomContainer(props) {
@@ -13,7 +13,7 @@ const useUtilityClasses = () => {
13
13
  };
14
14
  const Element = styled('div')({
15
15
  position: 'sticky',
16
- zIndex: 2,
16
+ zIndex: 4,
17
17
  top: 0,
18
18
  '&::after': {
19
19
  content: '" "',
@@ -85,9 +85,9 @@ function GridVirtualScroller(props) {
85
85
  virtualScroller: virtualScroller
86
86
  })
87
87
  })]
88
- })), /*#__PURE__*/_jsx(Scrollbar, _extends({
88
+ })), dimensions.hasScrollY && /*#__PURE__*/_jsx(Scrollbar, _extends({
89
89
  position: "vertical"
90
- }, getScrollbarVerticalProps())), /*#__PURE__*/_jsx(Scrollbar, _extends({
90
+ }, getScrollbarVerticalProps())), dimensions.hasScrollX && /*#__PURE__*/_jsx(Scrollbar, _extends({
91
91
  position: "horizontal"
92
92
  }, getScrollbarHorizontalProps())), props.children]
93
93
  }));
@@ -7,7 +7,8 @@ import { styled } from '@mui/system';
7
7
  import { unstable_composeClasses as composeClasses } from '@mui/utils';
8
8
  import { useGridApiContext } from '../../hooks/utils/useGridApiContext';
9
9
  import { useGridSelector } from '../../hooks/utils/useGridSelector';
10
- import { gridOffsetsSelector } from '../../hooks/features/virtualization';
10
+ import { gridRowsMetaSelector } from '../../hooks/features/rows';
11
+ import { gridRenderContextSelector } from '../../hooks/features/virtualization';
11
12
  import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
12
13
  import { getDataGridUtilityClass } from '../../constants/gridClasses';
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -38,13 +39,17 @@ const GridVirtualScrollerRenderZone = /*#__PURE__*/React.forwardRef(function Gri
38
39
  const apiRef = useGridApiContext();
39
40
  const rootProps = useGridRootProps();
40
41
  const classes = useUtilityClasses(rootProps);
41
- const offsets = useGridSelector(apiRef, gridOffsetsSelector);
42
+ const offsetTop = useGridSelector(apiRef, () => {
43
+ const renderContext = gridRenderContextSelector(apiRef);
44
+ const rowsMeta = gridRowsMetaSelector(apiRef.current.state);
45
+ return rowsMeta.positions[renderContext.firstRowIndex] ?? 0;
46
+ });
42
47
  return /*#__PURE__*/_jsx(VirtualScrollerRenderZoneRoot, _extends({
43
48
  ref: ref,
44
49
  className: clsx(classes.root, className),
45
50
  ownerState: rootProps,
46
51
  style: {
47
- transform: `translate3d(0, ${offsets.top}px, 0)`
52
+ transform: `translate3d(0, ${offsetTop}px, 0)`
48
53
  }
49
54
  }, other));
50
55
  });
@@ -1,23 +1,24 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { unstable_useForkRef as useForkRef } from '@mui/utils';
4
- import { styled } from '@mui/material/styles';
4
+ import { styled, useTheme } from '@mui/material/styles';
5
5
  import { useGridSelector } from '../../utils';
6
6
  import { useGridRootProps } from '../../utils/useGridRootProps';
7
7
  import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
8
8
  import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
9
9
  import { GridColumnHeaderItem } from '../../../components/columnHeaders/GridColumnHeaderItem';
10
10
  import { gridDimensionsSelector } from '../dimensions';
11
- import { gridOffsetsSelector, gridRenderContextColumnsSelector, gridVirtualizationColumnEnabledSelector } from '../virtualization';
11
+ import { gridRenderContextColumnsSelector, gridVirtualizationColumnEnabledSelector } from '../virtualization';
12
+ import { computeOffsetLeft } from '../virtualization/useGridVirtualScroller';
12
13
  import { GridColumnGroupHeader } from '../../../components/columnHeaders/GridColumnGroupHeader';
13
- import { GridPinnedColumnPosition, gridVisiblePinnedColumnDefinitionsSelector } from '../columns';
14
+ import { GridPinnedColumnPosition, gridColumnPositionsSelector, gridVisiblePinnedColumnDefinitionsSelector } from '../columns';
14
15
  import { GridScrollbarFillerCell as ScrollbarFiller } from '../../../components/GridScrollbarFillerCell';
15
16
  import { gridClasses } from '../../../constants/gridClasses';
16
17
  import { jsx as _jsx } from "react/jsx-runtime";
17
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
18
19
  const SpaceFiller = styled('div')({
19
20
  /* GridRootStyles conflict */
20
- '&&': {
21
+ '&&&': {
21
22
  padding: 0,
22
23
  width: 'calc(var(--DataGrid-width) - var(--DataGrid-columnsTotalWidth))'
23
24
  }
@@ -49,14 +50,16 @@ export const useGridColumnHeaders = props => {
49
50
  const [dragCol, setDragCol] = React.useState('');
50
51
  const [resizeCol, setResizeCol] = React.useState('');
51
52
  const apiRef = useGridPrivateApiContext();
53
+ const theme = useTheme();
52
54
  const rootProps = useGridRootProps();
53
55
  const hasVirtualization = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector);
54
56
  const innerRef = React.useRef(null);
55
57
  const handleInnerRef = useForkRef(innerRefProp, innerRef);
56
58
  const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
57
- const offsets = useGridSelector(apiRef, gridOffsetsSelector);
59
+ const columnPositions = useGridSelector(apiRef, gridColumnPositionsSelector);
58
60
  const renderContext = useGridSelector(apiRef, gridRenderContextColumnsSelector);
59
- const visiblePinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
61
+ const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
62
+ const offsetLeft = computeOffsetLeft(columnPositions, renderContext, theme.direction, pinnedColumns.left.length);
60
63
  React.useEffect(() => {
61
64
  apiRef.current.columnHeadersContainerElementRef.current.scrollLeft = 0;
62
65
  }, [apiRef]);
@@ -88,8 +91,8 @@ export const useGridColumnHeaders = props => {
88
91
  const getFillers = (params, children, leftOverflow, borderTop = false) => {
89
92
  const isPinnedRight = params?.position === GridPinnedColumnPosition.RIGHT;
90
93
  const isNotPinned = params?.position === undefined;
91
- const hasScrollbarFiller = visiblePinnedColumns.right.length > 0 && isPinnedRight || visiblePinnedColumns.right.length === 0 && isNotPinned;
92
- const leftOffsetWidth = offsets.left - leftOverflow;
94
+ const hasScrollbarFiller = pinnedColumns.right.length > 0 && isPinnedRight || pinnedColumns.right.length === 0 && isNotPinned;
95
+ const leftOffsetWidth = offsetLeft - leftOverflow;
93
96
  return /*#__PURE__*/_jsxs(React.Fragment, {
94
97
  children: [isNotPinned && /*#__PURE__*/_jsx("div", {
95
98
  role: "presentation",
@@ -134,4 +134,11 @@ export const gridFilterableColumnLookupSelector = createSelectorMemoized(gridCol
134
134
  acc[col.field] = col;
135
135
  }
136
136
  return acc;
137
- }, {}));
137
+ }, {}));
138
+
139
+ /**
140
+ * Checks if some column has a colSpan field.
141
+ * @category Columns
142
+ * @ignore - Do not document
143
+ */
144
+ export const gridHasColSpanSelector = createSelectorMemoized(gridColumnDefinitionsSelector, columns => columns.some(column => column.colSpan !== undefined));
@@ -44,6 +44,7 @@ export function useGridColumns(apiRef, props) {
44
44
  logger.debug('Updating columns state.');
45
45
  apiRef.current.setState(mergeColumnsState(columnsState));
46
46
  apiRef.current.publishEvent('columnsChange', columnsState.orderedFields);
47
+ apiRef.current.updateRenderContext?.();
47
48
  apiRef.current.forceUpdate();
48
49
  }, [logger, apiRef]);
49
50
 
@@ -73,6 +74,7 @@ export function useGridColumns(apiRef, props) {
73
74
  keepOnlyColumnsToUpsert: false
74
75
  })
75
76
  }));
77
+ apiRef.current.updateRenderContext?.();
76
78
  apiRef.current.forceUpdate();
77
79
  }
78
80
  }, [apiRef]);
@@ -21,7 +21,7 @@ export const useGridRowEditing = (apiRef, props) => {
21
21
  const [rowModesModel, setRowModesModel] = React.useState({});
22
22
  const rowModesModelRef = React.useRef(rowModesModel);
23
23
  const prevRowModesModel = React.useRef({});
24
- const focusTimeout = React.useRef(null);
24
+ const focusTimeout = React.useRef();
25
25
  const nextFocusedCell = React.useRef(null);
26
26
  const {
27
27
  processRowUpdate,
@@ -76,7 +76,6 @@ export const useGridRowEditing = (apiRef, props) => {
76
76
  // focus we check if the next cell that received focus is from a different row.
77
77
  nextFocusedCell.current = null;
78
78
  focusTimeout.current = setTimeout(() => {
79
- focusTimeout.current = null;
80
79
  if (nextFocusedCell.current?.id !== params.id) {
81
80
  // The row might have been deleted during the click
82
81
  if (!apiRef.current.getRow(params.id)) {
@@ -105,7 +105,7 @@ export const useGridFilter = (apiRef, props) => {
105
105
  const filterModel = gridFilterModelSelector(apiRef);
106
106
  const existingItems = [...filterModel.items];
107
107
  items.forEach(item => {
108
- const itemIndex = items.findIndex(filterItem => filterItem.id === item.id);
108
+ const itemIndex = existingItems.findIndex(filterItem => filterItem.id === item.id);
109
109
  if (itemIndex === -1) {
110
110
  existingItems.push(item);
111
111
  } else {
@@ -113,7 +113,7 @@ export const useGridFilter = (apiRef, props) => {
113
113
  }
114
114
  });
115
115
  apiRef.current.setFilterModel(_extends({}, filterModel, {
116
- items
116
+ items: existingItems
117
117
  }), 'upsertFilterItems');
118
118
  }, [apiRef]);
119
119
  const deleteFilterItem = React.useCallback(itemToDelete => {
@@ -260,13 +260,16 @@ export const useGridRows = (apiRef, props) => {
260
260
  const dataRowIdToIdLookup = _extends({}, gridRowsDataRowIdToIdLookupSelector(apiRef));
261
261
  const rootGroup = tree[GRID_ROOT_GROUP_ID];
262
262
  const rootGroupChildren = [...rootGroup.children];
263
+ const seenIds = new Set();
263
264
  for (let i = 0; i < newRows.length; i += 1) {
264
265
  const rowModel = newRows[i];
265
266
  const rowId = getRowIdFromRowModel(rowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
266
- const [replacedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
267
- delete dataRowIdToModelLookup[replacedRowId];
268
- delete dataRowIdToIdLookup[replacedRowId];
269
- delete tree[replacedRowId];
267
+ const [removedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
268
+ if (!seenIds.has(removedRowId)) {
269
+ delete dataRowIdToModelLookup[removedRowId];
270
+ delete dataRowIdToIdLookup[removedRowId];
271
+ delete tree[removedRowId];
272
+ }
270
273
  const rowTreeNodeConfig = {
271
274
  id: rowId,
272
275
  depth: 0,
@@ -277,6 +280,7 @@ export const useGridRows = (apiRef, props) => {
277
280
  dataRowIdToModelLookup[rowId] = rowModel;
278
281
  dataRowIdToIdLookup[rowId] = rowId;
279
282
  tree[rowId] = rowTreeNodeConfig;
283
+ seenIds.add(rowId);
280
284
  }
281
285
  tree[GRID_ROOT_GROUP_ID] = _extends({}, rootGroup, {
282
286
  children: rootGroupChildren
@@ -106,14 +106,9 @@ export const useGridRowsMeta = (apiRef, props) => {
106
106
  } else {
107
107
  rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
108
108
  }
109
- const initialHeights = {};
110
- /* eslint-disable-next-line no-restricted-syntax */
111
- for (const key in sizes) {
112
- if (/^base[A-Z]/.test(key)) {
113
- initialHeights[key] = sizes[key];
114
- }
115
- }
116
- initialHeights.baseCenter = baseRowHeight;
109
+ const initialHeights = {
110
+ baseCenter: baseRowHeight
111
+ };
117
112
  if (getRowSpacing) {
118
113
  const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
119
114
  const spacing = getRowSpacing(_extends({}, row, {
@@ -131,19 +126,16 @@ export const useGridRowsMeta = (apiRef, props) => {
131
126
  const positions = [];
132
127
  const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => {
133
128
  positions.push(acc);
134
- let maximumBaseSize = 0;
135
129
  let otherSizes = 0;
136
130
  const processedSizes = calculateRowProcessedSizes(row);
137
131
  /* eslint-disable-next-line no-restricted-syntax, guard-for-in */
138
132
  for (const key in processedSizes) {
139
133
  const value = processedSizes[key];
140
- if (/^base[A-Z]/.test(key)) {
141
- maximumBaseSize = value > maximumBaseSize ? value : maximumBaseSize;
142
- } else {
134
+ if (key !== 'baseCenter') {
143
135
  otherSizes += value;
144
136
  }
145
137
  }
146
- return acc + maximumBaseSize + otherSizes;
138
+ return acc + processedSizes.baseCenter + otherSizes;
147
139
  }, 0);
148
140
  pinnedRows?.top?.forEach(row => {
149
141
  calculateRowProcessedSizes(row);
@@ -28,7 +28,15 @@ const parseSortItem = (sortItem, apiRef) => {
28
28
  if (!column || sortItem.sort === null) {
29
29
  return null;
30
30
  }
31
- const comparator = isDesc(sortItem.sort) ? (...args) => -1 * column.sortComparator(...args) : column.sortComparator;
31
+ let comparator;
32
+ if (column.getSortComparator) {
33
+ comparator = column.getSortComparator(sortItem.sort);
34
+ } else {
35
+ comparator = isDesc(sortItem.sort) ? (...args) => -1 * column.sortComparator(...args) : column.sortComparator;
36
+ }
37
+ if (!comparator) {
38
+ return null;
39
+ }
32
40
  const getSortCellParams = id => ({
33
41
  id,
34
42
  field: column.field,
@@ -24,13 +24,6 @@ export const gridVirtualizationColumnEnabledSelector = createSelector(gridVirtua
24
24
  */
25
25
  export const gridRenderContextSelector = createSelector(gridVirtualizationSelector, state => state.renderContext);
26
26
 
27
- /**
28
- * Get the offsets
29
- * @category Virtualization
30
- * @ignore - do not document.
31
- */
32
- export const gridOffsetsSelector = createSelector(gridVirtualizationSelector, state => state.offsets);
33
-
34
27
  /**
35
28
  * Get the render context, with only columns filled in.
36
29
  * This is cached, so it can be used to only re-render when the column interval changes.