@mui/x-data-grid 8.17.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 (114) hide show
  1. package/CHANGELOG.md +213 -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 -36
  6. package/components/cell/GridActionsCellItem.js +0 -4
  7. package/components/cell/GridBooleanCell.js +0 -10
  8. package/components/cell/GridCell.js +4 -10
  9. package/components/columnHeaders/GridColumnHeaderItem.js +2 -2
  10. package/components/columnSelection/GridCellCheckboxRenderer.js +37 -22
  11. package/components/containers/GridRootStyles.js +1 -1
  12. package/components/toolbarV8/Toolbar.js +1 -1
  13. package/components/virtualization/GridVirtualScrollbar.d.ts +1 -0
  14. package/components/virtualization/GridVirtualScrollbar.js +13 -8
  15. package/components/virtualization/GridVirtualScroller.js +2 -1
  16. package/components/virtualization/GridVirtualScrollerRenderZone.js +1 -1
  17. package/constants/dataGridPropsDefaultValues.js +2 -1
  18. package/esm/DataGrid/useDataGridComponent.js +5 -4
  19. package/esm/components/GridRow.js +1 -1
  20. package/esm/components/cell/GridActionsCell.d.ts +9 -0
  21. package/esm/components/cell/GridActionsCell.js +55 -36
  22. package/esm/components/cell/GridActionsCellItem.js +0 -4
  23. package/esm/components/cell/GridBooleanCell.js +0 -10
  24. package/esm/components/cell/GridCell.js +4 -10
  25. package/esm/components/columnHeaders/GridColumnHeaderItem.js +2 -2
  26. package/esm/components/columnSelection/GridCellCheckboxRenderer.js +37 -22
  27. package/esm/components/containers/GridRootStyles.js +1 -1
  28. package/esm/components/toolbarV8/Toolbar.js +1 -1
  29. package/esm/components/virtualization/GridVirtualScrollbar.d.ts +1 -0
  30. package/esm/components/virtualization/GridVirtualScrollbar.js +12 -7
  31. package/esm/components/virtualization/GridVirtualScroller.js +2 -1
  32. package/esm/components/virtualization/GridVirtualScrollerRenderZone.js +1 -1
  33. package/esm/constants/dataGridPropsDefaultValues.js +2 -1
  34. package/esm/hooks/core/gridPropsSelectors.d.ts +2 -1
  35. package/esm/hooks/core/gridPropsSelectors.js +3 -0
  36. package/esm/hooks/core/useGridProps.js +8 -2
  37. package/esm/hooks/core/useGridVirtualizer.d.ts +80 -6
  38. package/esm/hooks/core/useGridVirtualizer.js +27 -12
  39. package/esm/hooks/features/columnGrouping/useGridColumnGrouping.js +6 -1
  40. package/esm/hooks/features/columnMenu/useGridColumnMenu.js +14 -4
  41. package/esm/hooks/features/columns/useGridColumnSpanning.js +9 -4
  42. package/esm/hooks/features/dimensions/useGridDimensions.js +12 -6
  43. package/esm/hooks/features/export/useGridPrintExport.js +18 -18
  44. package/esm/hooks/features/filter/useGridFilter.d.ts +1 -1
  45. package/esm/hooks/features/filter/useGridFilter.js +3 -1
  46. package/esm/hooks/features/focus/useGridFocus.js +0 -1
  47. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  48. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +189 -25
  49. package/esm/hooks/features/pagination/useGridPaginationMeta.js +3 -3
  50. package/esm/hooks/features/pagination/useGridPaginationModel.js +7 -4
  51. package/esm/hooks/features/pagination/useGridRowCount.js +31 -15
  52. package/esm/hooks/features/rowSelection/useGridRowSelection.js +8 -7
  53. package/esm/hooks/features/rowSelection/utils.d.ts +1 -0
  54. package/esm/hooks/features/rowSelection/utils.js +17 -4
  55. package/esm/hooks/features/rows/gridRowSpanningUtils.js +8 -5
  56. package/esm/hooks/features/rows/useGridParamsApi.js +2 -12
  57. package/esm/hooks/features/rows/useGridRowSpanning.js +23 -60
  58. package/esm/hooks/features/scroll/useGridScroll.js +2 -3
  59. package/esm/hooks/features/sorting/useGridSorting.d.ts +1 -1
  60. package/esm/hooks/features/sorting/useGridSorting.js +3 -1
  61. package/esm/hooks/features/virtualization/useGridVirtualization.js +24 -5
  62. package/esm/hooks/utils/useGridApiRef.d.ts +1 -2
  63. package/esm/hooks/utils/useGridEvent.js +6 -2
  64. package/esm/hooks/utils/useRunOncePerLoop.d.ts +4 -1
  65. package/esm/hooks/utils/useRunOncePerLoop.js +28 -18
  66. package/esm/index.js +1 -1
  67. package/esm/models/colDef/gridColDef.d.ts +14 -0
  68. package/esm/models/events/gridEventLookup.d.ts +5 -0
  69. package/esm/models/gridStateCommunity.d.ts +1 -1
  70. package/esm/models/params/gridCellParams.d.ts +0 -10
  71. package/esm/models/props/DataGridProps.d.ts +13 -6
  72. package/esm/utils/keyboardUtils.d.ts +1 -8
  73. package/esm/utils/keyboardUtils.js +0 -7
  74. package/hooks/core/gridPropsSelectors.d.ts +2 -1
  75. package/hooks/core/gridPropsSelectors.js +4 -1
  76. package/hooks/core/useGridProps.js +8 -2
  77. package/hooks/core/useGridVirtualizer.d.ts +80 -6
  78. package/hooks/core/useGridVirtualizer.js +26 -11
  79. package/hooks/features/columnGrouping/useGridColumnGrouping.js +6 -1
  80. package/hooks/features/columnMenu/useGridColumnMenu.js +14 -4
  81. package/hooks/features/columns/useGridColumnSpanning.js +9 -4
  82. package/hooks/features/dimensions/useGridDimensions.js +12 -6
  83. package/hooks/features/export/useGridPrintExport.js +18 -18
  84. package/hooks/features/filter/useGridFilter.d.ts +1 -1
  85. package/hooks/features/filter/useGridFilter.js +3 -1
  86. package/hooks/features/focus/useGridFocus.js +0 -1
  87. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  88. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +189 -25
  89. package/hooks/features/pagination/useGridPaginationMeta.js +2 -2
  90. package/hooks/features/pagination/useGridPaginationModel.js +7 -4
  91. package/hooks/features/pagination/useGridRowCount.js +30 -14
  92. package/hooks/features/rowSelection/useGridRowSelection.js +8 -7
  93. package/hooks/features/rowSelection/utils.d.ts +1 -0
  94. package/hooks/features/rowSelection/utils.js +16 -3
  95. package/hooks/features/rows/gridRowSpanningUtils.js +8 -5
  96. package/hooks/features/rows/useGridParamsApi.js +2 -12
  97. package/hooks/features/rows/useGridRowSpanning.js +23 -60
  98. package/hooks/features/scroll/useGridScroll.js +2 -3
  99. package/hooks/features/sorting/useGridSorting.d.ts +1 -1
  100. package/hooks/features/sorting/useGridSorting.js +3 -1
  101. package/hooks/features/virtualization/useGridVirtualization.js +24 -5
  102. package/hooks/utils/useGridApiRef.d.ts +1 -2
  103. package/hooks/utils/useGridEvent.js +6 -2
  104. package/hooks/utils/useRunOncePerLoop.d.ts +4 -1
  105. package/hooks/utils/useRunOncePerLoop.js +27 -18
  106. package/index.js +1 -1
  107. package/models/colDef/gridColDef.d.ts +14 -0
  108. package/models/events/gridEventLookup.d.ts +5 -0
  109. package/models/gridStateCommunity.d.ts +1 -1
  110. package/models/params/gridCellParams.d.ts +0 -10
  111. package/models/props/DataGridProps.d.ts +13 -6
  112. package/package.json +4 -4
  113. package/utils/keyboardUtils.d.ts +1 -8
  114. package/utils/keyboardUtils.js +1 -13
@@ -21,7 +21,7 @@ const separatorIconDragStyles = {
21
21
  // Emotion thinks it knows better than us which selector we should use.
22
22
  // https://github.com/emotion-js/emotion/issues/1105#issuecomment-1722524968
23
23
  const ignoreSsrWarning = '/* emotion-disable-server-rendering-unsafe-selector-warning-please-do-not-use-this-the-warning-exists-for-a-reason */';
24
- const shouldShowBorderTopRightRadiusSelector = apiRef => apiRef.current.state.dimensions.hasScrollX && (!apiRef.current.state.dimensions.hasScrollY || apiRef.current.state.dimensions.scrollbarSize === 0);
24
+ 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);
25
25
  const GridRootStyles = exports.GridRootStyles = (0, _styles.styled)('div', {
26
26
  name: 'MuiDataGrid',
27
27
  slot: 'Root',
@@ -36,7 +36,7 @@ const ToolbarRoot = (0, _system.styled)('div', {
36
36
  name: 'MuiDataGrid',
37
37
  slot: 'Toolbar'
38
38
  })({
39
- flex: 0,
39
+ flex: '0 1 1px',
40
40
  display: 'flex',
41
41
  alignItems: 'center',
42
42
  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 };
@@ -6,7 +6,7 @@ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWild
6
6
  Object.defineProperty(exports, "__esModule", {
7
7
  value: true
8
8
  });
9
- exports.ScrollbarCorner = exports.GridVirtualScrollbar = void 0;
9
+ exports.scrollbarSizeCssExpression = exports.ScrollbarCorner = exports.GridVirtualScrollbar = void 0;
10
10
  var React = _interopRequireWildcard(require("react"));
11
11
  var _system = require("@mui/system");
12
12
  var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
@@ -29,6 +29,12 @@ const useUtilityClasses = (ownerState, position) => {
29
29
  };
30
30
  return (0, _composeClasses.default)(slots, _gridClasses.getDataGridUtilityClass, classes);
31
31
  };
32
+
33
+ // In macOS Safari and Gnome Web, scrollbars are overlaid and don't affect the layout. So we consider
34
+ // their size to be 0px throughout all the calculations, but the floating scrollbar container does need
35
+ // to appear and have a real size. We set it to 14px because it seems like an acceptable value and we
36
+ // don't have a method to find the required size for scrollbars on those platforms.
37
+ const scrollbarSizeCssExpression = exports.scrollbarSizeCssExpression = 'calc(max(var(--DataGrid-scrollbarSize), 14px))';
32
38
  const Scrollbar = (0, _system.styled)('div')({
33
39
  position: 'absolute',
34
40
  display: 'inline-block',
@@ -36,11 +42,7 @@ const Scrollbar = (0, _system.styled)('div')({
36
42
  '&:hover': {
37
43
  zIndex: 70
38
44
  },
39
- // In macOS Safari and Gnome Web, scrollbars are overlaid and don't affect the layout. So we consider
40
- // their size to be 0px throughout all the calculations, but the floating scrollbar container does need
41
- // to appear and have a real size. We set it to 14px because it seems like an acceptable value and we
42
- // don't have a method to find the required size for scrollbars on those platforms.
43
- '--size': 'calc(max(var(--DataGrid-scrollbarSize), 14px))'
45
+ '--size': scrollbarSizeCssExpression
44
46
  });
45
47
  const ScrollbarVertical = (0, _system.styled)(Scrollbar)({
46
48
  width: 'var(--size)',
@@ -72,7 +74,10 @@ const ScrollbarCorner = exports.ScrollbarCorner = (0, _system.styled)(Scrollbar)
72
74
  height: 'var(--size)',
73
75
  right: 0,
74
76
  bottom: 0,
75
- overflow: 'scroll'
77
+ overflow: 'scroll',
78
+ '@media print': {
79
+ display: 'none'
80
+ }
76
81
  });
77
82
  const GridVirtualScrollbar = exports.GridVirtualScrollbar = (0, _forwardRef.forwardRef)(function GridVirtualScrollbar(props, ref) {
78
83
  const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)();
@@ -101,7 +106,7 @@ const GridVirtualScrollbar = exports.GridVirtualScrollbar = (0, _forwardRef.forw
101
106
  return;
102
107
  }
103
108
  isLocked.current = true;
104
- scrollbar[propertyScroll] = scrollPosition[propertyScrollPosition];
109
+ scrollbar[propertyScroll] = props.scrollPosition.current[propertyScrollPosition];
105
110
  });
106
111
  const onScrollbarScroll = (0, _useEventCallback.default)(() => {
107
112
  const scroller = apiRef.current.virtualScrollerRef.current;
@@ -27,6 +27,7 @@ var _GridVirtualScrollerRenderZone = require("./GridVirtualScrollerRenderZone");
27
27
  var _GridVirtualScrollbar = require("./GridVirtualScrollbar");
28
28
  var _GridScrollShadows = require("../GridScrollShadows");
29
29
  var _GridOverlays = require("../base/GridOverlays");
30
+ var _useGridVirtualizer = require("../../hooks/core/useGridVirtualizer");
30
31
  var _jsxRuntime = require("react/jsx-runtime");
31
32
  const useUtilityClasses = ownerState => {
32
33
  const {
@@ -90,7 +91,7 @@ function GridVirtualScroller(props) {
90
91
  loadingOverlayVariant
91
92
  };
92
93
  const classes = useUtilityClasses(ownerState);
93
- const virtualScroller = apiRef.current.virtualizer.api.useVirtualization().getters;
94
+ const virtualScroller = (0, _useGridVirtualizer.useGridVirtualizer)().api.getters;
94
95
  const {
95
96
  getContainerProps,
96
97
  getScrollerProps,
@@ -44,7 +44,7 @@ const GridVirtualScrollerRenderZone = exports.GridVirtualScrollerRenderZone = (0
44
44
  const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)();
45
45
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
46
46
  const classes = useUtilityClasses(rootProps);
47
- const offsetTop = apiRef.current.virtualizer.api.useVirtualization().getters.getOffsetTop();
47
+ const offsetTop = apiRef.current.virtualizer.api.getters.getOffsetTop();
48
48
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(VirtualScrollerRenderZoneRoot, (0, _extends2.default)({
49
49
  className: (0, _clsx.default)(classes.root, className),
50
50
  ownerState: rootProps,
@@ -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);
@@ -104,8 +114,6 @@ function GridActionsCell(props) {
104
114
  touchRippleRefs.current[index] = instance;
105
115
  };
106
116
  const handleButtonClick = (index, onClick) => event => {
107
- event.stopPropagation();
108
- event.preventDefault();
109
117
  setFocusedButtonIndex(index);
110
118
  ignoreCallToFocus.current = true;
111
119
  if (onClick) {
@@ -117,7 +125,7 @@ function GridActionsCell(props) {
117
125
  return;
118
126
  }
119
127
  const getNewIndex = (index, direction) => {
120
- if (index < 0 || index > options.length) {
128
+ if (index < 0 || index > actions.length) {
121
129
  return index;
122
130
  }
123
131
 
@@ -126,7 +134,7 @@ function GridActionsCell(props) {
126
134
  const indexMod = (direction === 'left' ? -1 : 1) * rtlMod;
127
135
 
128
136
  // if the button that should receive focus is disabled go one more step
129
- 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;
130
138
  };
131
139
  let newIndex = focusedButtonIndex;
132
140
  if (event.key === 'ArrowRight') {
@@ -203,6 +211,7 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
203
211
  * The mode of the cell.
204
212
  */
205
213
  cellMode: PropTypes.oneOf(['edit', 'view']).isRequired,
214
+ children: PropTypes.node.isRequired,
206
215
  /**
207
216
  * The column of the row that the current cell belongs to.
208
217
  */
@@ -211,16 +220,6 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
211
220
  * The column field of the cell that triggered the event.
212
221
  */
213
222
  field: PropTypes.string.isRequired,
214
- /**
215
- * A ref allowing to set imperative focus.
216
- * It can be passed to the element that should receive focus.
217
- * @ignore - do not document.
218
- */
219
- focusElementRef: PropTypes.oneOfType([PropTypes.func, PropTypes.shape({
220
- current: PropTypes.shape({
221
- focus: PropTypes.func.isRequired
222
- })
223
- })]),
224
223
  /**
225
224
  * The cell value formatted with the column valueFormatter.
226
225
  */
@@ -257,5 +256,25 @@ process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes = {
257
256
  value: PropTypes.any
258
257
  } : void 0;
259
258
  export { GridActionsCell };
260
- 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));
261
280
  if (process.env.NODE_ENV !== "production") renderActionsCell.displayName = "renderActionsCell";
@@ -16,8 +16,6 @@ const GridActionsCellItem = forwardRef((props, ref) => {
16
16
  } = props,
17
17
  other = _objectWithoutPropertiesLoose(props, _excluded);
18
18
  const handleClick = event => {
19
- event.stopPropagation();
20
- event.preventDefault();
21
19
  onClick?.(event);
22
20
  };
23
21
  return /*#__PURE__*/_jsx(rootProps.slots.baseIconButton, _extends({
@@ -42,8 +40,6 @@ const GridActionsCellItem = forwardRef((props, ref) => {
42
40
  } = props,
43
41
  other = _objectWithoutPropertiesLoose(props, _excluded2);
44
42
  const handleClick = event => {
45
- event.stopPropagation();
46
- event.preventDefault();
47
43
  onClick?.(event);
48
44
  if (closeMenuOnClick) {
49
45
  closeMenu?.();
@@ -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 };