@mui/x-data-grid 8.18.0 → 8.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/DataGrid/useDataGridComponent.js +4 -3
  3. package/components/GridRow.js +1 -1
  4. package/components/cell/GridActionsCell.d.ts +9 -0
  5. package/components/cell/GridActionsCell.js +54 -34
  6. package/components/cell/GridBooleanCell.js +0 -10
  7. package/components/cell/GridCell.js +4 -10
  8. package/components/columnHeaders/GridColumnHeaderItem.js +2 -2
  9. package/components/columnSelection/GridCellCheckboxRenderer.js +37 -22
  10. package/components/containers/GridRootStyles.js +1 -1
  11. package/components/toolbarV8/Toolbar.js +1 -1
  12. package/components/virtualization/GridVirtualScrollbar.d.ts +1 -0
  13. package/components/virtualization/GridVirtualScrollbar.js +13 -8
  14. package/components/virtualization/GridVirtualScroller.js +2 -1
  15. package/components/virtualization/GridVirtualScrollerRenderZone.js +1 -1
  16. package/constants/dataGridPropsDefaultValues.js +2 -1
  17. package/esm/DataGrid/useDataGridComponent.js +5 -4
  18. package/esm/components/GridRow.js +1 -1
  19. package/esm/components/cell/GridActionsCell.d.ts +9 -0
  20. package/esm/components/cell/GridActionsCell.js +55 -34
  21. package/esm/components/cell/GridBooleanCell.js +0 -10
  22. package/esm/components/cell/GridCell.js +4 -10
  23. package/esm/components/columnHeaders/GridColumnHeaderItem.js +2 -2
  24. package/esm/components/columnSelection/GridCellCheckboxRenderer.js +37 -22
  25. package/esm/components/containers/GridRootStyles.js +1 -1
  26. package/esm/components/toolbarV8/Toolbar.js +1 -1
  27. package/esm/components/virtualization/GridVirtualScrollbar.d.ts +1 -0
  28. package/esm/components/virtualization/GridVirtualScrollbar.js +12 -7
  29. package/esm/components/virtualization/GridVirtualScroller.js +2 -1
  30. package/esm/components/virtualization/GridVirtualScrollerRenderZone.js +1 -1
  31. package/esm/constants/dataGridPropsDefaultValues.js +2 -1
  32. package/esm/hooks/core/gridPropsSelectors.d.ts +2 -1
  33. package/esm/hooks/core/gridPropsSelectors.js +3 -0
  34. package/esm/hooks/core/useGridProps.js +8 -2
  35. package/esm/hooks/core/useGridVirtualizer.d.ts +80 -6
  36. package/esm/hooks/core/useGridVirtualizer.js +27 -12
  37. package/esm/hooks/features/columnGrouping/useGridColumnGrouping.js +6 -1
  38. package/esm/hooks/features/columnMenu/useGridColumnMenu.js +14 -4
  39. package/esm/hooks/features/columns/useGridColumnSpanning.js +9 -4
  40. package/esm/hooks/features/dimensions/useGridDimensions.js +12 -6
  41. package/esm/hooks/features/export/useGridPrintExport.js +18 -18
  42. package/esm/hooks/features/filter/useGridFilter.d.ts +1 -1
  43. package/esm/hooks/features/filter/useGridFilter.js +3 -1
  44. package/esm/hooks/features/focus/useGridFocus.js +0 -1
  45. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  46. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +189 -25
  47. package/esm/hooks/features/pagination/useGridPaginationMeta.js +3 -3
  48. package/esm/hooks/features/pagination/useGridPaginationModel.js +7 -4
  49. package/esm/hooks/features/pagination/useGridRowCount.js +31 -15
  50. package/esm/hooks/features/rowSelection/useGridRowSelection.js +8 -7
  51. package/esm/hooks/features/rowSelection/utils.d.ts +1 -0
  52. package/esm/hooks/features/rowSelection/utils.js +17 -4
  53. package/esm/hooks/features/rows/useGridRowSpanning.js +23 -60
  54. package/esm/hooks/features/scroll/useGridScroll.js +2 -3
  55. package/esm/hooks/features/sorting/useGridSorting.d.ts +1 -1
  56. package/esm/hooks/features/sorting/useGridSorting.js +3 -1
  57. package/esm/hooks/features/virtualization/useGridVirtualization.js +24 -5
  58. package/esm/hooks/utils/useGridEvent.js +6 -2
  59. package/esm/hooks/utils/useRunOncePerLoop.d.ts +4 -1
  60. package/esm/hooks/utils/useRunOncePerLoop.js +28 -18
  61. package/esm/index.js +1 -1
  62. package/esm/models/colDef/gridColDef.d.ts +14 -0
  63. package/esm/models/events/gridEventLookup.d.ts +5 -0
  64. package/esm/models/gridStateCommunity.d.ts +1 -1
  65. package/esm/models/params/gridCellParams.d.ts +0 -10
  66. package/esm/models/props/DataGridProps.d.ts +13 -6
  67. package/esm/utils/keyboardUtils.d.ts +1 -8
  68. package/esm/utils/keyboardUtils.js +0 -7
  69. package/hooks/core/gridPropsSelectors.d.ts +2 -1
  70. package/hooks/core/gridPropsSelectors.js +4 -1
  71. package/hooks/core/useGridProps.js +8 -2
  72. package/hooks/core/useGridVirtualizer.d.ts +80 -6
  73. package/hooks/core/useGridVirtualizer.js +26 -11
  74. package/hooks/features/columnGrouping/useGridColumnGrouping.js +6 -1
  75. package/hooks/features/columnMenu/useGridColumnMenu.js +14 -4
  76. package/hooks/features/columns/useGridColumnSpanning.js +9 -4
  77. package/hooks/features/dimensions/useGridDimensions.js +12 -6
  78. package/hooks/features/export/useGridPrintExport.js +18 -18
  79. package/hooks/features/filter/useGridFilter.d.ts +1 -1
  80. package/hooks/features/filter/useGridFilter.js +3 -1
  81. package/hooks/features/focus/useGridFocus.js +0 -1
  82. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  83. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +189 -25
  84. package/hooks/features/pagination/useGridPaginationMeta.js +2 -2
  85. package/hooks/features/pagination/useGridPaginationModel.js +7 -4
  86. package/hooks/features/pagination/useGridRowCount.js +30 -14
  87. package/hooks/features/rowSelection/useGridRowSelection.js +8 -7
  88. package/hooks/features/rowSelection/utils.d.ts +1 -0
  89. package/hooks/features/rowSelection/utils.js +16 -3
  90. package/hooks/features/rows/useGridRowSpanning.js +23 -60
  91. package/hooks/features/scroll/useGridScroll.js +2 -3
  92. package/hooks/features/sorting/useGridSorting.d.ts +1 -1
  93. package/hooks/features/sorting/useGridSorting.js +3 -1
  94. package/hooks/features/virtualization/useGridVirtualization.js +24 -5
  95. package/hooks/utils/useGridEvent.js +6 -2
  96. package/hooks/utils/useRunOncePerLoop.d.ts +4 -1
  97. package/hooks/utils/useRunOncePerLoop.js +27 -18
  98. package/index.js +1 -1
  99. package/models/colDef/gridColDef.d.ts +14 -0
  100. package/models/events/gridEventLookup.d.ts +5 -0
  101. package/models/gridStateCommunity.d.ts +1 -1
  102. package/models/params/gridCellParams.d.ts +0 -10
  103. package/models/props/DataGridProps.d.ts +13 -6
  104. package/package.json +3 -3
  105. package/utils/keyboardUtils.d.ts +1 -8
  106. package/utils/keyboardUtils.js +1 -13
@@ -63,5 +63,6 @@ const DATA_GRID_PROPS_DEFAULT_VALUES = exports.DATA_GRID_PROPS_DEFAULT_VALUES =
63
63
  sortingMode: 'client',
64
64
  sortingOrder: ['asc', 'desc', null],
65
65
  throttleRowsMs: 0,
66
- virtualizeColumnsWithAutoRowHeight: false
66
+ virtualizeColumnsWithAutoRowHeight: false,
67
+ tabNavigation: 'none'
67
68
  };
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
+ import { useFirstRender } from '@mui/x-internals/useFirstRender';
4
5
  import { useGridInitialization } from "../hooks/core/useGridInitialization.js";
5
- import { useGridVirtualizer } from "../hooks/core/useGridVirtualizer.js";
6
6
  import { useGridInitializeState } from "../hooks/utils/useGridInitializeState.js";
7
7
  import { useGridClipboard } from "../hooks/features/clipboard/useGridClipboard.js";
8
8
  import { columnMenuStateInitializer, useGridColumnMenu } from "../hooks/features/columnMenu/useGridColumnMenu.js";
@@ -25,7 +25,7 @@ import { useGridSorting, sortingStateInitializer } from "../hooks/features/sorti
25
25
  import { useGridScroll } from "../hooks/features/scroll/useGridScroll.js";
26
26
  import { useGridEvents } from "../hooks/features/events/useGridEvents.js";
27
27
  import { dimensionsStateInitializer, useGridDimensions } from "../hooks/features/dimensions/useGridDimensions.js";
28
- import { rowsMetaStateInitializer, useGridRowsMeta } from "../hooks/features/rows/useGridRowsMeta.js";
28
+ import { rowsMetaStateInitializer } from "../hooks/features/rows/useGridRowsMeta.js";
29
29
  import { useGridStatePersistence } from "../hooks/features/statePersistence/useGridStatePersistence.js";
30
30
  import { useGridColumnSpanning } from "../hooks/features/columns/useGridColumnSpanning.js";
31
31
  import { useGridColumnGrouping, columnGroupsStateInitializer } from "../hooks/features/columnGrouping/useGridColumnGrouping.js";
@@ -66,7 +66,6 @@ export const useDataGridComponent = (apiRef, props, configuration) => {
66
66
  useGridInitializeState(dimensionsStateInitializer, apiRef, props);
67
67
  useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
68
68
  useGridInitializeState(listViewStateInitializer, apiRef, props);
69
- useGridVirtualizer(apiRef, props);
70
69
  useGridKeyboardNavigation(apiRef, props);
71
70
  useGridRowSelection(apiRef, props);
72
71
  useGridColumns(apiRef, props);
@@ -83,7 +82,6 @@ export const useDataGridComponent = (apiRef, props, configuration) => {
83
82
  useGridDensity(apiRef, props);
84
83
  useGridColumnResize(apiRef, props);
85
84
  useGridPagination(apiRef, props);
86
- useGridRowsMeta(apiRef, props);
87
85
  useGridScroll(apiRef, props);
88
86
  useGridColumnMenu(apiRef);
89
87
  useGridCsvExport(apiRef, props);
@@ -97,6 +95,9 @@ export const useDataGridComponent = (apiRef, props, configuration) => {
97
95
  useGridDataSource(apiRef, props);
98
96
 
99
97
  // Should be the last thing to run, because all pre-processors should have been registered by now.
98
+ useFirstRender(() => {
99
+ apiRef.current.runAppliersForPendingProcessors();
100
+ });
100
101
  React.useEffect(() => {
101
102
  apiRef.current.runAppliersForPendingProcessors();
102
103
  });
@@ -197,7 +197,7 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
197
197
  rowStyle[property] = propertyValue;
198
198
  }
199
199
  return rowStyle;
200
- }, [isNotVisible, rowHeight, styleProp, heightEntry, rootProps.rowSpacingType]);
200
+ }, [isNotVisible, rowHeight, styleProp, heightEntry.spacingTop, heightEntry.spacingBottom, rootProps.rowSpacingType]);
201
201
 
202
202
  // HACK: Sometimes, the rowNode has already been removed from the state but the row is still rendered.
203
203
  if (!rowNode) {
@@ -1,8 +1,17 @@
1
+ import * as React from 'react';
1
2
  import { GridRenderCellParams } from "../../models/params/gridCellParams.js";
2
3
  import { GridMenuProps } from "../menu/GridMenu.js";
3
4
  interface GridActionsCellProps extends Omit<GridRenderCellParams, 'api'> {
4
5
  api?: GridRenderCellParams['api'];
5
6
  position?: GridMenuProps['position'];
7
+ children: React.ReactNode;
8
+ /**
9
+ * If true, the children passed to the component will not be validated.
10
+ * If false, only `GridActionsCellItem` and `React.Fragment` are allowed as children.
11
+ * Only use this prop if you know what you are doing.
12
+ * @default false
13
+ */
14
+ suppressChildrenValidation?: boolean;
6
15
  }
7
16
  declare function GridActionsCell(props: GridActionsCellProps): import("react/jsx-runtime").JSX.Element;
8
17
  declare namespace GridActionsCell {
@@ -2,25 +2,26 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
5
- const _excluded = ["api", "colDef", "id", "hasFocus", "isEditable", "field", "value", "formattedValue", "row", "rowNode", "cellMode", "tabIndex", "position", "focusElementRef"];
5
+ const _excluded = ["api", "colDef", "id", "hasFocus", "isEditable", "field", "value", "formattedValue", "row", "rowNode", "cellMode", "tabIndex", "position", "children", "suppressChildrenValidation"];
6
6
  import * as React from 'react';
7
7
  import PropTypes from 'prop-types';
8
8
  import { useRtl } from '@mui/system/RtlProvider';
9
9
  import useId from '@mui/utils/useId';
10
+ import { warnOnce } from '@mui/x-internals/warning';
10
11
  import { gridClasses } from "../../constants/gridClasses.js";
11
12
  import { GridMenu } from "../menu/GridMenu.js";
12
13
  import { useGridRootProps } from "../../hooks/utils/useGridRootProps.js";
13
14
  import { useGridApiContext } from "../../hooks/utils/useGridApiContext.js";
15
+ import { GridActionsCellItem } from "./GridActionsCellItem.js";
14
16
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
17
  const hasActions = colDef => typeof colDef.getActions === 'function';
16
18
  function GridActionsCell(props) {
17
19
  const {
18
- colDef,
19
- id,
20
20
  hasFocus,
21
21
  tabIndex,
22
22
  position = 'bottom-end',
23
- focusElementRef
23
+ children,
24
+ suppressChildrenValidation
24
25
  } = props,
25
26
  other = _objectWithoutPropertiesLoose(props, _excluded);
26
27
  const [focusedButtonIndex, setFocusedButtonIndex] = React.useState(-1);
@@ -34,12 +35,27 @@ function GridActionsCell(props) {
34
35
  const menuId = useId();
35
36
  const buttonId = useId();
36
37
  const rootProps = useGridRootProps();
37
- if (!hasActions(colDef)) {
38
- throw new Error('MUI X: Missing the `getActions` property in the `GridColDef`.');
39
- }
40
- const options = colDef.getActions(apiRef.current.getRowParams(id));
41
- const iconButtons = options.filter(option => !option.props.showInMenu);
42
- const menuButtons = options.filter(option => option.props.showInMenu);
38
+ const actions = [];
39
+ React.Children.forEach(children, child => {
40
+ // Unwrap React.Fragment
41
+ if (/*#__PURE__*/React.isValidElement(child)) {
42
+ if (child.type === React.Fragment) {
43
+ React.Children.forEach(child.props.children, fragChild => {
44
+ if (/*#__PURE__*/React.isValidElement(fragChild)) {
45
+ actions.push(fragChild);
46
+ }
47
+ });
48
+ } else if (child.type === GridActionsCellItem || suppressChildrenValidation) {
49
+ actions.push(child);
50
+ } else {
51
+ const childType = typeof child.type === 'function' ? child.type.name : child.type;
52
+ warnOnce(`MUI X: Invalid child type in \`GridActionsCell\`. Expected \`GridActionsCellItem\` or \`React.Fragment\`, got \`${childType}\`.
53
+ If this is intentional, you can suppress this warning by passing the \`suppressChildrenValidation\` prop to \`GridActionsCell\`.`, 'error');
54
+ }
55
+ }
56
+ });
57
+ const iconButtons = actions.filter(option => !option.props.showInMenu);
58
+ const menuButtons = actions.filter(option => option.props.showInMenu);
43
59
  const numberOfButtons = iconButtons.length + (menuButtons.length ? 1 : 0);
44
60
  React.useLayoutEffect(() => {
45
61
  if (!hasFocus) {
@@ -62,22 +78,16 @@ function GridActionsCell(props) {
62
78
  preventScroll: true
63
79
  });
64
80
  }, [focusedButtonIndex]);
81
+ const firstFocusableButtonIndex = actions.findIndex(o => !o.props.disabled);
65
82
  React.useEffect(() => {
83
+ if (hasFocus && focusedButtonIndex === -1) {
84
+ setFocusedButtonIndex(firstFocusableButtonIndex);
85
+ }
66
86
  if (!hasFocus) {
67
87
  setFocusedButtonIndex(-1);
68
88
  ignoreCallToFocus.current = false;
69
89
  }
70
- }, [hasFocus]);
71
- React.useImperativeHandle(focusElementRef, () => ({
72
- focus() {
73
- // If ignoreCallToFocus is true, then one of the buttons was clicked and the focus is already set
74
- if (!ignoreCallToFocus.current) {
75
- // find the first focusable button and pass the index to the state
76
- const focusableButtonIndex = options.findIndex(o => !o.props.disabled);
77
- setFocusedButtonIndex(focusableButtonIndex);
78
- }
79
- }
80
- }), [options]);
90
+ }, [hasFocus, focusedButtonIndex, firstFocusableButtonIndex]);
81
91
  React.useEffect(() => {
82
92
  if (focusedButtonIndex >= numberOfButtons) {
83
93
  setFocusedButtonIndex(numberOfButtons - 1);
@@ -115,7 +125,7 @@ function GridActionsCell(props) {
115
125
  return;
116
126
  }
117
127
  const getNewIndex = (index, direction) => {
118
- if (index < 0 || index > options.length) {
128
+ if (index < 0 || index > actions.length) {
119
129
  return index;
120
130
  }
121
131
 
@@ -124,7 +134,7 @@ function GridActionsCell(props) {
124
134
  const indexMod = (direction === 'left' ? -1 : 1) * rtlMod;
125
135
 
126
136
  // if the button that should receive focus is disabled go one more step
127
- return options[index + indexMod]?.props.disabled ? getNewIndex(index + indexMod, direction) : index + indexMod;
137
+ return actions[index + indexMod]?.props.disabled ? getNewIndex(index + indexMod, direction) : index + indexMod;
128
138
  };
129
139
  let newIndex = focusedButtonIndex;
130
140
  if (event.key === 'ArrowRight') {
@@ -201,6 +211,7 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
201
211
  * The mode of the cell.
202
212
  */
203
213
  cellMode: PropTypes.oneOf(['edit', 'view']).isRequired,
214
+ children: PropTypes.node.isRequired,
204
215
  /**
205
216
  * The column of the row that the current cell belongs to.
206
217
  */
@@ -209,16 +220,6 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
209
220
  * The column field of the cell that triggered the event.
210
221
  */
211
222
  field: PropTypes.string.isRequired,
212
- /**
213
- * A ref allowing to set imperative focus.
214
- * It can be passed to the element that should receive focus.
215
- * @ignore - do not document.
216
- */
217
- focusElementRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
218
- current: PropTypes.shape({
219
- focus: PropTypes.func.isRequired
220
- })
221
- })]),
222
223
  /**
223
224
  * The cell value formatted with the column valueFormatter.
224
225
  */
@@ -255,5 +256,25 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
255
256
  value: PropTypes.any
256
257
  } : void 0;
257
258
  export { GridActionsCell };
258
- export const renderActionsCell = params => /*#__PURE__*/_jsx(GridActionsCell, _extends({}, params));
259
+
260
+ // Temporary wrapper for backward compatibility.
261
+ // Only used to support `getActions` method in `GridColDef`.
262
+ // TODO(v9): Remove this wrapper and the default `renderCell` in gridActionsColDef
263
+ function GridActionsCellWrapper(props) {
264
+ const {
265
+ colDef,
266
+ id
267
+ } = props;
268
+ const apiRef = useGridApiContext();
269
+ if (!hasActions(colDef)) {
270
+ throw new Error('MUI X: Missing the `getActions` property in the `GridColDef`.');
271
+ }
272
+ const actions = colDef.getActions(apiRef.current.getRowParams(id));
273
+ return /*#__PURE__*/_jsx(GridActionsCell, _extends({
274
+ suppressChildrenValidation: true
275
+ }, props, {
276
+ children: actions
277
+ }));
278
+ }
279
+ export const renderActionsCell = params => /*#__PURE__*/_jsx(GridActionsCellWrapper, _extends({}, params));
259
280
  if (process.env.NODE_ENV !== "production") renderActionsCell.displayName = "renderActionsCell";
@@ -69,16 +69,6 @@ process.env.NODE_ENV !== "production" ? GridBooleanCellRaw.propTypes = {
69
69
  * The column field of the cell that triggered the event.
70
70
  */
71
71
  field: PropTypes.string.isRequired,
72
- /**
73
- * A ref allowing to set imperative focus.
74
- * It can be passed to the element that should receive focus.
75
- * @ignore - do not document.
76
- */
77
- focusElementRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
78
- current: PropTypes.shape({
79
- focus: PropTypes.func.isRequired
80
- })
81
- })]),
82
72
  /**
83
73
  * The cell value formatted with the column valueFormatter.
84
74
  */
@@ -16,6 +16,7 @@ import { useRtl } from '@mui/system/RtlProvider';
16
16
  import { forwardRef } from '@mui/x-internals/forwardRef';
17
17
  import { useStore } from '@mui/x-internals/store';
18
18
  import { Rowspan } from '@mui/x-virtualizer';
19
+ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
19
20
  import { doesSupportPreventScroll } from "../../utils/doesSupportPreventScroll.js";
20
21
  import { getDataGridUtilityClass, gridClasses } from "../../constants/gridClasses.js";
21
22
  import { GridCellModes } from "../../models/index.js";
@@ -135,8 +136,7 @@ const GridCell = forwardRef(function GridCell(props, ref) {
135
136
  isEditable = false,
136
137
  value
137
138
  } = cellParams;
138
- const canManageOwnFocus = column.type === 'actions' && 'getActions' in column && typeof column.getActions === 'function' && column.getActions(apiRef.current.getRowParams(rowId)).some(action => !action.props.disabled);
139
- const tabIndex = (cellMode === 'view' || !isEditable) && !canManageOwnFocus ? cellParams.tabIndex : -1;
139
+ const tabIndex = (cellMode === 'view' || !isEditable) && column.type !== 'actions' ? cellParams.tabIndex : -1;
140
140
  const {
141
141
  classes: rootClasses,
142
142
  getCellClassName
@@ -160,7 +160,6 @@ const GridCell = forwardRef(function GridCell(props, ref) {
160
160
  const valueToRender = cellParams.formattedValue ?? value;
161
161
  const cellRef = React.useRef(null);
162
162
  const handleRef = useForkRef(ref, cellRef);
163
- const focusElementRef = React.useRef(null);
164
163
  const isSelectionMode = rootProps.cellSelection ?? false;
165
164
  const ownerState = {
166
165
  align,
@@ -224,14 +223,14 @@ const GridCell = forwardRef(function GridCell(props, ref) {
224
223
  }
225
224
  return cellStyle;
226
225
  }, [width, isNotVisible, styleProp, pinnedOffset, pinnedPosition, isRtl, rowSpan]);
227
- React.useEffect(() => {
226
+ useEnhancedEffect(() => {
228
227
  if (!hasFocus || cellMode === GridCellModes.Edit) {
229
228
  return;
230
229
  }
231
230
  const doc = ownerDocument(apiRef.current.rootElementRef.current);
232
231
  if (cellRef.current && !cellRef.current.contains(doc.activeElement)) {
233
232
  const focusableElement = cellRef.current.querySelector('[tabindex="0"]');
234
- const elementToFocus = focusElementRef.current || focusableElement || cellRef.current;
233
+ const elementToFocus = focusableElement || cellRef.current;
235
234
  if (doesSupportPreventScroll()) {
236
235
  elementToFocus.focus({
237
236
  preventScroll: true
@@ -292,11 +291,6 @@ const GridCell = forwardRef(function GridCell(props, ref) {
292
291
  children = valueString;
293
292
  title = valueString;
294
293
  }
295
- if (/*#__PURE__*/React.isValidElement(children) && canManageOwnFocus) {
296
- children = /*#__PURE__*/React.cloneElement(children, {
297
- focusElementRef
298
- });
299
- }
300
294
  const draggableEventHandlers = disableDragEvents ? null : {
301
295
  onDragEnter: publish('cellDragEnter', onDragEnter),
302
296
  onDragOver: publish('cellDragOver', onDragOver)
@@ -78,7 +78,7 @@ function GridColumnHeaderItem(props) {
78
78
  const columnMenuButtonId = useId();
79
79
  const iconButtonRef = React.useRef(null);
80
80
  const [showColumnMenuIcon, setShowColumnMenuIcon] = React.useState(columnMenuOpen);
81
- const isDraggable = React.useMemo(() => !rootProps.disableColumnReorder && !disableReorder && !colDef.disableReorder, [rootProps.disableColumnReorder, disableReorder, colDef.disableReorder]);
81
+ const isDraggable = !rootProps.disableColumnReorder && !disableReorder && !colDef.disableReorder;
82
82
  let headerComponent;
83
83
  if (colDef.renderHeader) {
84
84
  headerComponent = colDef.renderHeader(apiRef.current.getColumnHeaderParams(colDef.field));
@@ -124,7 +124,7 @@ function GridColumnHeaderItem(props) {
124
124
  onDoubleClick: publish('columnSeparatorDoubleClick')
125
125
  }), [publish]);
126
126
  React.useEffect(() => {
127
- if (!showColumnMenuIcon) {
127
+ if (!showColumnMenuIcon && columnMenuOpen) {
128
128
  setShowColumnMenuIcon(columnMenuOpen);
129
129
  }
130
130
  }, [showColumnMenuIcon, columnMenuOpen]);
@@ -5,7 +5,9 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
5
5
  const _excluded = ["field", "id", "formattedValue", "row", "rowNode", "colDef", "isEditable", "cellMode", "hasFocus", "tabIndex", "api"];
6
6
  import * as React from 'react';
7
7
  import PropTypes from 'prop-types';
8
+ import clsx from 'clsx';
8
9
  import composeClasses from '@mui/utils/composeClasses';
10
+ import useEventCallback from '@mui/utils/useEventCallback';
9
11
  import { forwardRef } from '@mui/x-internals/forwardRef';
10
12
  import { useGridApiContext } from "../../hooks/utils/useGridApiContext.js";
11
13
  import { useGridRootProps } from "../../hooks/utils/useGridRootProps.js";
@@ -36,7 +38,19 @@ const GridCellCheckboxForwardRef = forwardRef(function GridCellCheckboxRenderer(
36
38
  classes: rootProps.classes
37
39
  };
38
40
  const classes = useUtilityClasses(ownerState);
41
+ const {
42
+ isIndeterminate,
43
+ isChecked,
44
+ isSelectable
45
+ } = useGridSelector(apiRef, checkboxPropsSelector, {
46
+ groupId: id,
47
+ autoSelectParents: rootProps.rowSelectionPropagation?.parents ?? false
48
+ });
49
+ const disabled = !isSelectable;
39
50
  const handleChange = event => {
51
+ if (disabled) {
52
+ return;
53
+ }
40
54
  const params = {
41
55
  value: event.target.checked,
42
56
  id
@@ -51,20 +65,26 @@ const GridCellCheckboxForwardRef = forwardRef(function GridCellCheckboxRenderer(
51
65
  }
52
66
  }
53
67
  }, [apiRef, tabIndex, id, field]);
54
- const handleKeyDown = React.useCallback(event => {
68
+ const handleKeyDown = useEventCallback(event => {
55
69
  if (event.key === ' ') {
56
70
  // We call event.stopPropagation to avoid selecting the row and also scrolling to bottom
57
71
  // TODO: Remove and add a check inside useGridKeyboardNavigation
58
72
  event.stopPropagation();
59
73
  }
60
- }, []);
61
- const isSelectable = apiRef.current.isRowSelectable(id);
62
- const {
63
- isIndeterminate,
64
- isChecked
65
- } = useGridSelector(apiRef, checkboxPropsSelector, {
66
- groupId: id,
67
- autoSelectParents: rootProps.rowSelectionPropagation?.parents ?? false
74
+ if (disabled) {
75
+ return;
76
+ }
77
+ });
78
+ const handleClick = useEventCallback(event => {
79
+ if (disabled) {
80
+ event.preventDefault();
81
+ return;
82
+ }
83
+ });
84
+ const handleMouseDown = useEventCallback(() => {
85
+ if (disabled) {
86
+ return;
87
+ }
68
88
  });
69
89
  if (rowNode.type === 'footer' || rowNode.type === 'pinnedRow') {
70
90
  return null;
@@ -74,16 +94,21 @@ const GridCellCheckboxForwardRef = forwardRef(function GridCellCheckboxRenderer(
74
94
  tabIndex: tabIndex,
75
95
  checked: isChecked && !isIndeterminate,
76
96
  onChange: handleChange,
77
- className: classes.root,
97
+ onClick: handleClick,
98
+ onMouseDown: handleMouseDown,
99
+ className: clsx(classes.root, disabled && 'Mui-disabled'),
100
+ material: {
101
+ disableRipple: disabled
102
+ },
78
103
  slotProps: {
79
104
  htmlInput: {
105
+ 'aria-disabled': disabled || undefined,
80
106
  'aria-label': label,
81
107
  name: 'select_row'
82
108
  }
83
109
  },
84
110
  onKeyDown: handleKeyDown,
85
- indeterminate: isIndeterminate,
86
- disabled: !isSelectable
111
+ indeterminate: isIndeterminate
87
112
  }, rootProps.slotProps?.baseCheckbox, other, {
88
113
  ref: ref
89
114
  }));
@@ -110,16 +135,6 @@ process.env.NODE_ENV !== "production" ? GridCellCheckboxForwardRef.propTypes = {
110
135
  * The column field of the cell that triggered the event.
111
136
  */
112
137
  field: PropTypes.string.isRequired,
113
- /**
114
- * A ref allowing to set imperative focus.
115
- * It can be passed to the element that should receive focus.
116
- * @ignore - do not document.
117
- */
118
- focusElementRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
119
- current: PropTypes.shape({
120
- focus: PropTypes.func.isRequired
121
- })
122
- })]),
123
138
  /**
124
139
  * The cell value formatted with the column valueFormatter.
125
140
  */
@@ -15,7 +15,7 @@ const separatorIconDragStyles = {
15
15
  // Emotion thinks it knows better than us which selector we should use.
16
16
  // https://github.com/emotion-js/emotion/issues/1105#issuecomment-1722524968
17
17
  const ignoreSsrWarning = '/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */';
18
- const shouldShowBorderTopRightRadiusSelector = apiRef => apiRef.current.state.dimensions.hasScrollX && (!apiRef.current.state.dimensions.hasScrollY || apiRef.current.state.dimensions.scrollbarSize === 0);
18
+ const shouldShowBorderTopRightRadiusSelector = apiRef => !apiRef.current.state.dimensions.isReady ? apiRef.current.state.dimensions.scrollbarSize === 0 : apiRef.current.state.dimensions.hasScrollX && (!apiRef.current.state.dimensions.hasScrollY || apiRef.current.state.dimensions.scrollbarSize === 0);
19
19
  export const GridRootStyles = styled('div', {
20
20
  name: 'MuiDataGrid',
21
21
  slot: 'Root',
@@ -29,7 +29,7 @@ const ToolbarRoot = styled('div', {
29
29
  name: 'MuiDataGrid',
30
30
  slot: 'Toolbar'
31
31
  })({
32
- flex: 0,
32
+ flex: '0 1 1px',
33
33
  display: 'flex',
34
34
  alignItems: 'center',
35
35
  justifyContent: 'end',
@@ -7,6 +7,7 @@ type GridVirtualScrollbarProps = {
7
7
  top: number;
8
8
  }>;
9
9
  };
10
+ export declare const scrollbarSizeCssExpression = "calc(max(var(--DataGrid-scrollbarSize), 14px))";
10
11
  export declare const ScrollbarCorner: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/system").Theme> & React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement>, {}, {}>;
11
12
  declare const GridVirtualScrollbar: React.ForwardRefExoticComponent<GridVirtualScrollbarProps> | React.ForwardRefExoticComponent<GridVirtualScrollbarProps & React.RefAttributes<HTMLDivElement>>;
12
13
  export { GridVirtualScrollbar };
@@ -22,6 +22,12 @@ const useUtilityClasses = (ownerState, position) => {
22
22
  };
23
23
  return composeClasses(slots, getDataGridUtilityClass, classes);
24
24
  };
25
+
26
+ // In macOS Safari and Gnome Web, scrollbars are overlaid and don't affect the layout. So we consider
27
+ // their size to be 0px throughout all the calculations, but the floating scrollbar container does need
28
+ // to appear and have a real size. We set it to 14px because it seems like an acceptable value and we
29
+ // don't have a method to find the required size for scrollbars on those platforms.
30
+ export const scrollbarSizeCssExpression = 'calc(max(var(--DataGrid-scrollbarSize), 14px))';
25
31
  const Scrollbar = styled('div')({
26
32
  position: 'absolute',
27
33
  display: 'inline-block',
@@ -29,11 +35,7 @@ const Scrollbar = styled('div')({
29
35
  '&:hover': {
30
36
  zIndex: 70
31
37
  },
32
- // In macOS Safari and Gnome Web, scrollbars are overlaid and don't affect the layout. So we consider
33
- // their size to be 0px throughout all the calculations, but the floating scrollbar container does need
34
- // to appear and have a real size. We set it to 14px because it seems like an acceptable value and we
35
- // don't have a method to find the required size for scrollbars on those platforms.
36
- '--size': 'calc(max(var(--DataGrid-scrollbarSize), 14px))'
38
+ '--size': scrollbarSizeCssExpression
37
39
  });
38
40
  const ScrollbarVertical = styled(Scrollbar)({
39
41
  width: 'var(--size)',
@@ -65,7 +67,10 @@ export const ScrollbarCorner = styled(Scrollbar)({
65
67
  height: 'var(--size)',
66
68
  right: 0,
67
69
  bottom: 0,
68
- overflow: 'scroll'
70
+ overflow: 'scroll',
71
+ '@media print': {
72
+ display: 'none'
73
+ }
69
74
  });
70
75
  const GridVirtualScrollbar = forwardRef(function GridVirtualScrollbar(props, ref) {
71
76
  const apiRef = useGridPrivateApiContext();
@@ -94,7 +99,7 @@ const GridVirtualScrollbar = forwardRef(function GridVirtualScrollbar(props, ref
94
99
  return;
95
100
  }
96
101
  isLocked.current = true;
97
- scrollbar[propertyScroll] = scrollPosition[propertyScrollPosition];
102
+ scrollbar[propertyScroll] = props.scrollPosition.current[propertyScrollPosition];
98
103
  });
99
104
  const onScrollbarScroll = useEventCallback(() => {
100
105
  const scroller = apiRef.current.virtualScrollerRef.current;
@@ -19,6 +19,7 @@ import { GridVirtualScrollerRenderZone as RenderZone } from "./GridVirtualScroll
19
19
  import { GridVirtualScrollbar as Scrollbar, ScrollbarCorner } from "./GridVirtualScrollbar.js";
20
20
  import { GridScrollShadows as ScrollShadows } from "../GridScrollShadows.js";
21
21
  import { GridOverlayWrapper } from "../base/GridOverlays.js";
22
+ import { useGridVirtualizer } from "../../hooks/core/useGridVirtualizer.js";
22
23
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
23
24
  const useUtilityClasses = ownerState => {
24
25
  const {
@@ -82,7 +83,7 @@ function GridVirtualScroller(props) {
82
83
  loadingOverlayVariant
83
84
  };
84
85
  const classes = useUtilityClasses(ownerState);
85
- const virtualScroller = apiRef.current.virtualizer.api.useVirtualization().getters;
86
+ const virtualScroller = useGridVirtualizer().api.getters;
86
87
  const {
87
88
  getContainerProps,
88
89
  getScrollerProps,
@@ -36,7 +36,7 @@ const GridVirtualScrollerRenderZone = forwardRef(function GridVirtualScrollerRen
36
36
  const apiRef = useGridPrivateApiContext();
37
37
  const rootProps = useGridRootProps();
38
38
  const classes = useUtilityClasses(rootProps);
39
- const offsetTop = apiRef.current.virtualizer.api.useVirtualization().getters.getOffsetTop();
39
+ const offsetTop = apiRef.current.virtualizer.api.getters.getOffsetTop();
40
40
  return /*#__PURE__*/_jsx(VirtualScrollerRenderZoneRoot, _extends({
41
41
  className: clsx(classes.root, className),
42
42
  ownerState: rootProps,
@@ -57,5 +57,6 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES = {
57
57
  sortingMode: 'client',
58
58
  sortingOrder: ['asc', 'desc', null],
59
59
  throttleRowsMs: 0,
60
- virtualizeColumnsWithAutoRowHeight: false
60
+ virtualizeColumnsWithAutoRowHeight: false,
61
+ tabNavigation: 'none'
61
62
  };
@@ -6,4 +6,5 @@ import type { GridRowId } from "../../models/gridRows.js";
6
6
  * @param {GridRowModel} row - The row to get the id for
7
7
  * @returns {GridRowId} The row id
8
8
  */
9
- export declare const gridRowIdSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, import("@mui/x-data-grid").GridValidRowModel, GridRowId>;
9
+ export declare const gridRowIdSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, import("@mui/x-data-grid").GridValidRowModel, GridRowId>;
10
+ export declare const gridRowSelectableSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, unknown, ((params: import("@mui/x-data-grid").GridRowParams<any>) => boolean) | undefined>;
@@ -12,4 +12,7 @@ export const gridRowIdSelector = createRootSelector((state, row) => {
12
12
  return row[GRID_ID_AUTOGENERATED];
13
13
  }
14
14
  return state.props.getRowId ? state.props.getRowId(row) : row.id;
15
+ });
16
+ export const gridRowSelectableSelector = createRootSelector(state => {
17
+ return state.props.isRowSelectable;
15
18
  });
@@ -12,13 +12,19 @@ export const propsStateInitializer = (state, props) => {
12
12
  });
13
13
  };
14
14
  export const useGridProps = (apiRef, props) => {
15
+ const isFirstRender = React.useRef(true);
15
16
  React.useEffect(() => {
17
+ if (isFirstRender.current) {
18
+ isFirstRender.current = false;
19
+ return;
20
+ }
16
21
  apiRef.current.setState(state => _extends({}, state, {
17
22
  props: {
18
23
  listView: props.listView,
19
24
  getRowId: props.getRowId,
20
- isCellEditable: props.isCellEditable
25
+ isCellEditable: props.isCellEditable,
26
+ isRowSelectable: props.isRowSelectable
21
27
  }
22
28
  }));
23
- }, [apiRef, props.listView, props.getRowId, props.isCellEditable]);
29
+ }, [apiRef, props.listView, props.getRowId, props.isCellEditable, props.isRowSelectable]);
24
30
  };