@mui/x-data-grid 9.3.0 → 9.5.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 (110) hide show
  1. package/CHANGELOG.md +296 -0
  2. package/colDef/gridColumnTypesRegistry.d.mts +8 -0
  3. package/colDef/gridColumnTypesRegistry.d.ts +8 -0
  4. package/colDef/gridColumnTypesRegistry.js +44 -0
  5. package/colDef/gridColumnTypesRegistry.mjs +34 -0
  6. package/colDef/gridDefaultColumnTypes.d.mts +1 -1
  7. package/colDef/gridDefaultColumnTypes.d.ts +1 -1
  8. package/colDef/gridDefaultColumnTypes.js +11 -23
  9. package/colDef/gridDefaultColumnTypes.mjs +4 -22
  10. package/components/GridRow.js +9 -1
  11. package/components/GridRow.mjs +9 -1
  12. package/components/cell/GridActionsCell.js +1 -1
  13. package/components/cell/GridActionsCell.mjs +1 -1
  14. package/components/cell/GridActionsCellItem.js +1 -1
  15. package/components/cell/GridActionsCellItem.mjs +1 -1
  16. package/components/cell/GridLongTextCell.js +2 -0
  17. package/components/cell/GridLongTextCell.mjs +2 -0
  18. package/components/cell/GridSkeletonCell.d.mts +2 -1
  19. package/components/cell/GridSkeletonCell.d.ts +2 -1
  20. package/components/cell/GridSkeletonCell.js +8 -3
  21. package/components/cell/GridSkeletonCell.mjs +8 -3
  22. package/components/containers/GridRootStyles.js +29 -0
  23. package/components/containers/GridRootStyles.mjs +29 -0
  24. package/components/panel/filterPanel/GridFilterInputSingleSelect.js +2 -4
  25. package/components/panel/filterPanel/GridFilterInputSingleSelect.mjs +2 -4
  26. package/components/panel/filterPanel/filterPanelUtils.d.mts +3 -2
  27. package/components/panel/filterPanel/filterPanelUtils.d.ts +3 -2
  28. package/components/panel/filterPanel/filterPanelUtils.js +4 -0
  29. package/components/panel/filterPanel/filterPanelUtils.mjs +3 -0
  30. package/constants/cssVariables.d.mts +3 -0
  31. package/constants/cssVariables.d.ts +3 -0
  32. package/constants/cssVariables.js +2 -1
  33. package/constants/cssVariables.mjs +2 -1
  34. package/constants/gridClasses.d.mts +48 -0
  35. package/constants/gridClasses.d.ts +48 -0
  36. package/constants/gridClasses.js +1 -1
  37. package/constants/gridClasses.mjs +1 -1
  38. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.mts +17 -1
  39. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.ts +17 -1
  40. package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +2 -1
  41. package/hooks/core/strategyProcessing/useGridStrategyProcessing.mjs +2 -1
  42. package/hooks/core/useGridProps.js +5 -3
  43. package/hooks/core/useGridProps.mjs +5 -3
  44. package/hooks/core/useGridVirtualizer.d.mts +10 -10
  45. package/hooks/core/useGridVirtualizer.d.ts +10 -10
  46. package/hooks/features/columns/gridColumnsUtils.js +18 -10
  47. package/hooks/features/columns/gridColumnsUtils.mjs +19 -11
  48. package/hooks/features/columns/useGridColumns.js +11 -0
  49. package/hooks/features/columns/useGridColumns.mjs +11 -0
  50. package/hooks/features/dataSource/models.d.mts +1 -1
  51. package/hooks/features/dataSource/models.d.ts +1 -1
  52. package/hooks/features/dataSource/useGridDataSourceBase.d.mts +2 -2
  53. package/hooks/features/dataSource/useGridDataSourceBase.d.ts +2 -2
  54. package/hooks/features/dataSource/useGridDataSourceBase.js +31 -19
  55. package/hooks/features/dataSource/useGridDataSourceBase.mjs +31 -19
  56. package/hooks/features/dataSource/utils.d.mts +1 -0
  57. package/hooks/features/dataSource/utils.d.ts +1 -0
  58. package/hooks/features/dataSource/utils.js +1 -0
  59. package/hooks/features/dataSource/utils.mjs +1 -0
  60. package/hooks/features/editing/useGridCellEditing.js +1 -1
  61. package/hooks/features/editing/useGridCellEditing.mjs +1 -1
  62. package/hooks/features/editing/useGridRowEditing.js +1 -1
  63. package/hooks/features/editing/useGridRowEditing.mjs +1 -1
  64. package/hooks/features/export/serializers/csvSerializer.js +3 -1
  65. package/hooks/features/export/serializers/csvSerializer.mjs +3 -1
  66. package/hooks/features/filter/gridFilterUtils.js +5 -3
  67. package/hooks/features/filter/gridFilterUtils.mjs +5 -3
  68. package/hooks/features/listView/useGridListView.js +1 -1
  69. package/hooks/features/listView/useGridListView.mjs +1 -1
  70. package/hooks/features/sorting/gridSortingUtils.js +3 -1
  71. package/hooks/features/sorting/gridSortingUtils.mjs +3 -1
  72. package/hooks/features/virtualization/gridVirtualizationSelectors.d.mts +1 -1
  73. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  74. package/hooks/utils/useGridSelector.js +26 -23
  75. package/hooks/utils/useGridSelector.mjs +25 -23
  76. package/index.js +1 -1
  77. package/index.mjs +1 -1
  78. package/internals/index.d.mts +9 -4
  79. package/internals/index.d.ts +9 -4
  80. package/internals/index.js +62 -2
  81. package/internals/index.mjs +8 -4
  82. package/internals/utils/propValidation.js +3 -0
  83. package/internals/utils/propValidation.mjs +3 -0
  84. package/material/augmentation.d.mts +4 -0
  85. package/material/augmentation.d.ts +4 -0
  86. package/material/index.js +38 -24
  87. package/material/index.mjs +38 -24
  88. package/material/variables.js +2 -1
  89. package/material/variables.mjs +2 -1
  90. package/models/colDef/gridColDef.d.mts +35 -3
  91. package/models/colDef/gridColDef.d.ts +35 -3
  92. package/models/colDef/gridColType.d.mts +1 -0
  93. package/models/colDef/gridColType.d.ts +1 -0
  94. package/models/colDef/gridColumnTypesRecord.d.mts +1 -1
  95. package/models/colDef/gridColumnTypesRecord.d.ts +1 -1
  96. package/models/colDef/index.d.mts +1 -1
  97. package/models/colDef/index.d.ts +1 -1
  98. package/models/gridBaseSlots.d.mts +46 -0
  99. package/models/gridBaseSlots.d.ts +46 -0
  100. package/models/gridDataSource.d.mts +6 -0
  101. package/models/gridDataSource.d.ts +6 -0
  102. package/models/gridRows.d.mts +0 -1
  103. package/models/gridRows.d.ts +0 -1
  104. package/models/gridSlotsComponent.d.mts +5 -0
  105. package/models/gridSlotsComponent.d.ts +5 -0
  106. package/models/gridSlotsComponentsProps.d.mts +3 -1
  107. package/models/gridSlotsComponentsProps.d.ts +3 -1
  108. package/models/gridStateCommunity.d.mts +1 -1
  109. package/models/gridStateCommunity.d.ts +1 -1
  110. package/package.json +4 -4
@@ -10,6 +10,7 @@ let DataSourceRowsUpdateStrategy = exports.DataSourceRowsUpdateStrategy = /*#__P
10
10
  DataSourceRowsUpdateStrategy["Default"] = "set-flat-rows";
11
11
  DataSourceRowsUpdateStrategy["LazyLoading"] = "replace-row-range";
12
12
  DataSourceRowsUpdateStrategy["GroupedData"] = "set-grouped-rows";
13
+ DataSourceRowsUpdateStrategy["LazyLoadedGroupedData"] = "replace-grouped-row-range";
13
14
  return DataSourceRowsUpdateStrategy;
14
15
  }({});
15
16
  /**
@@ -3,6 +3,7 @@ export let DataSourceRowsUpdateStrategy = /*#__PURE__*/function (DataSourceRowsU
3
3
  DataSourceRowsUpdateStrategy["Default"] = "set-flat-rows";
4
4
  DataSourceRowsUpdateStrategy["LazyLoading"] = "replace-row-range";
5
5
  DataSourceRowsUpdateStrategy["GroupedData"] = "set-grouped-rows";
6
+ DataSourceRowsUpdateStrategy["LazyLoadedGroupedData"] = "replace-grouped-row-range";
6
7
  return DataSourceRowsUpdateStrategy;
7
8
  }({});
8
9
 
@@ -373,7 +373,7 @@ const useGridCellEditing = (apiRef, props) => {
373
373
  });
374
374
  if (onProcessRowUpdateError) {
375
375
  onProcessRowUpdateError(errorThrown);
376
- } else {
376
+ } else if (process.env.NODE_ENV !== 'production') {
377
377
  (0, _warning.warnOnce)(['MUI X: A call to `processRowUpdate()` threw an error which was not handled because `onProcessRowUpdateError()` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError()` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/persistence/.'], 'error');
378
378
  }
379
379
  };
@@ -366,7 +366,7 @@ export const useGridCellEditing = (apiRef, props) => {
366
366
  });
367
367
  if (onProcessRowUpdateError) {
368
368
  onProcessRowUpdateError(errorThrown);
369
- } else {
369
+ } else if (process.env.NODE_ENV !== 'production') {
370
370
  warnOnce(['MUI X: A call to `processRowUpdate()` threw an error which was not handled because `onProcessRowUpdateError()` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError()` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/persistence/.'], 'error');
371
371
  }
372
372
  };
@@ -470,7 +470,7 @@ const useGridRowEditing = (apiRef, props) => {
470
470
  }
471
471
  if (onProcessRowUpdateError) {
472
472
  onProcessRowUpdateError(errorThrown);
473
- } else {
473
+ } else if (process.env.NODE_ENV !== 'production') {
474
474
  (0, _warning.warnOnce)(['MUI X: A call to `processRowUpdate()` threw an error which was not handled because `onProcessRowUpdateError()` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError()` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/persistence/.'], 'error');
475
475
  }
476
476
  };
@@ -463,7 +463,7 @@ export const useGridRowEditing = (apiRef, props) => {
463
463
  }
464
464
  if (onProcessRowUpdateError) {
465
465
  onProcessRowUpdateError(errorThrown);
466
- } else {
466
+ } else if (process.env.NODE_ENV !== 'production') {
467
467
  warnOnce(['MUI X: A call to `processRowUpdate()` threw an error which was not handled because `onProcessRowUpdateError()` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError()` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/persistence/.'], 'error');
468
468
  }
469
469
  };
@@ -85,7 +85,9 @@ const serializeRow = ({
85
85
  columns.forEach(column => {
86
86
  const cellParams = getCellParams(id, column.field);
87
87
  if (String(cellParams.formattedValue) === '[object Object]') {
88
- (0, _warning.warnOnce)(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
88
+ if (process.env.NODE_ENV !== 'production') {
89
+ (0, _warning.warnOnce)(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
90
+ }
89
91
  }
90
92
  row.addValue(serializeCellValue(cellParams, {
91
93
  ignoreValueFormatter,
@@ -77,7 +77,9 @@ const serializeRow = ({
77
77
  columns.forEach(column => {
78
78
  const cellParams = getCellParams(id, column.field);
79
79
  if (String(cellParams.formattedValue) === '[object Object]') {
80
- warnOnce(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
80
+ if (process.env.NODE_ENV !== 'production') {
81
+ warnOnce(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
82
+ }
81
83
  }
82
84
  row.addValue(serializeCellValue(cellParams, {
83
85
  ignoreValueFormatter,
@@ -50,17 +50,19 @@ const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiRef) =>
50
50
  const hasSeveralItems = model.items.length > 1;
51
51
  let items;
52
52
  if (hasSeveralItems && disableMultipleColumnsFiltering) {
53
- (0, _warning.warnOnce)(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
53
+ if (process.env.NODE_ENV !== 'production') {
54
+ (0, _warning.warnOnce)(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
55
+ }
54
56
  items = [model.items[0]];
55
57
  } else {
56
58
  items = model.items;
57
59
  }
58
60
  const hasItemsWithoutIds = hasSeveralItems && items.some(item => item.id == null);
59
61
  const hasItemWithoutOperator = items.some(item => item.operator == null);
60
- if (hasItemsWithoutIds) {
62
+ if (hasItemsWithoutIds && process.env.NODE_ENV !== 'production') {
61
63
  (0, _warning.warnOnce)('MUI X: The `id` field is required on `filterModel.items` when you use multiple filters.', 'error');
62
64
  }
63
- if (hasItemWithoutOperator) {
65
+ if (hasItemWithoutOperator && process.env.NODE_ENV !== 'production') {
64
66
  (0, _warning.warnOnce)('MUI X: The `operator` field is required on `filterModel.items`, one or more of your filtering item has no `operator` provided.', 'error');
65
67
  }
66
68
  if (hasItemWithoutOperator || hasItemsWithoutIds) {
@@ -42,17 +42,19 @@ export const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiR
42
42
  const hasSeveralItems = model.items.length > 1;
43
43
  let items;
44
44
  if (hasSeveralItems && disableMultipleColumnsFiltering) {
45
- warnOnce(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
45
+ if (process.env.NODE_ENV !== 'production') {
46
+ warnOnce(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
47
+ }
46
48
  items = [model.items[0]];
47
49
  } else {
48
50
  items = model.items;
49
51
  }
50
52
  const hasItemsWithoutIds = hasSeveralItems && items.some(item => item.id == null);
51
53
  const hasItemWithoutOperator = items.some(item => item.operator == null);
52
- if (hasItemsWithoutIds) {
54
+ if (hasItemsWithoutIds && process.env.NODE_ENV !== 'production') {
53
55
  warnOnce('MUI X: The `id` field is required on `filterModel.items` when you use multiple filters.', 'error');
54
56
  }
55
- if (hasItemWithoutOperator) {
57
+ if (hasItemWithoutOperator && process.env.NODE_ENV !== 'production') {
56
58
  warnOnce('MUI X: The `operator` field is required on `filterModel.items`, one or more of your filtering item has no `operator` provided.', 'error');
57
59
  }
58
60
  if (hasItemWithoutOperator || hasItemsWithoutIds) {
@@ -62,7 +62,7 @@ function useGridListView(apiRef, props) {
62
62
  }
63
63
  }, [apiRef, props.listViewColumn]);
64
64
  React.useEffect(() => {
65
- if (props.listView && !props.listViewColumn) {
65
+ if (process.env.NODE_ENV !== 'production' && props.listView && !props.listViewColumn) {
66
66
  (0, _warning.warnOnce)(['MUI X: The `listViewColumn` prop must be set if `listView` is enabled.', 'To fix, pass a column definition to the `listViewColumn` prop, e.g. `{ field: "example", renderCell: (params) => <div>{params.row.id}</div> }`.', 'For more details, see https://mui.com/x/react-data-grid/list-view/']);
67
67
  }
68
68
  }, [props.listView, props.listViewColumn]);
@@ -53,7 +53,7 @@ export function useGridListView(apiRef, props) {
53
53
  }
54
54
  }, [apiRef, props.listViewColumn]);
55
55
  React.useEffect(() => {
56
- if (props.listView && !props.listViewColumn) {
56
+ if (process.env.NODE_ENV !== 'production' && props.listView && !props.listViewColumn) {
57
57
  warnOnce(['MUI X: The `listViewColumn` prop must be set if `listView` is enabled.', 'To fix, pass a column definition to the `listViewColumn` prop, e.g. `{ field: "example", renderCell: (params) => <div>{params.row.id}</div> }`.', 'For more details, see https://mui.com/x/react-data-grid/list-view/']);
58
58
  }
59
59
  }, [props.listView, props.listViewColumn]);
@@ -10,7 +10,9 @@ var _warning = require("@mui/x-internals/warning");
10
10
  var _gridRowsSelector = require("../rows/gridRowsSelector");
11
11
  const sanitizeSortModel = (model, disableMultipleColumnsSorting) => {
12
12
  if (disableMultipleColumnsSorting && model.length > 1) {
13
- (0, _warning.warnOnce)(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
13
+ if (process.env.NODE_ENV !== 'production') {
14
+ (0, _warning.warnOnce)(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
15
+ }
14
16
  return [model[0]];
15
17
  }
16
18
  return model;
@@ -3,7 +3,9 @@ import { warnOnce } from '@mui/x-internals/warning';
3
3
  import { gridRowNodeSelector } from "../rows/gridRowsSelector.mjs";
4
4
  export const sanitizeSortModel = (model, disableMultipleColumnsSorting) => {
5
5
  if (disableMultipleColumnsSorting && model.length > 1) {
6
- warnOnce(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
6
+ if (process.env.NODE_ENV !== 'production') {
7
+ warnOnce(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
8
+ }
7
9
  return [model[0]];
8
10
  }
9
11
  return model;
@@ -42,7 +42,7 @@ export declare const gridVirtualizationLayoutModeSelector: (args_0: import("reac
42
42
  */
43
43
  export declare const gridRenderContextSelector: (args_0: import("react").RefObject<{
44
44
  state: GridStateCommunity;
45
- } | null>) => import("@mui/x-virtualizer/models").RenderContext;
45
+ } | null>) => import("@mui/x-virtualizer").RenderContext;
46
46
  /**
47
47
  * Get the render context, with only columns filled in.
48
48
  * This is cached, so it can be used to only re-render when the column interval changes.
@@ -42,7 +42,7 @@ export declare const gridVirtualizationLayoutModeSelector: (args_0: import("reac
42
42
  */
43
43
  export declare const gridRenderContextSelector: (args_0: import("react").RefObject<{
44
44
  state: GridStateCommunity;
45
- } | null>) => import("@mui/x-virtualizer/models").RenderContext;
45
+ } | null>) => import("@mui/x-virtualizer").RenderContext;
46
46
  /**
47
47
  * Get the render context, with only columns filled in.
48
48
  * This is cached, so it can be used to only re-render when the column interval changes.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  'use client';
3
3
 
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
5
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
6
  Object.defineProperty(exports, "__esModule", {
6
7
  value: true
@@ -8,9 +9,9 @@ Object.defineProperty(exports, "__esModule", {
8
9
  exports.objectShallowCompare = void 0;
9
10
  exports.useGridSelector = useGridSelector;
10
11
  var React = _interopRequireWildcard(require("react"));
12
+ var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
11
13
  var _fastObjectShallowCompare = require("@mui/x-internals/fastObjectShallowCompare");
12
14
  var _warning = require("@mui/x-internals/warning");
13
- var _shim = require("use-sync-external-store/shim");
14
15
  var _useLazyRef = require("./useLazyRef");
15
16
  const defaultCompare = Object.is;
16
17
  const objectShallowCompare = exports.objectShallowCompare = _fastObjectShallowCompare.fastObjectShallowCompare;
@@ -33,12 +34,12 @@ const createRefs = () => ({
33
34
  state: null,
34
35
  equals: null,
35
36
  selector: null,
36
- args: undefined
37
+ args: undefined,
38
+ storeState: null
37
39
  });
38
40
  const EMPTY = [];
39
- const emptyGetSnapshot = () => null;
40
41
  function useGridSelector(apiRef, selector, args = undefined, equals = defaultCompare) {
41
- if (!apiRef.current.state) {
42
+ if (process.env.NODE_ENV !== 'production' && !apiRef.current.state) {
42
43
  (0, _warning.warnOnce)(['MUI X: `useGridSelector` has been called before the initialization of the state.', 'This hook can only be used inside the context of the grid.']);
43
44
  }
44
45
  const refs = (0, _useLazyRef.useLazyRef)(createRefs);
@@ -47,6 +48,9 @@ function useGridSelector(apiRef, selector, args = undefined, equals = defaultCom
47
48
  // We don't use an initialization function to avoid allocations
48
49
  didInit ? null : selector(apiRef, args));
49
50
  refs.current.state = state;
51
+ if (!didInit) {
52
+ refs.current.storeState = apiRef.current.store.state;
53
+ }
50
54
  refs.current.equals = equals;
51
55
  refs.current.selector = selector;
52
56
  const prevArgs = refs.current.args;
@@ -57,35 +61,34 @@ function useGridSelector(apiRef, selector, args = undefined, equals = defaultCom
57
61
  refs.current.state = newState;
58
62
  setState(newState);
59
63
  }
64
+ refs.current.storeState = apiRef.current.store.state;
60
65
  }
61
- const subscribe = React.useCallback(() => {
62
- if (refs.current.subscription) {
63
- return null;
64
- }
65
- refs.current.subscription = apiRef.current.store.subscribe(() => {
66
+ const updateState = React.useCallback(() => {
67
+ const storeState = apiRef.current.store.state;
68
+ if (refs.current.storeState !== storeState) {
66
69
  const newState = refs.current.selector(apiRef, refs.current.args);
70
+ refs.current.storeState = storeState;
67
71
  if (!refs.current.equals(refs.current.state, newState)) {
68
72
  refs.current.state = newState;
69
73
  setState(newState);
70
74
  }
71
- });
72
- return null;
75
+ }
73
76
  },
74
77
  // eslint-disable-next-line react-hooks/exhaustive-deps
75
78
  EMPTY);
76
- const unsubscribe = React.useCallback(() => {
77
- // Fixes issue in React Strict Mode, where getSnapshot is not called
78
- if (!refs.current.subscription) {
79
- subscribe();
80
- }
81
- return () => {
82
- if (refs.current.subscription) {
83
- refs.current.subscription();
84
- refs.current.subscription = undefined;
85
- }
86
- };
79
+
80
+ // Why subscribe in an effect instead of during render: a component can render without
81
+ // ever mounting (e.g. when it suspends during hydration). If it subscribed during render,
82
+ // it could receive a store update and call `setState` before being mounted (#17077).
83
+ // Effects only run for mounted components, so subscribing here is safe.
84
+ //
85
+ // Using a layout effect because the store may already have changed
86
+ // between render and mount (e.g. from a child's ref callback or layout effect).
87
+ // `updateState()` picks up such changes, so the corrected value is shown right away instead of in a second frame.
88
+ (0, _useEnhancedEffect.default)(() => {
89
+ updateState();
90
+ return apiRef.current.store.subscribe(updateState);
87
91
  // eslint-disable-next-line react-hooks/exhaustive-deps
88
92
  }, EMPTY);
89
- (0, _shim.useSyncExternalStore)(unsubscribe, subscribe, emptyGetSnapshot);
90
93
  return state;
91
94
  }
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
+ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
4
5
  import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare';
5
6
  import { warnOnce } from '@mui/x-internals/warning';
6
- import { useSyncExternalStore } from 'use-sync-external-store/shim';
7
7
  import { useLazyRef } from "./useLazyRef.mjs";
8
8
  const defaultCompare = Object.is;
9
9
  export const objectShallowCompare = fastObjectShallowCompare;
@@ -26,12 +26,12 @@ const createRefs = () => ({
26
26
  state: null,
27
27
  equals: null,
28
28
  selector: null,
29
- args: undefined
29
+ args: undefined,
30
+ storeState: null
30
31
  });
31
32
  const EMPTY = [];
32
- const emptyGetSnapshot = () => null;
33
33
  export function useGridSelector(apiRef, selector, args = undefined, equals = defaultCompare) {
34
- if (!apiRef.current.state) {
34
+ if (process.env.NODE_ENV !== 'production' && !apiRef.current.state) {
35
35
  warnOnce(['MUI X: `useGridSelector` has been called before the initialization of the state.', 'This hook can only be used inside the context of the grid.']);
36
36
  }
37
37
  const refs = useLazyRef(createRefs);
@@ -40,6 +40,9 @@ export function useGridSelector(apiRef, selector, args = undefined, equals = def
40
40
  // We don't use an initialization function to avoid allocations
41
41
  didInit ? null : selector(apiRef, args));
42
42
  refs.current.state = state;
43
+ if (!didInit) {
44
+ refs.current.storeState = apiRef.current.store.state;
45
+ }
43
46
  refs.current.equals = equals;
44
47
  refs.current.selector = selector;
45
48
  const prevArgs = refs.current.args;
@@ -50,35 +53,34 @@ export function useGridSelector(apiRef, selector, args = undefined, equals = def
50
53
  refs.current.state = newState;
51
54
  setState(newState);
52
55
  }
56
+ refs.current.storeState = apiRef.current.store.state;
53
57
  }
54
- const subscribe = React.useCallback(() => {
55
- if (refs.current.subscription) {
56
- return null;
57
- }
58
- refs.current.subscription = apiRef.current.store.subscribe(() => {
58
+ const updateState = React.useCallback(() => {
59
+ const storeState = apiRef.current.store.state;
60
+ if (refs.current.storeState !== storeState) {
59
61
  const newState = refs.current.selector(apiRef, refs.current.args);
62
+ refs.current.storeState = storeState;
60
63
  if (!refs.current.equals(refs.current.state, newState)) {
61
64
  refs.current.state = newState;
62
65
  setState(newState);
63
66
  }
64
- });
65
- return null;
67
+ }
66
68
  },
67
69
  // eslint-disable-next-line react-hooks/exhaustive-deps
68
70
  EMPTY);
69
- const unsubscribe = React.useCallback(() => {
70
- // Fixes issue in React Strict Mode, where getSnapshot is not called
71
- if (!refs.current.subscription) {
72
- subscribe();
73
- }
74
- return () => {
75
- if (refs.current.subscription) {
76
- refs.current.subscription();
77
- refs.current.subscription = undefined;
78
- }
79
- };
71
+
72
+ // Why subscribe in an effect instead of during render: a component can render without
73
+ // ever mounting (e.g. when it suspends during hydration). If it subscribed during render,
74
+ // it could receive a store update and call `setState` before being mounted (#17077).
75
+ // Effects only run for mounted components, so subscribing here is safe.
76
+ //
77
+ // Using a layout effect because the store may already have changed
78
+ // between render and mount (e.g. from a child's ref callback or layout effect).
79
+ // `updateState()` picks up such changes, so the corrected value is shown right away instead of in a second frame.
80
+ useEnhancedEffect(() => {
81
+ updateState();
82
+ return apiRef.current.store.subscribe(updateState);
80
83
  // eslint-disable-next-line react-hooks/exhaustive-deps
81
84
  }, EMPTY);
82
- useSyncExternalStore(unsubscribe, subscribe, emptyGetSnapshot);
83
85
  return state;
84
86
  }
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v9.3.0
2
+ * @mui/x-data-grid v9.5.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v9.3.0
2
+ * @mui/x-data-grid v9.5.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,4 +1,7 @@
1
1
  export type { GridBaseColDef, GridStateColDef, GridSingleSelectColDef } from "../models/colDef/gridColDef.mjs";
2
+ export { GRID_STRING_COL_DEF } from "../colDef/gridStringColDef.mjs";
3
+ export { registerGridColumnTypes } from "../colDef/gridColumnTypesRegistry.mjs";
4
+ export { gridRowIdSelector } from "../hooks/core/gridPropsSelectors.mjs";
2
5
  export { GridVirtualScroller } from "../components/virtualization/GridVirtualScroller.mjs";
3
6
  export { GridVirtualScrollerContent } from "../components/virtualization/GridVirtualScrollerContent.mjs";
4
7
  export { GridVirtualScrollerRenderZone } from "../components/virtualization/GridVirtualScrollerRenderZone.mjs";
@@ -16,7 +19,7 @@ export { vars } from "../constants/cssVariables.mjs";
16
19
  export { useGridVirtualizer } from "../hooks/core/useGridVirtualizer.mjs";
17
20
  export { propsStateInitializer } from "../hooks/core/useGridProps.mjs";
18
21
  export { getGridFilter } from "../components/panel/filterPanel/GridFilterPanel.mjs";
19
- export { getValueOptions } from "../components/panel/filterPanel/filterPanelUtils.mjs";
22
+ export { getValueOptions, getValueFromValueOptions, isMultiSelectColDef } from "../components/panel/filterPanel/filterPanelUtils.mjs";
20
23
  export { useGridRegisterPipeProcessor } from "../hooks/core/pipeProcessing/index.mjs";
21
24
  export type { GridPipeProcessor } from "../hooks/core/pipeProcessing/index.mjs";
22
25
  export { GridStrategyGroup, useGridRegisterStrategyProcessor, GRID_DEFAULT_STRATEGY } from "../hooks/core/strategyProcessing/index.mjs";
@@ -42,8 +45,8 @@ export { useGridCsvExport } from "../hooks/features/export/useGridCsvExport.mjs"
42
45
  export { useGridPrintExport } from "../hooks/features/export/useGridPrintExport.mjs";
43
46
  export { useGridFilter, filterStateInitializer } from "../hooks/features/filter/useGridFilter.mjs";
44
47
  export { defaultGridFilterLookup } from "../hooks/features/filter/gridFilterState.mjs";
45
- export { passFilterLogic } from "../hooks/features/filter/gridFilterUtils.mjs";
46
- export { gridFilteredChildrenCountLookupSelector, gridExpandedSortedRowTreeLevelPositionLookupSelector, gridFilteredSortedDepthRowEntriesSelector } from "../hooks/features/filter/gridFilterSelector.mjs";
48
+ export { passFilterLogic, removeDiacritics } from "../hooks/features/filter/gridFilterUtils.mjs";
49
+ export { gridFilteredChildrenCountLookupSelector, gridExpandedSortedRowTreeLevelPositionLookupSelector, gridFilteredSortedDepthRowEntriesSelector, gridFilterModelSelector } from "../hooks/features/filter/gridFilterSelector.mjs";
47
50
  export { isSingleSelectColDef } from "../components/panel/filterPanel/filterPanelUtils.mjs";
48
51
  export type { GridAggregatedFilterItemApplier, GridAggregatedFilterItemApplierResult } from "../hooks/features/filter/gridFilterState.mjs";
49
52
  export { useGridFocus, focusStateInitializer } from "../hooks/features/focus/useGridFocus.mjs";
@@ -90,6 +93,7 @@ export { useGridInitializeState } from "../hooks/utils/useGridInitializeState.mj
90
93
  export type { GridStateInitializer } from "../hooks/utils/useGridInitializeState.mjs";
91
94
  export { usePinnedScrollOffset } from "../hooks/utils/usePinnedScrollOffset.mjs";
92
95
  export type * as BaseSlots from "../models/gridBaseSlots.mjs";
96
+ export type { TextFieldProps, AutocompleteProps, SelectProps } from "../models/gridBaseSlots.mjs";
93
97
  export type * from "../models/props/DataGridProps.mjs";
94
98
  export type { GridAggregationPosition, GridAggregationCellMeta } from "../models/gridAggregation.mjs";
95
99
  export type { GridDataSourceApiBase, GridDataSourceApi, GridDataSourceBaseOptions, GridDataSourceFetchRowsParams } from "../hooks/features/dataSource/models.mjs";
@@ -126,4 +130,5 @@ export type { CellEditableConditionFn } from "../models/configuration/gridCellEd
126
130
  export * from "../hooks/features/pivoting/index.mjs";
127
131
  export { createSvgIcon } from "../material/icons/createSvgIcon.mjs";
128
132
  export { useGridPanelContext } from "../components/panel/GridPanelContext.mjs";
129
- export type { RowReorderDropPosition, RowReorderDragDirection } from "../models/api/gridRowApi.mjs";
133
+ export type { RowReorderDropPosition, RowReorderDragDirection } from "../models/api/gridRowApi.mjs";
134
+ export { useSyncExternalStore } from 'use-sync-external-store/shim';
@@ -1,4 +1,7 @@
1
1
  export type { GridBaseColDef, GridStateColDef, GridSingleSelectColDef } from "../models/colDef/gridColDef.js";
2
+ export { GRID_STRING_COL_DEF } from "../colDef/gridStringColDef.js";
3
+ export { registerGridColumnTypes } from "../colDef/gridColumnTypesRegistry.js";
4
+ export { gridRowIdSelector } from "../hooks/core/gridPropsSelectors.js";
2
5
  export { GridVirtualScroller } from "../components/virtualization/GridVirtualScroller.js";
3
6
  export { GridVirtualScrollerContent } from "../components/virtualization/GridVirtualScrollerContent.js";
4
7
  export { GridVirtualScrollerRenderZone } from "../components/virtualization/GridVirtualScrollerRenderZone.js";
@@ -16,7 +19,7 @@ export { vars } from "../constants/cssVariables.js";
16
19
  export { useGridVirtualizer } from "../hooks/core/useGridVirtualizer.js";
17
20
  export { propsStateInitializer } from "../hooks/core/useGridProps.js";
18
21
  export { getGridFilter } from "../components/panel/filterPanel/GridFilterPanel.js";
19
- export { getValueOptions } from "../components/panel/filterPanel/filterPanelUtils.js";
22
+ export { getValueOptions, getValueFromValueOptions, isMultiSelectColDef } from "../components/panel/filterPanel/filterPanelUtils.js";
20
23
  export { useGridRegisterPipeProcessor } from "../hooks/core/pipeProcessing/index.js";
21
24
  export type { GridPipeProcessor } from "../hooks/core/pipeProcessing/index.js";
22
25
  export { GridStrategyGroup, useGridRegisterStrategyProcessor, GRID_DEFAULT_STRATEGY } from "../hooks/core/strategyProcessing/index.js";
@@ -42,8 +45,8 @@ export { useGridCsvExport } from "../hooks/features/export/useGridCsvExport.js";
42
45
  export { useGridPrintExport } from "../hooks/features/export/useGridPrintExport.js";
43
46
  export { useGridFilter, filterStateInitializer } from "../hooks/features/filter/useGridFilter.js";
44
47
  export { defaultGridFilterLookup } from "../hooks/features/filter/gridFilterState.js";
45
- export { passFilterLogic } from "../hooks/features/filter/gridFilterUtils.js";
46
- export { gridFilteredChildrenCountLookupSelector, gridExpandedSortedRowTreeLevelPositionLookupSelector, gridFilteredSortedDepthRowEntriesSelector } from "../hooks/features/filter/gridFilterSelector.js";
48
+ export { passFilterLogic, removeDiacritics } from "../hooks/features/filter/gridFilterUtils.js";
49
+ export { gridFilteredChildrenCountLookupSelector, gridExpandedSortedRowTreeLevelPositionLookupSelector, gridFilteredSortedDepthRowEntriesSelector, gridFilterModelSelector } from "../hooks/features/filter/gridFilterSelector.js";
47
50
  export { isSingleSelectColDef } from "../components/panel/filterPanel/filterPanelUtils.js";
48
51
  export type { GridAggregatedFilterItemApplier, GridAggregatedFilterItemApplierResult } from "../hooks/features/filter/gridFilterState.js";
49
52
  export { useGridFocus, focusStateInitializer } from "../hooks/features/focus/useGridFocus.js";
@@ -90,6 +93,7 @@ export { useGridInitializeState } from "../hooks/utils/useGridInitializeState.js
90
93
  export type { GridStateInitializer } from "../hooks/utils/useGridInitializeState.js";
91
94
  export { usePinnedScrollOffset } from "../hooks/utils/usePinnedScrollOffset.js";
92
95
  export type * as BaseSlots from "../models/gridBaseSlots.js";
96
+ export type { TextFieldProps, AutocompleteProps, SelectProps } from "../models/gridBaseSlots.js";
93
97
  export type * from "../models/props/DataGridProps.js";
94
98
  export type { GridAggregationPosition, GridAggregationCellMeta } from "../models/gridAggregation.js";
95
99
  export type { GridDataSourceApiBase, GridDataSourceApi, GridDataSourceBaseOptions, GridDataSourceFetchRowsParams } from "../hooks/features/dataSource/models.js";
@@ -126,4 +130,5 @@ export type { CellEditableConditionFn } from "../models/configuration/gridCellEd
126
130
  export * from "../hooks/features/pivoting/index.js";
127
131
  export { createSvgIcon } from "../material/icons/createSvgIcon.js";
128
132
  export { useGridPanelContext } from "../components/panel/GridPanelContext.js";
129
- export type { RowReorderDropPosition, RowReorderDragDirection } from "../models/api/gridRowApi.js";
133
+ export type { RowReorderDropPosition, RowReorderDragDirection } from "../models/api/gridRowApi.js";
134
+ export { useSyncExternalStore } from 'use-sync-external-store/shim';