@mui/x-data-grid 9.3.0 → 9.4.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 (34) hide show
  1. package/CHANGELOG.md +196 -0
  2. package/components/GridRow.js +9 -1
  3. package/components/GridRow.mjs +9 -1
  4. package/components/cell/GridActionsCellItem.js +1 -1
  5. package/components/cell/GridActionsCellItem.mjs +1 -1
  6. package/components/cell/GridSkeletonCell.d.mts +2 -1
  7. package/components/cell/GridSkeletonCell.d.ts +2 -1
  8. package/components/cell/GridSkeletonCell.js +8 -3
  9. package/components/cell/GridSkeletonCell.mjs +8 -3
  10. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.mts +17 -1
  11. package/hooks/core/strategyProcessing/gridStrategyProcessingApi.d.ts +17 -1
  12. package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +2 -1
  13. package/hooks/core/strategyProcessing/useGridStrategyProcessing.mjs +2 -1
  14. package/hooks/core/useGridVirtualizer.d.mts +10 -10
  15. package/hooks/core/useGridVirtualizer.d.ts +10 -10
  16. package/hooks/features/dataSource/models.d.mts +1 -1
  17. package/hooks/features/dataSource/models.d.ts +1 -1
  18. package/hooks/features/dataSource/useGridDataSourceBase.d.mts +2 -2
  19. package/hooks/features/dataSource/useGridDataSourceBase.d.ts +2 -2
  20. package/hooks/features/dataSource/useGridDataSourceBase.js +29 -17
  21. package/hooks/features/dataSource/useGridDataSourceBase.mjs +29 -17
  22. package/hooks/features/dataSource/utils.d.mts +1 -0
  23. package/hooks/features/dataSource/utils.d.ts +1 -0
  24. package/hooks/features/dataSource/utils.js +1 -0
  25. package/hooks/features/dataSource/utils.mjs +1 -0
  26. package/hooks/features/virtualization/gridVirtualizationSelectors.d.mts +1 -1
  27. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  28. package/index.js +1 -1
  29. package/index.mjs +1 -1
  30. package/models/gridDataSource.d.mts +6 -0
  31. package/models/gridDataSource.d.ts +6 -0
  32. package/models/gridRows.d.mts +0 -1
  33. package/models/gridRows.d.ts +0 -1
  34. package/package.json +3 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,201 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.4.0
4
+
5
+ <!-- generated comparing v9.3.0..master -->
6
+
7
+ _Jun 4, 2026_
8
+
9
+ We'd like to extend a big thank you to the 21 contributors who made this release possible. Here are some highlights ✨:
10
+
11
+ - 🎉 Scheduler is now in Beta shipping with Timeline vitualization and lazy loading
12
+ - 📆 Implement Event Timeline virtualization (#22339)
13
+ - 🫧 Introduce bubble charts (#22537)
14
+ - 🐞 Bugfixes
15
+ - 📚 Documentation improvements
16
+
17
+ Special thanks go out to these community members for their valuable contributions:
18
+ @imxv, @mixelburg, @mustafajw07
19
+
20
+ The following team members contributed to this release:
21
+ @aemartos, @alexfauquette, @arminmeh, @bernardobelchior, @cherniavskii, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @joserodolfofreitas, @LukasTy, @MBilalShafi, @michelengelen, @mj12albert, @noraleonte, @oliviertassinari, @rita-codes, @romgrk, @sai6855
22
+
23
+ ### Data Grid
24
+
25
+ #### `@mui/x-data-grid@9.4.0`
26
+
27
+ - [DataGrid] Fix `avg` aggregation when the average is zero (#22652) @mj12albert
28
+ - [DataGrid] Inherit icon `fontSize` from `baseIconButton` size (#22187) @imxv
29
+ - [DataGrid] Fix `noRowsOverlay` flicker between `dataSource` re-fetches (#22465) @LukasTy
30
+
31
+ #### `@mui/x-data-grid-pro@9.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
32
+
33
+ Same changes as in `@mui/x-data-grid@9.4.0`.
34
+
35
+ #### `@mui/x-data-grid-premium@9.4.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
36
+
37
+ > This release includes a version bump of the `@mui/x-internal-exceljs-fork` package to address the vulnerable dependencies.
38
+ > The following CVEs are fixed:
39
+ >
40
+ > - <https://github.com/advisories/GHSA-ph9p-34f9-6g65>
41
+ > - <https://github.com/isaacs/minimatch/security/advisories/GHSA-23c5-xmqv-rm74>
42
+ > - <https://github.com/advisories/GHSA-w5hq-g745-h8pq>
43
+ >
44
+ > To make this security update possible, we bumped the `node` version requirement from `>=14.0.0` to `>=14.17.0`.
45
+ > [Node.js 14.17.0](https://nodejs.org/en/blog/release/v14.17.0) was released in May 2021, so we consider it safe to bump the requirement without causing issues for our users.
46
+
47
+ Same changes as in `@mui/x-data-grid-pro@9.4.0`, plus:
48
+
49
+ - [DataGridPremium] Nested Lazy Loading (#21043) @MBilalShafi
50
+ - [DataGridPremium] Update exceljs fork (#22658) @cherniavskii
51
+
52
+ ### Date and Time Pickers
53
+
54
+ #### `@mui/x-date-pickers@9.4.0`
55
+
56
+ Internal changes.
57
+
58
+ #### `@mui/x-date-pickers-pro@9.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
59
+
60
+ Same changes as in `@mui/x-date-pickers@9.4.0`.
61
+
62
+ ### Charts
63
+
64
+ #### `@mui/x-charts@9.4.0`
65
+
66
+ - [charts] Add functionality to hide elements during chart export (#22525) @sai6855
67
+ - [charts] Add option to show marks only on the first/last values (#22645) @alexfauquette
68
+ - [charts] Add text customization section and demo for axis labels (#22597) @sai6855
69
+ - [charts] Allow axes to scale according to the visible series only (#22566) @alexfauquette
70
+ - [charts] Correctly handle different identifiers for each series (#22556) @sai6855
71
+ - [charts] Fix inverted Y axis zoom/pan on ordinal scales (#22654) @JCQuintas
72
+ - [charts] Introduce bubble charts (#22537) @alexfauquette
73
+ - [charts] Let scatter chart tooltip ignore hidden series (#22614) @alexfauquette
74
+ - [charts] Make `'sqrt'` size mapping the default (#22683) @alexfauquette
75
+ - [charts] Remove unused proptypes (#22618) @alexfauquette
76
+ - [charts] Support module augmentation for slots (#22519) @sai6855
77
+ - [charts] Support multiple marker size in `findClosestPoint` (#22622) @alexfauquette
78
+ - [charts] Upgrade bezier-easing to v3 and use it for line chart hit-detection (#22608) @sai6855
79
+ - [charts] Use `useLayoutEffect` with `ResizeObserver` (#22646) @JCQuintas
80
+
81
+ #### `@mui/x-charts-pro@9.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
82
+
83
+ Same changes as in `@mui/x-charts@9.4.0`, plus:
84
+
85
+ - [charts-pro] Auto-select range button matching current zoom (#22137) @JCQuintas
86
+ - [charts-pro] Support range values in `initialZoom` (#22563) @JCQuintas
87
+
88
+ #### `@mui/x-charts-premium@9.4.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
89
+
90
+ Same changes as in `@mui/x-charts-pro@9.4.0`, plus:
91
+
92
+ - [charts-premium] Support range-bar series in WebGL bar renderer (#22607) @JCQuintas
93
+ - [charts-premium] Fix `onAxisClick` for radial bar and lines (#22522) @alexfauquette
94
+
95
+ ### Tree View
96
+
97
+ #### `@mui/x-tree-view@9.4.0`
98
+
99
+ Internal changes.
100
+
101
+ #### `@mui/x-tree-view-pro@9.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
102
+
103
+ Same changes as in `@mui/x-tree-view@9.4.0`.
104
+
105
+ ### Scheduler
106
+
107
+ #### Breaking changes
108
+
109
+ The theme `styleOverrides` slots for the skeleton and the error container were
110
+ renamed and unified. The CSS utility class names (for example
111
+ `.MuiEventCalendar-eventSkeleton`) are **not** affected — only
112
+ `theme.components.*` overrides need updating.
113
+
114
+ **Event skeleton**
115
+
116
+ | Before | After |
117
+ | --------------------------------------- | ------------------------------ |
118
+ | `MuiEventCalendar` slot `EventSkeleton` | `MuiEventSkeleton` slot `Root` |
119
+ | `MuiEventTimeline` slot `EventSkeleton` | `MuiEventSkeleton` slot `Root` |
120
+
121
+ **Error container**
122
+
123
+ | Before | After |
124
+ | ------------------------------------------------------------- | --------------------------------------- |
125
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorContainer` | `MuiEventErrorContainer` slot `Root` |
126
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorAlert` | `MuiEventErrorContainer` slot `Alert` |
127
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorMessage` | `MuiEventErrorContainer` slot `Message` |
128
+
129
+ If you customized these through the theme, update the component name and slot
130
+ names accordingly:
131
+
132
+ ```diff
133
+ components: {
134
+ - MuiEventCalendar: {
135
+ + MuiEventSkeleton: {
136
+ styleOverrides: {
137
+ - EventSkeleton: { /* ... */ },
138
+ + Root: { /* ... */ },
139
+ },
140
+ },
141
+ },
142
+ }
143
+ ```
144
+
145
+ #### `@mui/x-scheduler@9.0.0-beta.0`
146
+
147
+ - [scheduler] Add a prop to control whether the resource of an event can be cleared (#22464) @rita-codes
148
+ - [scheduler] Add week number labels to agenda, day and week views (#22594) @mustafajw07
149
+ - [scheduler] Add `weekStartsOn` preference and update date functions to support custom week start (#22426) @mustafajw07
150
+ - [scheduler] Export premium version of the standalone views (#22621) @flaviendelangle
151
+ - [scheduler] Implement timeline virtualization (#22339) @romgrk
152
+ - [scheduler] Split scheduler overview (#22453) @joserodolfofreitas
153
+ - [scheduler] Unify `EventSkeleton` and `ErrorContainer` between `EventCalendar` and `EventTimeline` (#22676) @noraleonte
154
+
155
+ #### `@mui/x-scheduler-premium@9.0.0-beta.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
156
+
157
+ Same changes as in `@mui/x-scheduler@9.0.0-beta.0`.
158
+
159
+ ### Docs
160
+
161
+ - [docs] Add a performance docs page for charts (#22656) @alexfauquette
162
+ - [docs] Add real dataset for maps documentation (#22599) @alexfauquette
163
+ - [docs] Add spacing between selects on charts overview demo (#22589) @bernardobelchior
164
+ - [docs] Reorganize existing chat docs navigation (#22478) @hasdfa
165
+ - [docs] Switch to visionscarto's world atlas dataset (#22669) @cherniavskii
166
+ - [docs] Update TreeView `domstructure` docs and add demo (#22420) @mj12albert
167
+ - [docs] Fix indexation of Scheduler (#22567) @oliviertassinari
168
+ - [docs] Fix wide layout on event timeline lazy loading and Import title (#22604) @rita-codes
169
+ - [docs] Derive class name owners for shared charts classes (#22674) @JCQuintas
170
+
171
+ ### Core
172
+
173
+ - [code-infra] Drop unused and now-transitive deps from docs/package.json (#22549) @LukasTy
174
+ - [code-infra] Refresh CI Node pins to 22.22.3 (#22598) @LukasTy
175
+ - [code-infra] Skip empty product sections in changelog (#22541) @rita-codes
176
+ - [code-infra] Stabilize DataGridScrollRestoration visual regression test (#22553) @Janpot
177
+ - [internal] Add license to the `x-data-grid-generator` (#22240) @arminmeh
178
+ - [internal] Express default value for resource_class (#22569) @oliviertassinari
179
+ - [internal] Fix use of ellipsis (#21852) @oliviertassinari
180
+ - [internal] `useLayoutEffect` with `ResizeObserver` (#22428) @romgrk
181
+
182
+ ### Miscellaneous
183
+
184
+ - [chat-headless] Add built-in chat adapters (#22479) @hasdfa
185
+ - [chat-headless] Harden runtime model and message errors (#22480) @hasdfa
186
+ - [core] Prepare for TypeScript 6 bump (#22551) @LukasTy
187
+ - [core] Use CircleCI Gen2 resource classes (#22610) @LukasTy
188
+ - [infra] Fix broken tag retrieval on `master` during release (#22174) @michelengelen
189
+ - [infra] Group Base UI renovate updates (#22590) @LukasTy
190
+ - [pnpm] Add security settings to pnpm-workspace.yaml (#22611) @Janpot
191
+ - [release] Fix release PR scripts (#22680) @JCQuintas
192
+ - [test] Add a Tree View regression test for lazy loading with getChildrenCount returning -1 (#22605) @mixelburg
193
+ - [test] Disable LCD subpixel antialiasing in regression screenshots (#22602) @Janpot
194
+ - [test] Fix flaky Data Grid Pro data source tree data tests (#22659) @LukasTy
195
+ - [test] Remove stale form-submit TODO from e2e suite (#22564) @LukasTy
196
+ - [x-license] Exclude test keys from the published npm package (#22647) @aemartos
197
+ - [test] Fix flaky WebGL benchmark by polling for canvas content (#22535) @JCQuintas
198
+
3
199
  ## 9.3.0
4
200
 
5
201
  _May 21, 2026_
@@ -16,6 +16,7 @@ var _useForkRef = _interopRequireDefault(require("@mui/utils/useForkRef"));
16
16
  var _fastMemo = require("@mui/x-internals/fastMemo");
17
17
  var _forwardRef = require("@mui/x-internals/forwardRef");
18
18
  var _isObjectEmpty = require("@mui/x-internals/isObjectEmpty");
19
+ var _cssVariables = require("../constants/cssVariables");
19
20
  var _gridEditRowModel = require("../models/gridEditRowModel");
20
21
  var _gridClasses = require("../constants/gridClasses");
21
22
  var _composeGridClasses = require("../utils/composeGridClasses");
@@ -236,7 +237,14 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
236
237
  width: width,
237
238
  height: rowHeight,
238
239
  field: column.field,
239
- align: column.align
240
+ align: column.align,
241
+ skeletonProps: {
242
+ style: {
243
+ marginLeft: indexRelativeToAllColumns === 0 && rowNode.depth > 0 ?
244
+ // TODO: Make the factor configurable
245
+ _cssVariables.vars.spacing(rowNode.depth * 2) : '0px'
246
+ }
247
+ }
240
248
  }, column.field);
241
249
  }
242
250
 
@@ -10,6 +10,7 @@ import useForkRef from '@mui/utils/useForkRef';
10
10
  import { fastMemo } from '@mui/x-internals/fastMemo';
11
11
  import { forwardRef } from '@mui/x-internals/forwardRef';
12
12
  import { isObjectEmpty } from '@mui/x-internals/isObjectEmpty';
13
+ import { vars } from "../constants/cssVariables.mjs";
13
14
  import { GridEditModes, GridCellModes } from "../models/gridEditRowModel.mjs";
14
15
  import { gridClasses } from "../constants/gridClasses.mjs";
15
16
  import { composeGridClasses } from "../utils/composeGridClasses.mjs";
@@ -229,7 +230,14 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
229
230
  width: width,
230
231
  height: rowHeight,
231
232
  field: column.field,
232
- align: column.align
233
+ align: column.align,
234
+ skeletonProps: {
235
+ style: {
236
+ marginLeft: indexRelativeToAllColumns === 0 && rowNode.depth > 0 ?
237
+ // TODO: Make the factor configurable
238
+ vars.spacing(rowNode.depth * 2) : '0px'
239
+ }
240
+ }
233
241
  }, column.field);
234
242
  }
235
243
 
@@ -36,7 +36,7 @@ const GridActionsCellItem = exports.GridActionsCellItem = (0, _forwardRef.forwar
36
36
  }, rootProps.slotProps?.baseIconButton, {
37
37
  ref: ref,
38
38
  children: /*#__PURE__*/React.cloneElement(icon, {
39
- fontSize: 'small'
39
+ fontSize: 'inherit'
40
40
  })
41
41
  }));
42
42
  }
@@ -29,7 +29,7 @@ const GridActionsCellItem = forwardRef((props, ref) => {
29
29
  }, rootProps.slotProps?.baseIconButton, {
30
30
  ref: ref,
31
31
  children: /*#__PURE__*/React.cloneElement(icon, {
32
- fontSize: 'small'
32
+ fontSize: 'inherit'
33
33
  })
34
34
  }));
35
35
  }
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { GridColType } from "../../models/index.mjs";
2
+ import type { GridColType, GridSlotProps } from "../../models/index.mjs";
3
3
  export interface GridSkeletonCellProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  type?: GridColType;
5
5
  width?: number | string;
@@ -11,6 +11,7 @@ export interface GridSkeletonCellProps extends React.HTMLAttributes<HTMLDivEleme
11
11
  * @default false
12
12
  */
13
13
  empty?: boolean;
14
+ skeletonProps?: GridSlotProps['baseSkeleton'];
14
15
  }
15
16
  declare function GridSkeletonCell(props: GridSkeletonCellProps): import("react/jsx-runtime").JSX.Element;
16
17
  declare namespace GridSkeletonCell {
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react';
2
- import type { GridColType } from "../../models/index.js";
2
+ import type { GridColType, GridSlotProps } from "../../models/index.js";
3
3
  export interface GridSkeletonCellProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  type?: GridColType;
5
5
  width?: number | string;
@@ -11,6 +11,7 @@ export interface GridSkeletonCellProps extends React.HTMLAttributes<HTMLDivEleme
11
11
  * @default false
12
12
  */
13
13
  empty?: boolean;
14
+ skeletonProps?: GridSlotProps['baseSkeleton'];
14
15
  }
15
16
  declare function GridSkeletonCell(props: GridSkeletonCellProps): import("react/jsx-runtime").JSX.Element;
16
17
  declare namespace GridSkeletonCell {
@@ -18,7 +18,7 @@ var _utils = require("../../utils/utils");
18
18
  var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
19
19
  var _gridClasses = require("../../constants/gridClasses");
20
20
  var _jsxRuntime = require("react/jsx-runtime");
21
- const _excluded = ["field", "type", "align", "width", "height", "empty", "style", "className"];
21
+ const _excluded = ["field", "type", "align", "width", "height", "empty", "style", "className", "skeletonProps"];
22
22
  const CIRCULAR_CONTENT_SIZE = '1.3em';
23
23
  const CONTENT_HEIGHT = '1.2em';
24
24
  const DEFAULT_CONTENT_WIDTH_RANGE = [40, 80];
@@ -50,7 +50,8 @@ function GridSkeletonCell(props) {
50
50
  height,
51
51
  empty = false,
52
52
  style,
53
- className
53
+ className,
54
+ skeletonProps: skeletonPropsOverride
54
55
  } = props,
55
56
  other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
56
57
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
@@ -62,7 +63,7 @@ function GridSkeletonCell(props) {
62
63
  const classes = useUtilityClasses(ownerState);
63
64
 
64
65
  // Memo prevents the non-circular skeleton widths changing to random widths on every render
65
- const skeletonProps = React.useMemo(() => {
66
+ const baseSkeletonProps = React.useMemo(() => {
66
67
  const isCircularContent = type === 'boolean' || type === 'actions';
67
68
  if (isCircularContent) {
68
69
  return {
@@ -81,6 +82,10 @@ function GridSkeletonCell(props) {
81
82
  height: CONTENT_HEIGHT
82
83
  };
83
84
  }, [type]);
85
+
86
+ // Merge caller overrides outside the memo so an inline `skeletonProps` object
87
+ // doesn't bust the memo and re-roll the random width on every render
88
+ const skeletonProps = skeletonPropsOverride && Object.keys(skeletonPropsOverride).length > 0 ? (0, _extends2.default)({}, baseSkeletonProps, skeletonPropsOverride) : baseSkeletonProps;
84
89
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", (0, _extends2.default)({
85
90
  "data-field": field,
86
91
  className: (0, _clsx.default)(classes.root, className),
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["field", "type", "align", "width", "height", "empty", "style", "className"];
3
+ const _excluded = ["field", "type", "align", "width", "height", "empty", "style", "className", "skeletonProps"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import clsx from 'clsx';
@@ -42,7 +42,8 @@ function GridSkeletonCell(props) {
42
42
  height,
43
43
  empty = false,
44
44
  style,
45
- className
45
+ className,
46
+ skeletonProps: skeletonPropsOverride
46
47
  } = props,
47
48
  other = _objectWithoutPropertiesLoose(props, _excluded);
48
49
  const rootProps = useGridRootProps();
@@ -54,7 +55,7 @@ function GridSkeletonCell(props) {
54
55
  const classes = useUtilityClasses(ownerState);
55
56
 
56
57
  // Memo prevents the non-circular skeleton widths changing to random widths on every render
57
- const skeletonProps = React.useMemo(() => {
58
+ const baseSkeletonProps = React.useMemo(() => {
58
59
  const isCircularContent = type === 'boolean' || type === 'actions';
59
60
  if (isCircularContent) {
60
61
  return {
@@ -73,6 +74,10 @@ function GridSkeletonCell(props) {
73
74
  height: CONTENT_HEIGHT
74
75
  };
75
76
  }, [type]);
77
+
78
+ // Merge caller overrides outside the memo so an inline `skeletonProps` object
79
+ // doesn't bust the memo and re-roll the random width on every render
80
+ const skeletonProps = skeletonPropsOverride && Object.keys(skeletonPropsOverride).length > 0 ? _extends({}, baseSkeletonProps, skeletonPropsOverride) : baseSkeletonProps;
76
81
  return /*#__PURE__*/_jsx("div", _extends({
77
82
  "data-field": field,
78
83
  className: clsx(classes.root, className),
@@ -2,6 +2,7 @@ import type { GridRowTreeCreationParams, GridRowTreeCreationValue, GridRowsState
2
2
  import type { GridFilteringMethodParams, GridFilteringMethodValue, GridFilterState, GridVisibleRowsLookupState } from "../../features/filter/gridFilterState.mjs";
3
3
  import type { GridSortingMethodParams, GridSortingMethodValue } from "../../features/sorting/gridSortingState.mjs";
4
4
  import type { GridGetRowsParams, GridGetRowsResponse, GridGetRowsOptions } from "../../../models/gridDataSource.mjs";
5
+ import type { GridRowId } from "../../../models/gridRows.mjs";
5
6
  export type GridStrategyProcessorName = keyof GridStrategyProcessingLookup;
6
7
  export declare enum GridStrategyGroup {
7
8
  DataSource = "dataSource",
@@ -9,7 +10,7 @@ export declare enum GridStrategyGroup {
9
10
  }
10
11
  export type GridStrategyGroupValue = `${GridStrategyGroup}`;
11
12
  export interface GridStrategyProcessingLookup {
12
- dataSourceRowsUpdate: {
13
+ dataSourceRootRowsUpdate: {
13
14
  group: GridStrategyGroup.DataSource;
14
15
  params: {
15
16
  response: GridGetRowsResponse;
@@ -22,6 +23,21 @@ export interface GridStrategyProcessingLookup {
22
23
  };
23
24
  value: void;
24
25
  };
26
+ dataSourceNestedRowsUpdate: {
27
+ group: GridStrategyGroup.DataSource;
28
+ params: {
29
+ parentId: GridRowId;
30
+ path: string[];
31
+ response: GridGetRowsResponse;
32
+ fetchParams: GridGetRowsParams;
33
+ } | {
34
+ parentId: GridRowId;
35
+ path: string[];
36
+ error: Error;
37
+ fetchParams: GridGetRowsParams;
38
+ };
39
+ value: void;
40
+ };
25
41
  rowTreeCreation: {
26
42
  group: GridStrategyGroup.RowTree;
27
43
  params: GridRowTreeCreationParams;
@@ -2,6 +2,7 @@ import type { GridRowTreeCreationParams, GridRowTreeCreationValue, GridRowsState
2
2
  import type { GridFilteringMethodParams, GridFilteringMethodValue, GridFilterState, GridVisibleRowsLookupState } from "../../features/filter/gridFilterState.js";
3
3
  import type { GridSortingMethodParams, GridSortingMethodValue } from "../../features/sorting/gridSortingState.js";
4
4
  import type { GridGetRowsParams, GridGetRowsResponse, GridGetRowsOptions } from "../../../models/gridDataSource.js";
5
+ import type { GridRowId } from "../../../models/gridRows.js";
5
6
  export type GridStrategyProcessorName = keyof GridStrategyProcessingLookup;
6
7
  export declare enum GridStrategyGroup {
7
8
  DataSource = "dataSource",
@@ -9,7 +10,7 @@ export declare enum GridStrategyGroup {
9
10
  }
10
11
  export type GridStrategyGroupValue = `${GridStrategyGroup}`;
11
12
  export interface GridStrategyProcessingLookup {
12
- dataSourceRowsUpdate: {
13
+ dataSourceRootRowsUpdate: {
13
14
  group: GridStrategyGroup.DataSource;
14
15
  params: {
15
16
  response: GridGetRowsResponse;
@@ -22,6 +23,21 @@ export interface GridStrategyProcessingLookup {
22
23
  };
23
24
  value: void;
24
25
  };
26
+ dataSourceNestedRowsUpdate: {
27
+ group: GridStrategyGroup.DataSource;
28
+ params: {
29
+ parentId: GridRowId;
30
+ path: string[];
31
+ response: GridGetRowsResponse;
32
+ fetchParams: GridGetRowsParams;
33
+ } | {
34
+ parentId: GridRowId;
35
+ path: string[];
36
+ error: Error;
37
+ fetchParams: GridGetRowsParams;
38
+ };
39
+ value: void;
40
+ };
25
41
  rowTreeCreation: {
26
42
  group: GridStrategyGroup.RowTree;
27
43
  params: GridRowTreeCreationParams;
@@ -15,7 +15,8 @@ var _gridStrategyProcessingApi = require("./gridStrategyProcessingApi");
15
15
  var _useGridApiMethod = require("../../utils/useGridApiMethod");
16
16
  const GRID_DEFAULT_STRATEGY = exports.GRID_DEFAULT_STRATEGY = 'none';
17
17
  const GRID_STRATEGIES_PROCESSORS = {
18
- dataSourceRowsUpdate: _gridStrategyProcessingApi.GridStrategyGroup.DataSource,
18
+ dataSourceRootRowsUpdate: _gridStrategyProcessingApi.GridStrategyGroup.DataSource,
19
+ dataSourceNestedRowsUpdate: _gridStrategyProcessingApi.GridStrategyGroup.DataSource,
19
20
  rowTreeCreation: _gridStrategyProcessingApi.GridStrategyGroup.RowTree,
20
21
  filtering: _gridStrategyProcessingApi.GridStrategyGroup.RowTree,
21
22
  sorting: _gridStrategyProcessingApi.GridStrategyGroup.RowTree,
@@ -8,7 +8,8 @@ import { GridStrategyGroup } from "./gridStrategyProcessingApi.mjs";
8
8
  import { useGridApiMethod } from "../../utils/useGridApiMethod.mjs";
9
9
  export const GRID_DEFAULT_STRATEGY = 'none';
10
10
  const GRID_STRATEGIES_PROCESSORS = {
11
- dataSourceRowsUpdate: GridStrategyGroup.DataSource,
11
+ dataSourceRootRowsUpdate: GridStrategyGroup.DataSource,
12
+ dataSourceNestedRowsUpdate: GridStrategyGroup.DataSource,
12
13
  rowTreeCreation: GridStrategyGroup.RowTree,
13
14
  filtering: GridStrategyGroup.RowTree,
14
15
  sorting: GridStrategyGroup.RowTree,
@@ -9,28 +9,28 @@ export declare function useGridVirtualizer(): {
9
9
  updateDimensions: (firstUpdate?: boolean) => void;
10
10
  debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
11
11
  rowsMeta: {
12
- getRowHeight: (rowId: import("@mui/x-virtualizer/models").RowId) => any;
12
+ getRowHeight: (rowId: import("@mui/x-virtualizer").RowId) => any;
13
13
  setLastMeasuredRowIndex: (index: number) => void;
14
- storeRowHeightMeasurement: (id: import("@mui/x-virtualizer/models").RowId, height: number) => void;
14
+ storeRowHeightMeasurement: (id: import("@mui/x-virtualizer").RowId, height: number) => void;
15
15
  hydrateRowsMeta: () => void;
16
- observeRowHeight: (element: Element, rowId: import("@mui/x-virtualizer/models").RowId) => () => void | undefined;
17
- rowHasAutoHeight: (id: import("@mui/x-virtualizer/models").RowId) => any;
18
- getRowHeightEntry: (rowId: import("@mui/x-virtualizer/models").RowId) => any;
16
+ observeRowHeight: (element: Element, rowId: import("@mui/x-virtualizer").RowId) => () => void | undefined;
17
+ rowHasAutoHeight: (id: import("@mui/x-virtualizer").RowId) => any;
18
+ getRowHeightEntry: (rowId: import("@mui/x-virtualizer").RowId) => any;
19
19
  getLastMeasuredRowIndex: () => number;
20
20
  resetRowHeights: () => void;
21
21
  };
22
22
  } & {
23
- getCellColSpanInfo: (rowId: import("@mui/x-virtualizer/models").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer/models").CellColSpanInfo;
24
- calculateColSpan: (rowId: import("@mui/x-virtualizer/models").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer/models").ColumnWithWidth[]) => void;
25
- getHiddenCellsOrigin: () => Record<import("@mui/x-virtualizer/models").RowId, Record<number, number>>;
23
+ getCellColSpanInfo: (rowId: import("@mui/x-virtualizer").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer").CellColSpanInfo;
24
+ calculateColSpan: (rowId: import("@mui/x-virtualizer").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer").ColumnWithWidth[]) => void;
25
+ getHiddenCellsOrigin: () => Record<import("@mui/x-virtualizer").RowId, Record<number, number>>;
26
26
  getters: any;
27
27
  setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
28
28
  forceUpdateRenderContext: () => void;
29
29
  scheduleUpdateRenderContext: () => void;
30
30
  } & {
31
31
  resetColSpan: () => void;
32
- getCellColSpanInfo: (rowId: import("@mui/x-virtualizer/models").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer/models").CellColSpanInfo | undefined;
33
- calculateColSpan: (rowId: import("@mui/x-virtualizer/models").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer/models").ColumnWithWidth[]) => void;
32
+ getCellColSpanInfo: (rowId: import("@mui/x-virtualizer").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer").CellColSpanInfo | undefined;
33
+ calculateColSpan: (rowId: import("@mui/x-virtualizer").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer").ColumnWithWidth[]) => void;
34
34
  } & {
35
35
  getHiddenCellsOrigin: () => Record<number, Record<number, number>>;
36
36
  } & {
@@ -9,28 +9,28 @@ export declare function useGridVirtualizer(): {
9
9
  updateDimensions: (firstUpdate?: boolean) => void;
10
10
  debouncedUpdateDimensions: (((firstUpdate?: boolean) => void) & import("@mui/x-internals/throttle").Cancelable) | undefined;
11
11
  rowsMeta: {
12
- getRowHeight: (rowId: import("@mui/x-virtualizer/models").RowId) => any;
12
+ getRowHeight: (rowId: import("@mui/x-virtualizer").RowId) => any;
13
13
  setLastMeasuredRowIndex: (index: number) => void;
14
- storeRowHeightMeasurement: (id: import("@mui/x-virtualizer/models").RowId, height: number) => void;
14
+ storeRowHeightMeasurement: (id: import("@mui/x-virtualizer").RowId, height: number) => void;
15
15
  hydrateRowsMeta: () => void;
16
- observeRowHeight: (element: Element, rowId: import("@mui/x-virtualizer/models").RowId) => () => void | undefined;
17
- rowHasAutoHeight: (id: import("@mui/x-virtualizer/models").RowId) => any;
18
- getRowHeightEntry: (rowId: import("@mui/x-virtualizer/models").RowId) => any;
16
+ observeRowHeight: (element: Element, rowId: import("@mui/x-virtualizer").RowId) => () => void | undefined;
17
+ rowHasAutoHeight: (id: import("@mui/x-virtualizer").RowId) => any;
18
+ getRowHeightEntry: (rowId: import("@mui/x-virtualizer").RowId) => any;
19
19
  getLastMeasuredRowIndex: () => number;
20
20
  resetRowHeights: () => void;
21
21
  };
22
22
  } & {
23
- getCellColSpanInfo: (rowId: import("@mui/x-virtualizer/models").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer/models").CellColSpanInfo;
24
- calculateColSpan: (rowId: import("@mui/x-virtualizer/models").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer/models").ColumnWithWidth[]) => void;
25
- getHiddenCellsOrigin: () => Record<import("@mui/x-virtualizer/models").RowId, Record<number, number>>;
23
+ getCellColSpanInfo: (rowId: import("@mui/x-virtualizer").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer").CellColSpanInfo;
24
+ calculateColSpan: (rowId: import("@mui/x-virtualizer").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer").ColumnWithWidth[]) => void;
25
+ getHiddenCellsOrigin: () => Record<import("@mui/x-virtualizer").RowId, Record<number, number>>;
26
26
  getters: any;
27
27
  setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<any, React.ReactNode>>>>;
28
28
  forceUpdateRenderContext: () => void;
29
29
  scheduleUpdateRenderContext: () => void;
30
30
  } & {
31
31
  resetColSpan: () => void;
32
- getCellColSpanInfo: (rowId: import("@mui/x-virtualizer/models").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer/models").CellColSpanInfo | undefined;
33
- calculateColSpan: (rowId: import("@mui/x-virtualizer/models").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer/models").ColumnWithWidth[]) => void;
32
+ getCellColSpanInfo: (rowId: import("@mui/x-virtualizer").RowId, columnIndex: import("@mui/x-internals/types").integer) => import("@mui/x-virtualizer").CellColSpanInfo | undefined;
33
+ calculateColSpan: (rowId: import("@mui/x-virtualizer").RowId, minFirstColumn: import("@mui/x-internals/types").integer, maxLastColumn: import("@mui/x-internals/types").integer, columns: import("@mui/x-virtualizer").ColumnWithWidth[]) => void;
34
34
  } & {
35
35
  getHiddenCellsOrigin: () => Record<number, Record<number, number>>;
36
36
  } & {
@@ -41,7 +41,7 @@ export interface GridDataSourceApiBase {
41
41
  }
42
42
  export interface GridDataSourceBaseOptions {
43
43
  cacheOptions?: GridDataSourceCacheDefaultConfig;
44
- fetchRowChildren?: (parents: GridRowId[], options?: GridDataSourceFetchRowChildrenOptions) => void;
44
+ fetchRowChildren?: (parents: GridRowId[], fetchParams: GridGetRowsParams[], showChildrenLoading?: boolean) => void;
45
45
  clearDataSourceState?: () => void;
46
46
  handleEditRow?: (params: GridUpdateRowParams, updatedRow: GridRowModel) => void;
47
47
  }
@@ -41,7 +41,7 @@ export interface GridDataSourceApiBase {
41
41
  }
42
42
  export interface GridDataSourceBaseOptions {
43
43
  cacheOptions?: GridDataSourceCacheDefaultConfig;
44
- fetchRowChildren?: (parents: GridRowId[], options?: GridDataSourceFetchRowChildrenOptions) => void;
44
+ fetchRowChildren?: (parents: GridRowId[], fetchParams: GridGetRowsParams[], showChildrenLoading?: boolean) => void;
45
45
  clearDataSourceState?: () => void;
46
46
  handleEditRow?: (params: GridUpdateRowParams, updatedRow: GridRowModel) => void;
47
47
  }
@@ -14,8 +14,8 @@ export declare const useGridDataSourceBase: <Api extends GridPrivateApiCommunity
14
14
  debouncedFetchRows: ((parentId?: GridRowId, params?: import("./models.mjs").GridDataSourceFetchRowsParams<import("@mui/x-data-grid").GridGetRowsParams>) => Promise<void>) & import("@mui/utils/debounce").Cancelable;
15
15
  strategyProcessor: {
16
16
  strategyName: DataSourceRowsUpdateStrategy;
17
- group: "dataSourceRowsUpdate";
18
- processor: GridStrategyProcessor<"dataSourceRowsUpdate">;
17
+ group: "dataSourceRootRowsUpdate";
18
+ processor: GridStrategyProcessor<"dataSourceRootRowsUpdate">;
19
19
  };
20
20
  setStrategyAvailability: () => void;
21
21
  startPolling: () => void;
@@ -14,8 +14,8 @@ export declare const useGridDataSourceBase: <Api extends GridPrivateApiCommunity
14
14
  debouncedFetchRows: ((parentId?: GridRowId, params?: import("./models.js").GridDataSourceFetchRowsParams<import("@mui/x-data-grid").GridGetRowsParams>) => Promise<void>) & import("@mui/utils/debounce").Cancelable;
15
15
  strategyProcessor: {
16
16
  strategyName: DataSourceRowsUpdateStrategy;
17
- group: "dataSourceRowsUpdate";
18
- processor: GridStrategyProcessor<"dataSourceRowsUpdate">;
17
+ group: "dataSourceRootRowsUpdate";
18
+ processor: GridStrategyProcessor<"dataSourceRootRowsUpdate">;
19
19
  };
20
20
  setStrategyAvailability: () => void;
21
21
  startPolling: () => void;
@@ -25,7 +25,7 @@ var _gridDataSourceSelector = require("./gridDataSourceSelector");
25
25
  var _utils2 = require("./utils");
26
26
  var _cache = require("./cache");
27
27
  var _gridDataSourceError = require("./gridDataSourceError");
28
- const _excluded = ["skipCache", "keepChildrenExpanded"];
28
+ const _excluded = ["skipCache", "keepChildrenExpanded", "showChildrenLoading"];
29
29
  const noopCache = {
30
30
  clear: () => {},
31
31
  get: () => undefined,
@@ -64,22 +64,26 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
64
64
  if (!getRows) {
65
65
  return;
66
66
  }
67
- if (parentId && parentId !== _gridRowsUtils.GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
68
- options.fetchRowChildren?.([parentId]);
69
- return;
70
- }
71
- options.clearDataSourceState?.();
72
67
  const _ref = params || {},
73
68
  {
74
69
  skipCache,
75
- keepChildrenExpanded
70
+ keepChildrenExpanded,
71
+ showChildrenLoading
76
72
  } = _ref,
77
73
  getRowsParams = (0, _objectWithoutPropertiesLoose2.default)(_ref, _excluded);
78
74
  const fetchParams = (0, _extends2.default)({}, (0, _gridDataSourceSelector.gridGetRowsParamsSelector)(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}), getRowsParams);
75
+ if (parentId && parentId !== _gridRowsUtils.GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
76
+ options.fetchRowChildren?.([parentId], [fetchParams], showChildrenLoading);
77
+ return;
78
+ }
79
+ options.clearDataSourceState?.();
79
80
  const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
80
81
  const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
81
82
  if (!skipCache && responses.every(response => response !== undefined)) {
82
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
83
+ // Bump the request id so any cache-miss request still in flight is treated as
84
+ // stale and won't override the cached data we're about to apply.
85
+ lastRequestId.current += 1;
86
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
83
87
  response: _utils2.CacheChunkManager.mergeResponses(responses),
84
88
  fetchParams,
85
89
  options: {
@@ -87,6 +91,9 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
87
91
  keepChildrenExpanded
88
92
  }
89
93
  });
94
+ if (standardRowsUpdateStrategyActive) {
95
+ apiRef.current.setLoading(false);
96
+ }
90
97
  return;
91
98
  }
92
99
 
@@ -101,7 +108,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
101
108
  const cacheResponses = cacheChunkManager.splitResponse(fetchParams, getRowsResponse);
102
109
  cacheResponses.forEach((response, key) => cache.set(key, response));
103
110
  if (lastRequestId.current === requestId) {
104
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
111
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
105
112
  response: getRowsResponse,
106
113
  fetchParams,
107
114
  options: {
@@ -112,7 +119,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
112
119
  }
113
120
  } catch (originalError) {
114
121
  if (lastRequestId.current === requestId) {
115
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
122
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
116
123
  error: originalError,
117
124
  fetchParams,
118
125
  options: {
@@ -159,9 +166,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
159
166
  return acc;
160
167
  }, []);
161
168
  if (expandedGroupIds.length > 0) {
162
- fetchRowChildrenOption(expandedGroupIds, {
163
- showChildrenLoading: false
164
- });
169
+ fetchRowChildrenOption(expandedGroupIds, [], false);
165
170
  }
166
171
  };
167
172
  const fetchParams = (0, _extends2.default)({}, (0, _gridDataSourceSelector.gridGetRowsParamsSelector)(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
@@ -179,7 +184,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
179
184
  }
180
185
  const cacheResponses = cacheChunkManager.splitResponse(fetchParams, response);
181
186
  cacheResponses.forEach((cacheResponse, key) => cache.set(key, cacheResponse));
182
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
187
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
183
188
  response,
184
189
  fetchParams,
185
190
  options: {}
@@ -260,10 +265,17 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
260
265
  };
261
266
  const debouncedFetchRows = React.useMemo(() => (0, _debounce.default)(fetchRows, 0), [fetchRows]);
262
267
  const handleFetchRowsOnParamsChange = React.useCallback(() => {
268
+ // Clear the rows first and immediately mark the grid as loading so the overlay
269
+ // selector never observes the intermediate `rows=[] && loading=false` state that
270
+ // would otherwise pick `noRowsOverlay`. Order matters: `setRows([])` rebuilds
271
+ // `state.rows` from `props.loading`, so the `setLoading(true)` call must come after
272
+ // it to survive the rebuild. This handler is only wired up when a standard strategy
273
+ // is active via the `runIf` guards on the returned `events` object.
263
274
  apiRef.current.setRows([]);
275
+ apiRef.current.setLoading(true);
264
276
  stopPolling();
265
277
  debouncedFetchRows();
266
- }, [stopPolling, debouncedFetchRows, apiRef]);
278
+ }, [apiRef, stopPolling, debouncedFetchRows]);
267
279
  const isFirstRender = React.useRef(true);
268
280
  React.useEffect(() => {
269
281
  if (isFirstRender.current) {
@@ -290,7 +302,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
290
302
  React.useEffect(() => {
291
303
  // Return early if the proper strategy isn't set yet
292
304
  // Context: https://github.com/mui/mui-x/issues/19650
293
- if (currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.Default && currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.LazyLoading && currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.GroupedData) {
305
+ if (currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.Default && currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.LazyLoading && currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.GroupedData && currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.LazyLoadedGroupedData) {
294
306
  return undefined;
295
307
  }
296
308
  if (props.dataSource) {
@@ -311,7 +323,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
311
323
  debouncedFetchRows,
312
324
  strategyProcessor: {
313
325
  strategyName: _utils2.DataSourceRowsUpdateStrategy.Default,
314
- group: 'dataSourceRowsUpdate',
326
+ group: 'dataSourceRootRowsUpdate',
315
327
  processor: handleDataUpdate
316
328
  },
317
329
  setStrategyAvailability,
@@ -2,7 +2,7 @@
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 = ["skipCache", "keepChildrenExpanded"];
5
+ const _excluded = ["skipCache", "keepChildrenExpanded", "showChildrenLoading"];
6
6
  import * as React from 'react';
7
7
  import useLazyRef from '@mui/utils/useLazyRef';
8
8
  import useEventCallback from '@mui/utils/useEventCallback';
@@ -57,22 +57,26 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
57
57
  if (!getRows) {
58
58
  return;
59
59
  }
60
- if (parentId && parentId !== GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
61
- options.fetchRowChildren?.([parentId]);
62
- return;
63
- }
64
- options.clearDataSourceState?.();
65
60
  const _ref = params || {},
66
61
  {
67
62
  skipCache,
68
- keepChildrenExpanded
63
+ keepChildrenExpanded,
64
+ showChildrenLoading
69
65
  } = _ref,
70
66
  getRowsParams = _objectWithoutPropertiesLoose(_ref, _excluded);
71
67
  const fetchParams = _extends({}, gridGetRowsParamsSelector(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}), getRowsParams);
68
+ if (parentId && parentId !== GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
69
+ options.fetchRowChildren?.([parentId], [fetchParams], showChildrenLoading);
70
+ return;
71
+ }
72
+ options.clearDataSourceState?.();
72
73
  const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
73
74
  const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
74
75
  if (!skipCache && responses.every(response => response !== undefined)) {
75
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
76
+ // Bump the request id so any cache-miss request still in flight is treated as
77
+ // stale and won't override the cached data we're about to apply.
78
+ lastRequestId.current += 1;
79
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
76
80
  response: CacheChunkManager.mergeResponses(responses),
77
81
  fetchParams,
78
82
  options: {
@@ -80,6 +84,9 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
80
84
  keepChildrenExpanded
81
85
  }
82
86
  });
87
+ if (standardRowsUpdateStrategyActive) {
88
+ apiRef.current.setLoading(false);
89
+ }
83
90
  return;
84
91
  }
85
92
 
@@ -94,7 +101,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
94
101
  const cacheResponses = cacheChunkManager.splitResponse(fetchParams, getRowsResponse);
95
102
  cacheResponses.forEach((response, key) => cache.set(key, response));
96
103
  if (lastRequestId.current === requestId) {
97
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
104
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
98
105
  response: getRowsResponse,
99
106
  fetchParams,
100
107
  options: {
@@ -105,7 +112,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
105
112
  }
106
113
  } catch (originalError) {
107
114
  if (lastRequestId.current === requestId) {
108
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
115
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
109
116
  error: originalError,
110
117
  fetchParams,
111
118
  options: {
@@ -152,9 +159,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
152
159
  return acc;
153
160
  }, []);
154
161
  if (expandedGroupIds.length > 0) {
155
- fetchRowChildrenOption(expandedGroupIds, {
156
- showChildrenLoading: false
157
- });
162
+ fetchRowChildrenOption(expandedGroupIds, [], false);
158
163
  }
159
164
  };
160
165
  const fetchParams = _extends({}, gridGetRowsParamsSelector(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
@@ -172,7 +177,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
172
177
  }
173
178
  const cacheResponses = cacheChunkManager.splitResponse(fetchParams, response);
174
179
  cacheResponses.forEach((cacheResponse, key) => cache.set(key, cacheResponse));
175
- apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
180
+ apiRef.current.applyStrategyProcessor('dataSourceRootRowsUpdate', {
176
181
  response,
177
182
  fetchParams,
178
183
  options: {}
@@ -253,10 +258,17 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
253
258
  };
254
259
  const debouncedFetchRows = React.useMemo(() => debounce(fetchRows, 0), [fetchRows]);
255
260
  const handleFetchRowsOnParamsChange = React.useCallback(() => {
261
+ // Clear the rows first and immediately mark the grid as loading so the overlay
262
+ // selector never observes the intermediate `rows=[] && loading=false` state that
263
+ // would otherwise pick `noRowsOverlay`. Order matters: `setRows([])` rebuilds
264
+ // `state.rows` from `props.loading`, so the `setLoading(true)` call must come after
265
+ // it to survive the rebuild. This handler is only wired up when a standard strategy
266
+ // is active via the `runIf` guards on the returned `events` object.
256
267
  apiRef.current.setRows([]);
268
+ apiRef.current.setLoading(true);
257
269
  stopPolling();
258
270
  debouncedFetchRows();
259
- }, [stopPolling, debouncedFetchRows, apiRef]);
271
+ }, [apiRef, stopPolling, debouncedFetchRows]);
260
272
  const isFirstRender = React.useRef(true);
261
273
  React.useEffect(() => {
262
274
  if (isFirstRender.current) {
@@ -283,7 +295,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
283
295
  React.useEffect(() => {
284
296
  // Return early if the proper strategy isn't set yet
285
297
  // Context: https://github.com/mui/mui-x/issues/19650
286
- if (currentStrategy !== DataSourceRowsUpdateStrategy.Default && currentStrategy !== DataSourceRowsUpdateStrategy.LazyLoading && currentStrategy !== DataSourceRowsUpdateStrategy.GroupedData) {
298
+ if (currentStrategy !== DataSourceRowsUpdateStrategy.Default && currentStrategy !== DataSourceRowsUpdateStrategy.LazyLoading && currentStrategy !== DataSourceRowsUpdateStrategy.GroupedData && currentStrategy !== DataSourceRowsUpdateStrategy.LazyLoadedGroupedData) {
287
299
  return undefined;
288
300
  }
289
301
  if (props.dataSource) {
@@ -304,7 +316,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
304
316
  debouncedFetchRows,
305
317
  strategyProcessor: {
306
318
  strategyName: DataSourceRowsUpdateStrategy.Default,
307
- group: 'dataSourceRowsUpdate',
319
+ group: 'dataSourceRootRowsUpdate',
308
320
  processor: handleDataUpdate
309
321
  },
310
322
  setStrategyAvailability,
@@ -3,6 +3,7 @@ export declare enum DataSourceRowsUpdateStrategy {
3
3
  Default = "set-flat-rows",
4
4
  LazyLoading = "replace-row-range",
5
5
  GroupedData = "set-grouped-rows",
6
+ LazyLoadedGroupedData = "replace-grouped-row-range",
6
7
  }
7
8
  /**
8
9
  * Provides better cache hit rate by:
@@ -3,6 +3,7 @@ export declare enum DataSourceRowsUpdateStrategy {
3
3
  Default = "set-flat-rows",
4
4
  LazyLoading = "replace-row-range",
5
5
  GroupedData = "set-grouped-rows",
6
+ LazyLoadedGroupedData = "replace-grouped-row-range",
6
7
  }
7
8
  /**
8
9
  * Provides better cache hit rate by:
@@ -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
 
@@ -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.
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v9.3.0
2
+ * @mui/x-data-grid v9.4.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.4.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -27,6 +27,12 @@ export interface GridGetRowsOptions {
27
27
  * @default true
28
28
  */
29
29
  keepChildrenExpanded?: boolean;
30
+ /**
31
+ * If `false`, the loading indicator for children will not be shown during the fetch.
32
+ * Useful for background revalidation where loading indicators should be suppressed.
33
+ * @default true
34
+ */
35
+ showChildrenLoading?: boolean;
30
36
  }
31
37
  export interface GridUpdateRowParams {
32
38
  rowId: GridRowId;
@@ -27,6 +27,12 @@ export interface GridGetRowsOptions {
27
27
  * @default true
28
28
  */
29
29
  keepChildrenExpanded?: boolean;
30
+ /**
31
+ * If `false`, the loading indicator for children will not be shown during the fetch.
32
+ * Useful for background revalidation where loading indicators should be suppressed.
33
+ * @default true
34
+ */
35
+ showChildrenLoading?: boolean;
30
36
  }
31
37
  export interface GridUpdateRowParams {
32
38
  rowId: GridRowId;
@@ -129,7 +129,6 @@ export interface GridSkeletonRowNode extends GridTreeBasicNode {
129
129
  type: 'skeletonRow';
130
130
  /**
131
131
  * The id of the group containing this node.
132
- * Is always equal to `GRID_ROOT_GROUP_ID`.
133
132
  */
134
133
  parent: GridRowId;
135
134
  }
@@ -129,7 +129,6 @@ export interface GridSkeletonRowNode extends GridTreeBasicNode {
129
129
  type: 'skeletonRow';
130
130
  /**
131
131
  * The id of the group containing this node.
132
- * Is always equal to `GRID_ROOT_GROUP_ID`.
133
132
  */
134
133
  parent: GridRowId;
135
134
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid",
3
- "version": "9.3.0",
3
+ "version": "9.4.0",
4
4
  "author": "MUI Team",
5
5
  "description": "The Community plan edition of the MUI X Data Grid components.",
6
6
  "license": "MIT",
@@ -37,12 +37,12 @@
37
37
  "directory": "packages/x-data-grid"
38
38
  },
39
39
  "dependencies": {
40
- "@babel/runtime": "^7.29.2",
40
+ "@babel/runtime": "^7.29.7",
41
41
  "@mui/utils": "9.0.1",
42
42
  "clsx": "^2.1.1",
43
43
  "prop-types": "^15.8.1",
44
44
  "use-sync-external-store": "^1.6.0",
45
- "@mui/x-virtualizer": "9.0.0-alpha.7",
45
+ "@mui/x-virtualizer": "9.0.0-alpha.8",
46
46
  "@mui/x-internals": "^9.1.0"
47
47
  },
48
48
  "peerDependencies": {