@mui/x-data-grid-premium 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.
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_
@@ -51,8 +51,8 @@ const configuration = {
51
51
  }
52
52
  };
53
53
  const packageInfo = {
54
- releaseDate: "MTc3OTMyMTYwMDAwMA==",
55
- version: "9.3.0",
54
+ releaseDate: "MTc4MDUzMTIwMDAwMA==",
55
+ version: "9.4.0",
56
56
  name: 'x-data-grid-premium'
57
57
  };
58
58
  const watermark = /*#__PURE__*/(0, _jsxRuntime.jsx)(_internals.Watermark, {
@@ -44,8 +44,8 @@ const configuration = {
44
44
  }
45
45
  };
46
46
  const packageInfo = {
47
- releaseDate: "MTc3OTMyMTYwMDAwMA==",
48
- version: "9.3.0",
47
+ releaseDate: "MTc4MDUzMTIwMDAwMA==",
48
+ version: "9.4.0",
49
49
  name: 'x-data-grid-premium'
50
50
  };
51
51
  const watermark = /*#__PURE__*/_jsx(Watermark, {
@@ -135,6 +135,7 @@ const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
135
135
  (0, _internals.useGridInfiniteLoader)(apiRef, props);
136
136
  (0, _internals.useGridLazyLoader)(apiRef, props);
137
137
  (0, _internals.useGridDataSourceLazyLoader)(apiRef, props);
138
+ (0, _internals.useGridDataSourceNestedLazyLoader)(apiRef, props);
138
139
  (0, _internals.useGridInfiniteLoadingIntersection)(apiRef, props);
139
140
  (0, _internals.useGridColumnMenu)(apiRef);
140
141
  (0, _internals.useGridCsvExport)(apiRef, props);
@@ -2,7 +2,7 @@
2
2
 
3
3
  import _extends from "@babel/runtime/helpers/esm/extends";
4
4
  import * as React from 'react';
5
- import { useGridInitialization, useGridInitializeState, useGridClipboard, useGridColumnMenu, useGridColumns, columnsStateInitializer, useGridDensity, useGridCsvExport, useGridPrintExport, useGridFilter, filterStateInitializer, useGridFocus, useGridKeyboardNavigation, useGridPagination, paginationStateInitializer, useGridPreferencesPanel, useGridEditing, editingStateInitializer, useGridRows, useGridRowsPreProcessors, rowsStateInitializer, useGridParamsApi, useGridRowSelection, useGridSorting, sortingStateInitializer, useGridScroll, useGridEvents, dimensionsStateInitializer, useGridDimensions, useGridStatePersistence, useGridRowSelectionPreProcessors, columnMenuStateInitializer, densityStateInitializer, focusStateInitializer, preferencePanelStateInitializer, rowsMetaStateInitializer, rowSelectionStateInitializer, useGridColumnReorder, columnReorderStateInitializer, useGridColumnResize, columnResizeStateInitializer, useGridTreeData, useGridTreeDataPreProcessors, useGridColumnPinning, columnPinningStateInitializer, useGridColumnPinningPreProcessors, useGridDetailPanel, detailPanelStateInitializer, useGridDetailPanelPreProcessors, useGridInfiniteLoader, useGridColumnSpanning, useGridRowReorder, useGridRowReorderPreProcessors, useGridRowPinning, useGridRowPinningPreProcessors, rowPinningStateInitializer, useGridColumnGrouping, columnGroupsStateInitializer, useGridLazyLoader, useGridLazyLoaderPreProcessors, useGridDataSourceLazyLoader, useGridInfiniteLoadingIntersection, headerFilteringStateInitializer, useGridHeaderFiltering, virtualizationStateInitializer, useGridVirtualization, useGridDataSourceTreeDataPreProcessors, dataSourceStateInitializer, useGridRowSpanning, rowSpanningStateInitializer, useGridListView, listViewStateInitializer, propsStateInitializer, rowReorderStateInitializer, useFirstRender } from '@mui/x-data-grid-pro/internals';
5
+ import { useGridInitialization, useGridInitializeState, useGridClipboard, useGridColumnMenu, useGridColumns, columnsStateInitializer, useGridDensity, useGridCsvExport, useGridPrintExport, useGridFilter, filterStateInitializer, useGridFocus, useGridKeyboardNavigation, useGridPagination, paginationStateInitializer, useGridPreferencesPanel, useGridEditing, editingStateInitializer, useGridRows, useGridRowsPreProcessors, rowsStateInitializer, useGridParamsApi, useGridRowSelection, useGridSorting, sortingStateInitializer, useGridScroll, useGridEvents, dimensionsStateInitializer, useGridDimensions, useGridStatePersistence, useGridRowSelectionPreProcessors, columnMenuStateInitializer, densityStateInitializer, focusStateInitializer, preferencePanelStateInitializer, rowsMetaStateInitializer, rowSelectionStateInitializer, useGridColumnReorder, columnReorderStateInitializer, useGridColumnResize, columnResizeStateInitializer, useGridTreeData, useGridTreeDataPreProcessors, useGridColumnPinning, columnPinningStateInitializer, useGridColumnPinningPreProcessors, useGridDetailPanel, detailPanelStateInitializer, useGridDetailPanelPreProcessors, useGridInfiniteLoader, useGridColumnSpanning, useGridRowReorder, useGridRowReorderPreProcessors, useGridRowPinning, useGridRowPinningPreProcessors, rowPinningStateInitializer, useGridColumnGrouping, columnGroupsStateInitializer, useGridLazyLoader, useGridLazyLoaderPreProcessors, useGridDataSourceLazyLoader, useGridDataSourceNestedLazyLoader, useGridInfiniteLoadingIntersection, headerFilteringStateInitializer, useGridHeaderFiltering, virtualizationStateInitializer, useGridVirtualization, useGridDataSourceTreeDataPreProcessors, dataSourceStateInitializer, useGridRowSpanning, rowSpanningStateInitializer, useGridListView, listViewStateInitializer, propsStateInitializer, rowReorderStateInitializer, useFirstRender } from '@mui/x-data-grid-pro/internals';
6
6
  import { useGridSelector } from '@mui/x-data-grid-pro';
7
7
  import { useGridDataSourcePremium as useGridDataSource } from "../hooks/features/dataSource/useGridDataSourcePremium.mjs";
8
8
  // Premium-only features
@@ -127,6 +127,7 @@ export const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
127
127
  useGridInfiniteLoader(apiRef, props);
128
128
  useGridLazyLoader(apiRef, props);
129
129
  useGridDataSourceLazyLoader(apiRef, props);
130
+ useGridDataSourceNestedLazyLoader(apiRef, props);
130
131
  useGridInfiniteLoadingIntersection(apiRef, props);
131
132
  useGridColumnMenu(apiRef);
132
133
  useGridCsvExport(apiRef, props);
@@ -40,18 +40,24 @@ function GridGroupingCriteriaCellIcon(props) {
40
40
  const error = (0, _xDataGridPro.useGridSelector)(apiRef, _internals.gridDataSourceErrorSelector, id);
41
41
  const handleClick = event => {
42
42
  if (!rowNode.childrenExpanded) {
43
- // always fetch/get from cache the children when the node is expanded
44
- apiRef.current.dataSource.fetchRows(id);
43
+ if (!rootProps.lazyLoading) {
44
+ // always fetch/get from cache the children when the node is expanded
45
+ apiRef.current.dataSource.fetchRows(id);
46
+ } else {
47
+ apiRef.current.setRowChildrenExpansion(id, true);
48
+ }
45
49
  } else {
46
50
  // Collapse the node and remove child rows from the grid
47
51
  apiRef.current.setRowChildrenExpansion(id, false);
48
- apiRef.current.removeChildrenRows(id);
52
+ if (!rootProps.lazyLoading) {
53
+ apiRef.current.removeChildrenRows(id);
54
+ }
49
55
  }
50
56
  apiRef.current.setCellFocus(id, field);
51
57
  event.stopPropagation();
52
58
  };
53
59
  const Icon = rowNode.childrenExpanded ? rootProps.slots.groupingCriteriaCollapseIcon : rootProps.slots.groupingCriteriaExpandIcon;
54
- if (isDataLoading) {
60
+ if (isDataLoading && !rootProps.lazyLoading) {
55
61
  return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
56
62
  className: classes.loadingContainer,
57
63
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.baseCircularProgress, {
@@ -32,18 +32,24 @@ function GridGroupingCriteriaCellIcon(props) {
32
32
  const error = useGridSelector(apiRef, gridDataSourceErrorSelector, id);
33
33
  const handleClick = event => {
34
34
  if (!rowNode.childrenExpanded) {
35
- // always fetch/get from cache the children when the node is expanded
36
- apiRef.current.dataSource.fetchRows(id);
35
+ if (!rootProps.lazyLoading) {
36
+ // always fetch/get from cache the children when the node is expanded
37
+ apiRef.current.dataSource.fetchRows(id);
38
+ } else {
39
+ apiRef.current.setRowChildrenExpansion(id, true);
40
+ }
37
41
  } else {
38
42
  // Collapse the node and remove child rows from the grid
39
43
  apiRef.current.setRowChildrenExpansion(id, false);
40
- apiRef.current.removeChildrenRows(id);
44
+ if (!rootProps.lazyLoading) {
45
+ apiRef.current.removeChildrenRows(id);
46
+ }
41
47
  }
42
48
  apiRef.current.setCellFocus(id, field);
43
49
  event.stopPropagation();
44
50
  };
45
51
  const Icon = rowNode.childrenExpanded ? rootProps.slots.groupingCriteriaCollapseIcon : rootProps.slots.groupingCriteriaExpandIcon;
46
- if (isDataLoading) {
52
+ if (isDataLoading && !rootProps.lazyLoading) {
47
53
  return /*#__PURE__*/_jsx("div", {
48
54
  className: classes.loadingContainer,
49
55
  children: /*#__PURE__*/_jsx(rootProps.slots.baseCircularProgress, {
@@ -24,9 +24,6 @@ const avgAgg = {
24
24
  apply: ({
25
25
  values
26
26
  }) => {
27
- if (values.length === 0) {
28
- return null;
29
- }
30
27
  let sum = 0;
31
28
  let valuesCount = 0;
32
29
  for (let i = 0; i < values.length; i += 1) {
@@ -36,7 +33,7 @@ const avgAgg = {
36
33
  sum += value;
37
34
  }
38
35
  }
39
- if (sum === 0) {
36
+ if (valuesCount === 0) {
40
37
  return null;
41
38
  }
42
39
  return sum / valuesCount;
@@ -18,9 +18,6 @@ const avgAgg = {
18
18
  apply: ({
19
19
  values
20
20
  }) => {
21
- if (values.length === 0) {
22
- return null;
23
- }
24
21
  let sum = 0;
25
22
  let valuesCount = 0;
26
23
  for (let i = 0; i < values.length; i += 1) {
@@ -30,7 +27,7 @@ const avgAgg = {
30
27
  sum += value;
31
28
  }
32
29
  }
33
- if (sum === 0) {
30
+ if (valuesCount === 0) {
34
31
  return null;
35
32
  }
36
33
  return sum / valuesCount;
@@ -25,14 +25,34 @@ const options = {
25
25
  getKey: getKeyPremium
26
26
  }
27
27
  };
28
+ const getStrategies = (props, groupingModelSize) => {
29
+ const previousStrategies = new Set([_internals.DataSourceRowsUpdateStrategy.Default, _internals.DataSourceRowsUpdateStrategy.GroupedData, _internals.DataSourceRowsUpdateStrategy.LazyLoadedGroupedData]);
30
+ let currentStrategy = _internals.DataSourceRowsUpdateStrategy.Default;
31
+ if (props.treeData || !props.disableRowGrouping && groupingModelSize > 0) {
32
+ currentStrategy = props.lazyLoading ? _internals.DataSourceRowsUpdateStrategy.LazyLoadedGroupedData : _internals.DataSourceRowsUpdateStrategy.GroupedData;
33
+ }
34
+ previousStrategies.delete(currentStrategy);
35
+ return {
36
+ currentStrategy,
37
+ previousStrategies: Array.from(previousStrategies)
38
+ };
39
+ };
28
40
  const useGridDataSourcePremium = (apiRef, props) => {
29
41
  const aggregationModel = (0, _gridAggregationSelectors.gridAggregationModelSelector)(apiRef);
30
42
  const groupingModelSize = (0, _gridRowGroupingSelector.gridRowGroupingSanitizedModelSelector)(apiRef).length;
31
43
  const setStrategyAvailability = React.useCallback(() => {
32
- const currentStrategy = props.treeData || !props.disableRowGrouping && groupingModelSize > 0 ? _internals.DataSourceRowsUpdateStrategy.GroupedData : _internals.DataSourceRowsUpdateStrategy.Default;
33
- const prevStrategy = currentStrategy === _internals.DataSourceRowsUpdateStrategy.GroupedData ? _internals.DataSourceRowsUpdateStrategy.Default : _internals.DataSourceRowsUpdateStrategy.GroupedData;
34
- apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, prevStrategy, () => false);
35
- apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, currentStrategy, props.dataSource && !props.lazyLoading ? () => true : () => false);
44
+ const {
45
+ currentStrategy,
46
+ previousStrategies
47
+ } = getStrategies({
48
+ treeData: props.treeData,
49
+ lazyLoading: props.lazyLoading,
50
+ disableRowGrouping: props.disableRowGrouping
51
+ }, groupingModelSize);
52
+ previousStrategies.forEach(strategy => {
53
+ apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, strategy, () => false);
54
+ });
55
+ apiRef.current.setStrategyAvailability(_internals.GridStrategyGroup.DataSource, currentStrategy, props.dataSource ? () => true : () => false);
36
56
  }, [apiRef, props.dataSource, props.lazyLoading, props.treeData, props.disableRowGrouping, groupingModelSize]);
37
57
  const handleEditRowWithAggregation = React.useCallback((params, updatedRow) => {
38
58
  const rowTree = (0, _xDataGridPro.gridRowTreeSelector)(apiRef);
@@ -50,6 +70,7 @@ const useGridDataSourcePremium = (apiRef, props) => {
50
70
  debouncedFetchRows,
51
71
  flatTreeStrategyProcessor,
52
72
  groupedDataStrategyProcessor,
73
+ nestedDataStrategyProcessor,
53
74
  events,
54
75
  stopPolling
55
76
  } = (0, _internals.useGridDataSourceBasePro)(apiRef, props, (0, _extends2.default)({}, !props.disableAggregation && Object.keys(aggregationModel).length > 0 ? {
@@ -105,7 +126,22 @@ See [server-side pivoting](https://mui.com/x/react-data-grid/server-side-data/pi
105
126
  return props.dataSource?.getAggregatedValue?.(row, field);
106
127
  }, [apiRef, props.dataSource]);
107
128
  const handleRowGroupingModelChange = React.useCallback(() => {
129
+ // Clear the rows on every grouping model change to match the pre-fix behavior on
130
+ // non-standard strategies (e.g. lazy loading) where `setRows([])` is required to
131
+ // reset the existing grouping state.
108
132
  apiRef.current.setRows([]);
133
+ // The event listener is wired regardless of the active strategy
134
+ // (see `runIf(!pivotActive && !!props.dataSource, ...)` below), so we have to gate the
135
+ // `setLoading(true)` here. `fetchRows` only clears the loading flag when a standard
136
+ // strategy is active, and we don't want to leave the overlay stuck on lazy-loading or
137
+ // other non-standard strategies. Order matters too: `setRows([])` above rebuilds
138
+ // `state.rows` from `props.loading`, so the `setLoading(true)` call must come after
139
+ // it to survive the rebuild.
140
+ const currentStrategy = apiRef.current.getActiveStrategy(_internals.GridStrategyGroup.DataSource);
141
+ const isStandardStrategyActive = currentStrategy === _internals.DataSourceRowsUpdateStrategy.Default || currentStrategy === _internals.DataSourceRowsUpdateStrategy.GroupedData;
142
+ if (isStandardStrategyActive) {
143
+ apiRef.current.setLoading(true);
144
+ }
109
145
  stopPolling();
110
146
  debouncedFetchRows();
111
147
  }, [apiRef, debouncedFetchRows, stopPolling]);
@@ -116,6 +152,7 @@ See [server-side pivoting](https://mui.com/x/react-data-grid/server-side-data/pi
116
152
  (0, _xDataGridPro.useGridApiMethod)(apiRef, privateApi, 'private');
117
153
  (0, _internals.useGridRegisterStrategyProcessor)(apiRef, flatTreeStrategyProcessor.strategyName, flatTreeStrategyProcessor.group, flatTreeStrategyProcessor.processor);
118
154
  (0, _internals.useGridRegisterStrategyProcessor)(apiRef, groupedDataStrategyProcessor.strategyName, groupedDataStrategyProcessor.group, groupedDataStrategyProcessor.processor);
155
+ (0, _internals.useGridRegisterStrategyProcessor)(apiRef, nestedDataStrategyProcessor.strategyName, nestedDataStrategyProcessor.group, nestedDataStrategyProcessor.processor);
119
156
  (0, _internals.useGridRegisterPipeProcessor)(apiRef, 'processDataSourceRows', processDataSourceRows);
120
157
  Object.entries(events).forEach(([event, handler]) => {
121
158
  (0, _xDataGridPro.useGridEvent)(apiRef, event, handler);
@@ -18,14 +18,34 @@ const options = {
18
18
  getKey: getKeyPremium
19
19
  }
20
20
  };
21
+ const getStrategies = (props, groupingModelSize) => {
22
+ const previousStrategies = new Set([DataSourceRowsUpdateStrategy.Default, DataSourceRowsUpdateStrategy.GroupedData, DataSourceRowsUpdateStrategy.LazyLoadedGroupedData]);
23
+ let currentStrategy = DataSourceRowsUpdateStrategy.Default;
24
+ if (props.treeData || !props.disableRowGrouping && groupingModelSize > 0) {
25
+ currentStrategy = props.lazyLoading ? DataSourceRowsUpdateStrategy.LazyLoadedGroupedData : DataSourceRowsUpdateStrategy.GroupedData;
26
+ }
27
+ previousStrategies.delete(currentStrategy);
28
+ return {
29
+ currentStrategy,
30
+ previousStrategies: Array.from(previousStrategies)
31
+ };
32
+ };
21
33
  export const useGridDataSourcePremium = (apiRef, props) => {
22
34
  const aggregationModel = gridAggregationModelSelector(apiRef);
23
35
  const groupingModelSize = gridRowGroupingSanitizedModelSelector(apiRef).length;
24
36
  const setStrategyAvailability = React.useCallback(() => {
25
- const currentStrategy = props.treeData || !props.disableRowGrouping && groupingModelSize > 0 ? DataSourceRowsUpdateStrategy.GroupedData : DataSourceRowsUpdateStrategy.Default;
26
- const prevStrategy = currentStrategy === DataSourceRowsUpdateStrategy.GroupedData ? DataSourceRowsUpdateStrategy.Default : DataSourceRowsUpdateStrategy.GroupedData;
27
- apiRef.current.setStrategyAvailability(GridStrategyGroup.DataSource, prevStrategy, () => false);
28
- apiRef.current.setStrategyAvailability(GridStrategyGroup.DataSource, currentStrategy, props.dataSource && !props.lazyLoading ? () => true : () => false);
37
+ const {
38
+ currentStrategy,
39
+ previousStrategies
40
+ } = getStrategies({
41
+ treeData: props.treeData,
42
+ lazyLoading: props.lazyLoading,
43
+ disableRowGrouping: props.disableRowGrouping
44
+ }, groupingModelSize);
45
+ previousStrategies.forEach(strategy => {
46
+ apiRef.current.setStrategyAvailability(GridStrategyGroup.DataSource, strategy, () => false);
47
+ });
48
+ apiRef.current.setStrategyAvailability(GridStrategyGroup.DataSource, currentStrategy, props.dataSource ? () => true : () => false);
29
49
  }, [apiRef, props.dataSource, props.lazyLoading, props.treeData, props.disableRowGrouping, groupingModelSize]);
30
50
  const handleEditRowWithAggregation = React.useCallback((params, updatedRow) => {
31
51
  const rowTree = gridRowTreeSelector(apiRef);
@@ -43,6 +63,7 @@ export const useGridDataSourcePremium = (apiRef, props) => {
43
63
  debouncedFetchRows,
44
64
  flatTreeStrategyProcessor,
45
65
  groupedDataStrategyProcessor,
66
+ nestedDataStrategyProcessor,
46
67
  events,
47
68
  stopPolling
48
69
  } = useGridDataSourceBasePro(apiRef, props, _extends({}, !props.disableAggregation && Object.keys(aggregationModel).length > 0 ? {
@@ -98,7 +119,22 @@ See [server-side pivoting](https://mui.com/x/react-data-grid/server-side-data/pi
98
119
  return props.dataSource?.getAggregatedValue?.(row, field);
99
120
  }, [apiRef, props.dataSource]);
100
121
  const handleRowGroupingModelChange = React.useCallback(() => {
122
+ // Clear the rows on every grouping model change to match the pre-fix behavior on
123
+ // non-standard strategies (e.g. lazy loading) where `setRows([])` is required to
124
+ // reset the existing grouping state.
101
125
  apiRef.current.setRows([]);
126
+ // The event listener is wired regardless of the active strategy
127
+ // (see `runIf(!pivotActive && !!props.dataSource, ...)` below), so we have to gate the
128
+ // `setLoading(true)` here. `fetchRows` only clears the loading flag when a standard
129
+ // strategy is active, and we don't want to leave the overlay stuck on lazy-loading or
130
+ // other non-standard strategies. Order matters too: `setRows([])` above rebuilds
131
+ // `state.rows` from `props.loading`, so the `setLoading(true)` call must come after
132
+ // it to survive the rebuild.
133
+ const currentStrategy = apiRef.current.getActiveStrategy(GridStrategyGroup.DataSource);
134
+ const isStandardStrategyActive = currentStrategy === DataSourceRowsUpdateStrategy.Default || currentStrategy === DataSourceRowsUpdateStrategy.GroupedData;
135
+ if (isStandardStrategyActive) {
136
+ apiRef.current.setLoading(true);
137
+ }
102
138
  stopPolling();
103
139
  debouncedFetchRows();
104
140
  }, [apiRef, debouncedFetchRows, stopPolling]);
@@ -109,6 +145,7 @@ See [server-side pivoting](https://mui.com/x/react-data-grid/server-side-data/pi
109
145
  useGridApiMethod(apiRef, privateApi, 'private');
110
146
  useGridRegisterStrategyProcessor(apiRef, flatTreeStrategyProcessor.strategyName, flatTreeStrategyProcessor.group, flatTreeStrategyProcessor.processor);
111
147
  useGridRegisterStrategyProcessor(apiRef, groupedDataStrategyProcessor.strategyName, groupedDataStrategyProcessor.group, groupedDataStrategyProcessor.processor);
148
+ useGridRegisterStrategyProcessor(apiRef, nestedDataStrategyProcessor.strategyName, nestedDataStrategyProcessor.group, nestedDataStrategyProcessor.processor);
112
149
  useGridRegisterPipeProcessor(apiRef, 'processDataSourceRows', processDataSourceRows);
113
150
  Object.entries(events).forEach(([event, handler]) => {
114
151
  addEventHandler(apiRef, event, handler);
@@ -8,4 +8,4 @@ export declare const rowGroupingStateInitializer: GridStateInitializer<Pick<Data
8
8
  * @requires useGridRows (state, method) - can be after, async only
9
9
  * @requires useGridParamsApi (method) - can be after, async only
10
10
  */
11
- export declare const useGridRowGrouping: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "initialState" | "rowGroupingModel" | "onRowGroupingModelChange" | "isGroupExpandedByDefault" | "rowGroupingColumnMode" | "disableRowGrouping" | "slotProps" | "slots" | "dataSource" | "treeData" | "isValidRowReorder">) => void;
11
+ export declare const useGridRowGrouping: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "initialState" | "rowGroupingModel" | "onRowGroupingModelChange" | "isGroupExpandedByDefault" | "rowGroupingColumnMode" | "disableRowGrouping" | "slotProps" | "slots" | "dataSource" | "lazyLoading" | "treeData" | "isValidRowReorder">) => void;
@@ -8,4 +8,4 @@ export declare const rowGroupingStateInitializer: GridStateInitializer<Pick<Data
8
8
  * @requires useGridRows (state, method) - can be after, async only
9
9
  * @requires useGridParamsApi (method) - can be after, async only
10
10
  */
11
- export declare const useGridRowGrouping: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "initialState" | "rowGroupingModel" | "onRowGroupingModelChange" | "isGroupExpandedByDefault" | "rowGroupingColumnMode" | "disableRowGrouping" | "slotProps" | "slots" | "dataSource" | "treeData" | "isValidRowReorder">) => void;
11
+ export declare const useGridRowGrouping: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "initialState" | "rowGroupingModel" | "onRowGroupingModelChange" | "isGroupExpandedByDefault" | "rowGroupingColumnMode" | "disableRowGrouping" | "slotProps" | "slots" | "dataSource" | "lazyLoading" | "treeData" | "isValidRowReorder">) => void;
@@ -152,12 +152,16 @@ const useGridRowGrouping = (apiRef, props) => {
152
152
  return;
153
153
  }
154
154
  if (props.dataSource && !params.rowNode.childrenExpanded) {
155
- apiRef.current.dataSource.fetchRows(params.id);
155
+ if (props.lazyLoading) {
156
+ apiRef.current.setRowChildrenExpansion(params.id, true);
157
+ } else {
158
+ apiRef.current.dataSource.fetchRows(params.id);
159
+ }
156
160
  return;
157
161
  }
158
162
  apiRef.current.setRowChildrenExpansion(params.id, !params.rowNode.childrenExpanded);
159
163
  }
160
- }, [apiRef, props.rowGroupingColumnMode, props.dataSource]);
164
+ }, [apiRef, props.rowGroupingColumnMode, props.dataSource, props.lazyLoading]);
161
165
  const checkGroupingColumnsModelDiff = React.useCallback(() => {
162
166
  const sanitizedRowGroupingModel = (0, _gridRowGroupingSelector.gridRowGroupingSanitizedModelSelector)(apiRef);
163
167
  const rulesOnLastRowTreeCreation = apiRef.current.caches.rowGrouping.rulesOnLastRowTreeCreation || [];
@@ -144,12 +144,16 @@ export const useGridRowGrouping = (apiRef, props) => {
144
144
  return;
145
145
  }
146
146
  if (props.dataSource && !params.rowNode.childrenExpanded) {
147
- apiRef.current.dataSource.fetchRows(params.id);
147
+ if (props.lazyLoading) {
148
+ apiRef.current.setRowChildrenExpansion(params.id, true);
149
+ } else {
150
+ apiRef.current.dataSource.fetchRows(params.id);
151
+ }
148
152
  return;
149
153
  }
150
154
  apiRef.current.setRowChildrenExpansion(params.id, !params.rowNode.childrenExpanded);
151
155
  }
152
- }, [apiRef, props.rowGroupingColumnMode, props.dataSource]);
156
+ }, [apiRef, props.rowGroupingColumnMode, props.dataSource, props.lazyLoading]);
153
157
  const checkGroupingColumnsModelDiff = React.useCallback(() => {
154
158
  const sanitizedRowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
155
159
  const rulesOnLastRowTreeCreation = apiRef.current.caches.rowGrouping.rulesOnLastRowTreeCreation || [];
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-premium v9.3.0
2
+ * @mui/x-data-grid-premium v9.4.0
3
3
  *
4
4
  * @license SEE LICENSE IN LICENSE
5
5
  * This source code is licensed under the SEE LICENSE IN LICENSE license found in the
package/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-premium v9.3.0
2
+ * @mui/x-data-grid-premium v9.4.0
3
3
  *
4
4
  * @license SEE LICENSE IN LICENSE
5
5
  * This source code is licensed under the SEE LICENSE IN LICENSE license found in the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid-premium",
3
- "version": "9.3.0",
3
+ "version": "9.4.0",
4
4
  "author": "MUI Team",
5
5
  "description": "The Premium plan edition of the MUI X Data Grid Components.",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -33,15 +33,15 @@
33
33
  "directory": "packages/x-data-grid-premium"
34
34
  },
35
35
  "dependencies": {
36
- "@babel/runtime": "^7.29.2",
36
+ "@babel/runtime": "^7.29.7",
37
37
  "@mui/utils": "9.0.1",
38
- "@mui/x-internal-exceljs-fork": "4.4.5",
38
+ "@mui/x-internal-exceljs-fork": "5.0.0",
39
39
  "clsx": "^2.1.1",
40
40
  "prop-types": "^15.8.1",
41
- "@mui/x-data-grid-pro": "^9.3.0",
42
- "@mui/x-data-grid": "^9.3.0",
41
+ "@mui/x-data-grid-pro": "^9.4.0",
42
+ "@mui/x-data-grid": "^9.4.0",
43
43
  "@mui/x-internals": "^9.1.0",
44
- "@mui/x-license": "^9.2.0"
44
+ "@mui/x-license": "^9.4.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@emotion/react": "^11.9.0",
@@ -60,7 +60,7 @@
60
60
  }
61
61
  },
62
62
  "engines": {
63
- "node": ">=14.0.0"
63
+ "node": ">=14.17.0"
64
64
  },
65
65
  "type": "commonjs",
66
66
  "exports": {