@mui/x-data-grid-premium 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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,301 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.5.0
4
+
5
+ _Jun 11, 2026_
6
+
7
+ We'd like to extend a big thank you to the 9 contributors who made this release possible. Here are some highlights ✨:
8
+
9
+ - 🎁 New [`multiSelect` column type for Data Grid Pro](https://mui.com/x/react-data-grid/column-definition/#MultiSelectColumn)
10
+ - 🚀 New [renderer="svg-progressive"](https://mui.com/x/react-charts/scatter/#progressive-renderer) paints scatter points in batched frames so large datasets render smoothly without blocking the main thread.
11
+ - 🐞 Bugfixes
12
+ - 📚 Documentation improvements
13
+
14
+ Special thanks go out to community members @mustafajw07 and @Anexus5919 for their valuable contribution.
15
+
16
+ The following team members contributed to this release:
17
+ @alexfauquette, @JCQuintas, @rita-codes, @rluzists1, @sai6855, @siriwatknp, @arminmeh, @brijeshb42
18
+
19
+ ### Data Grid
20
+
21
+ #### `@mui/x-data-grid@9.5.0`
22
+
23
+ - [DataGrid] Restrict warning messages to non-production environments in various components (#22461) @sai6855
24
+ - [DataGrid] Prevent React state update before mount (#22374) @arminmeh
25
+
26
+ #### `@mui/x-data-grid-pro@9.5.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
27
+
28
+ Same changes as in `@mui/x-data-grid@9.5.0`, plus:
29
+
30
+ - [DataGridPro] Add new `multiSelect` column type (#21157) @siriwatknp
31
+
32
+ #### `@mui/x-data-grid-premium@9.5.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
33
+
34
+ Same changes as in `@mui/x-data-grid-pro@9.5.0`.
35
+
36
+ ### Date and Time Pickers
37
+
38
+ #### `@mui/x-date-pickers@9.5.0`
39
+
40
+ - [pickers] Fix missing export of `th-TH` (#22703) @alexfauquette
41
+
42
+ #### `@mui/x-date-pickers-pro@9.5.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
43
+
44
+ Same changes as in `@mui/x-date-pickers@9.5.0`.
45
+
46
+ ### Charts
47
+
48
+ #### `@mui/x-charts@9.5.0`
49
+
50
+ - [charts] Add `FocusedBar` component to `BarScatterComposition` demo (#22704) @sai6855
51
+ - [charts] Add dedicated Bubble Chart documentation page (#22688) @mustafajw07
52
+ - [charts] Add progressive scatter renderer (#22518) @JCQuintas
53
+ - [charts] Avoid full axis pipeline rebuild on resize (#22695) @JCQuintas
54
+ - [charts] Document focus indicator in composition page (#22712) @JCQuintas
55
+ - [charts] Fix `ChartsTooltip` `container` and `disablePortal` props being ignored (#22690) @JCQuintas
56
+ - [charts] Make ordinal scales O(1) to copy and re-range (#22691) @JCQuintas
57
+ - [charts] Stabilize WebGL bar rendering at sub-pixel widths (#22678) @JCQuintas
58
+ - [charts] Use the series config to define value types (#22693) @sai6855
59
+ - [charts] Decouple interaction hook from the cartesian zoom (#22708) @alexfauquette
60
+
61
+ #### `@mui/x-charts-pro@9.5.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
62
+
63
+ Same changes as in `@mui/x-charts@9.5.0`, plus:
64
+
65
+ - [charts-pro] Add missing focus highlight (#22689) @alexfauquette
66
+
67
+ #### `@mui/x-charts-premium@9.5.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
68
+
69
+ Same changes as in `@mui/x-charts-pro@9.5.0`, plus:
70
+
71
+ - [charts-premium] Set `Heatmap` WebGL render as stable (#22665) @alexfauquette
72
+ - [charts-premium] Stabilize candlestick charts (#22666) @alexfauquette
73
+ - [charts-premium] Stabilize the radial charts (#22655) @alexfauquette
74
+
75
+ ### Scheduler
76
+
77
+ #### `@mui/x-scheduler@9.0.0-beta.1`
78
+
79
+ Internal changes.
80
+
81
+ #### `@mui/x-scheduler-premium@9.0.0-beta.1` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
82
+
83
+ Same changes as in `@mui/x-scheduler@9.0.0-beta.1`, plus:
84
+
85
+ - [scheduler] Remove dead CSS variable writes in `EventTimelinePremiumContent` (#22720) @rita-codes
86
+ - [scheduler] Show scope dialog when deleting a recurring event (#22552) @Anexus5919
87
+
88
+ ### Core
89
+
90
+ - [docs-infra] Fix immutable cache headers for `/\_next/static` assets (#22747) @brijeshb42
91
+ - [docs-infra] Prefix `/\_next/static` cache header rule with `/x` basePath (#22748) @brijeshb42
92
+ - [code-infra] Update dependencies to resolve Dependabot security alerts (#22714) @Janpot
93
+
94
+ ### Docs
95
+
96
+ - [docs] Fix broken links checker crashing on 404 known-targets fetch (#22707) @sai6855
97
+ - [docs] Fix country data (#22716) @alexfauquette
98
+
99
+ ### Miscellaneous
100
+
101
+ - [legal] Update EULA links in docs (#22717) @rluzists1
102
+
103
+ ## 9.4.0
104
+
105
+ <!-- generated comparing v9.3.0..master -->
106
+
107
+ _Jun 4, 2026_
108
+
109
+ We'd like to extend a big thank you to the 21 contributors who made this release possible. Here are some highlights ✨:
110
+
111
+ - 🎉 Scheduler is now in Beta shipping with Timeline vitualization and lazy loading
112
+ - 📆 Implement Event Timeline virtualization (#22339)
113
+ - 🫧 Introduce bubble charts (#22537)
114
+ - 🐞 Bugfixes
115
+ - 📚 Documentation improvements
116
+
117
+ Special thanks go out to these community members for their valuable contributions:
118
+ @imxv, @mixelburg, @mustafajw07
119
+
120
+ The following team members contributed to this release:
121
+ @aemartos, @alexfauquette, @arminmeh, @bernardobelchior, @cherniavskii, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @joserodolfofreitas, @LukasTy, @MBilalShafi, @michelengelen, @mj12albert, @noraleonte, @oliviertassinari, @rita-codes, @romgrk, @sai6855
122
+
123
+ ### Data Grid
124
+
125
+ #### `@mui/x-data-grid@9.4.0`
126
+
127
+ - [DataGrid] Fix `avg` aggregation when the average is zero (#22652) @mj12albert
128
+ - [DataGrid] Inherit icon `fontSize` from `baseIconButton` size (#22187) @imxv
129
+ - [DataGrid] Fix `noRowsOverlay` flicker between `dataSource` re-fetches (#22465) @LukasTy
130
+
131
+ #### `@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')
132
+
133
+ Same changes as in `@mui/x-data-grid@9.4.0`.
134
+
135
+ #### `@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')
136
+
137
+ > This release includes a version bump of the `@mui/x-internal-exceljs-fork` package to address the vulnerable dependencies.
138
+ > The following CVEs are fixed:
139
+ >
140
+ > - <https://github.com/advisories/GHSA-ph9p-34f9-6g65>
141
+ > - <https://github.com/isaacs/minimatch/security/advisories/GHSA-23c5-xmqv-rm74>
142
+ > - <https://github.com/advisories/GHSA-w5hq-g745-h8pq>
143
+ >
144
+ > To make this security update possible, we bumped the `node` version requirement from `>=14.0.0` to `>=14.17.0`.
145
+ > [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.
146
+
147
+ Same changes as in `@mui/x-data-grid-pro@9.4.0`, plus:
148
+
149
+ - [DataGridPremium] Nested Lazy Loading (#21043) @MBilalShafi
150
+ - [DataGridPremium] Update exceljs fork (#22658) @cherniavskii
151
+
152
+ ### Date and Time Pickers
153
+
154
+ #### `@mui/x-date-pickers@9.4.0`
155
+
156
+ Internal changes.
157
+
158
+ #### `@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')
159
+
160
+ Same changes as in `@mui/x-date-pickers@9.4.0`.
161
+
162
+ ### Charts
163
+
164
+ #### `@mui/x-charts@9.4.0`
165
+
166
+ - [charts] Add functionality to hide elements during chart export (#22525) @sai6855
167
+ - [charts] Add option to show marks only on the first/last values (#22645) @alexfauquette
168
+ - [charts] Add text customization section and demo for axis labels (#22597) @sai6855
169
+ - [charts] Allow axes to scale according to the visible series only (#22566) @alexfauquette
170
+ - [charts] Correctly handle different identifiers for each series (#22556) @sai6855
171
+ - [charts] Fix inverted Y axis zoom/pan on ordinal scales (#22654) @JCQuintas
172
+ - [charts] Introduce bubble charts (#22537) @alexfauquette
173
+ - [charts] Let scatter chart tooltip ignore hidden series (#22614) @alexfauquette
174
+ - [charts] Make `'sqrt'` size mapping the default (#22683) @alexfauquette
175
+ - [charts] Remove unused proptypes (#22618) @alexfauquette
176
+ - [charts] Support module augmentation for slots (#22519) @sai6855
177
+ - [charts] Support multiple marker size in `findClosestPoint` (#22622) @alexfauquette
178
+ - [charts] Upgrade bezier-easing to v3 and use it for line chart hit-detection (#22608) @sai6855
179
+ - [charts] Use `useLayoutEffect` with `ResizeObserver` (#22646) @JCQuintas
180
+
181
+ #### `@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')
182
+
183
+ Same changes as in `@mui/x-charts@9.4.0`, plus:
184
+
185
+ - [charts-pro] Auto-select range button matching current zoom (#22137) @JCQuintas
186
+ - [charts-pro] Support range values in `initialZoom` (#22563) @JCQuintas
187
+
188
+ #### `@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')
189
+
190
+ Same changes as in `@mui/x-charts-pro@9.4.0`, plus:
191
+
192
+ - [charts-premium] Support range-bar series in WebGL bar renderer (#22607) @JCQuintas
193
+ - [charts-premium] Fix `onAxisClick` for radial bar and lines (#22522) @alexfauquette
194
+
195
+ ### Tree View
196
+
197
+ #### `@mui/x-tree-view@9.4.0`
198
+
199
+ Internal changes.
200
+
201
+ #### `@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')
202
+
203
+ Same changes as in `@mui/x-tree-view@9.4.0`.
204
+
205
+ ### Scheduler
206
+
207
+ #### Breaking changes
208
+
209
+ The theme `styleOverrides` slots for the skeleton and the error container were
210
+ renamed and unified. The CSS utility class names (for example
211
+ `.MuiEventCalendar-eventSkeleton`) are **not** affected — only
212
+ `theme.components.*` overrides need updating.
213
+
214
+ **Event skeleton**
215
+
216
+ | Before | After |
217
+ | --------------------------------------- | ------------------------------ |
218
+ | `MuiEventCalendar` slot `EventSkeleton` | `MuiEventSkeleton` slot `Root` |
219
+ | `MuiEventTimeline` slot `EventSkeleton` | `MuiEventSkeleton` slot `Root` |
220
+
221
+ **Error container**
222
+
223
+ | Before | After |
224
+ | ------------------------------------------------------------- | --------------------------------------- |
225
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorContainer` | `MuiEventErrorContainer` slot `Root` |
226
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorAlert` | `MuiEventErrorContainer` slot `Alert` |
227
+ | `MuiEventCalendar` / `MuiEventTimeline` slot `ErrorMessage` | `MuiEventErrorContainer` slot `Message` |
228
+
229
+ If you customized these through the theme, update the component name and slot
230
+ names accordingly:
231
+
232
+ ```diff
233
+ components: {
234
+ - MuiEventCalendar: {
235
+ + MuiEventSkeleton: {
236
+ styleOverrides: {
237
+ - EventSkeleton: { /* ... */ },
238
+ + Root: { /* ... */ },
239
+ },
240
+ },
241
+ },
242
+ }
243
+ ```
244
+
245
+ #### `@mui/x-scheduler@9.0.0-beta.0`
246
+
247
+ - [scheduler] Add a prop to control whether the resource of an event can be cleared (#22464) @rita-codes
248
+ - [scheduler] Add week number labels to agenda, day and week views (#22594) @mustafajw07
249
+ - [scheduler] Add `weekStartsOn` preference and update date functions to support custom week start (#22426) @mustafajw07
250
+ - [scheduler] Export premium version of the standalone views (#22621) @flaviendelangle
251
+ - [scheduler] Implement timeline virtualization (#22339) @romgrk
252
+ - [scheduler] Split scheduler overview (#22453) @joserodolfofreitas
253
+ - [scheduler] Unify `EventSkeleton` and `ErrorContainer` between `EventCalendar` and `EventTimeline` (#22676) @noraleonte
254
+
255
+ #### `@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')
256
+
257
+ Same changes as in `@mui/x-scheduler@9.0.0-beta.0`.
258
+
259
+ ### Docs
260
+
261
+ - [docs] Add a performance docs page for charts (#22656) @alexfauquette
262
+ - [docs] Add real dataset for maps documentation (#22599) @alexfauquette
263
+ - [docs] Add spacing between selects on charts overview demo (#22589) @bernardobelchior
264
+ - [docs] Reorganize existing chat docs navigation (#22478) @hasdfa
265
+ - [docs] Switch to visionscarto's world atlas dataset (#22669) @cherniavskii
266
+ - [docs] Update TreeView `domstructure` docs and add demo (#22420) @mj12albert
267
+ - [docs] Fix indexation of Scheduler (#22567) @oliviertassinari
268
+ - [docs] Fix wide layout on event timeline lazy loading and Import title (#22604) @rita-codes
269
+ - [docs] Derive class name owners for shared charts classes (#22674) @JCQuintas
270
+
271
+ ### Core
272
+
273
+ - [code-infra] Drop unused and now-transitive deps from docs/package.json (#22549) @LukasTy
274
+ - [code-infra] Refresh CI Node pins to 22.22.3 (#22598) @LukasTy
275
+ - [code-infra] Skip empty product sections in changelog (#22541) @rita-codes
276
+ - [code-infra] Stabilize DataGridScrollRestoration visual regression test (#22553) @Janpot
277
+ - [internal] Add license to the `x-data-grid-generator` (#22240) @arminmeh
278
+ - [internal] Express default value for resource_class (#22569) @oliviertassinari
279
+ - [internal] Fix use of ellipsis (#21852) @oliviertassinari
280
+ - [internal] `useLayoutEffect` with `ResizeObserver` (#22428) @romgrk
281
+
282
+ ### Miscellaneous
283
+
284
+ - [chat-headless] Add built-in chat adapters (#22479) @hasdfa
285
+ - [chat-headless] Harden runtime model and message errors (#22480) @hasdfa
286
+ - [core] Prepare for TypeScript 6 bump (#22551) @LukasTy
287
+ - [core] Use CircleCI Gen2 resource classes (#22610) @LukasTy
288
+ - [infra] Fix broken tag retrieval on `master` during release (#22174) @michelengelen
289
+ - [infra] Group Base UI renovate updates (#22590) @LukasTy
290
+ - [pnpm] Add security settings to pnpm-workspace.yaml (#22611) @Janpot
291
+ - [release] Fix release PR scripts (#22680) @JCQuintas
292
+ - [test] Add a Tree View regression test for lazy loading with getChildrenCount returning -1 (#22605) @mixelburg
293
+ - [test] Disable LCD subpixel antialiasing in regression screenshots (#22602) @Janpot
294
+ - [test] Fix flaky Data Grid Pro data source tree data tests (#22659) @LukasTy
295
+ - [test] Remove stale form-submit TODO from e2e suite (#22564) @LukasTy
296
+ - [x-license] Exclude test keys from the published npm package (#22647) @aemartos
297
+ - [test] Fix flaky WebGL benchmark by polling for canvas content (#22535) @JCQuintas
298
+
3
299
  ## 9.3.0
4
300
 
5
301
  _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: "MTc4MTEzNjAwMDAwMA==",
55
+ version: "9.5.0",
56
56
  name: 'x-data-grid-premium'
57
57
  };
58
58
  const watermark = /*#__PURE__*/(0, _jsxRuntime.jsx)(_internals.Watermark, {
@@ -76,14 +76,14 @@ const DataGridPremiumRaw = (0, _forwardRef.forwardRef)(function DataGridPremium(
76
76
  privateApiRef: privateApiRef,
77
77
  configuration: configuration,
78
78
  props: props,
79
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_xDataGridPro.GridRoot, (0, _extends2.default)({
79
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_xDataGridPro.GridRoot, (0, _extends2.default)({
80
80
  className: props.className,
81
81
  style: props.style,
82
82
  sx: props.sx
83
83
  }, props.slotProps?.root, {
84
84
  ref: ref,
85
85
  sidePanel: sidePanel,
86
- children: watermark
86
+ children: [watermark, /*#__PURE__*/(0, _jsxRuntime.jsx)(_internals2.GridMultiSelectMeasurer, {})]
87
87
  }))
88
88
  });
89
89
  });
@@ -5,7 +5,7 @@ import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { useLicenseVerifier, Watermark } from '@mui/x-license/internals';
7
7
  import { GridRoot, GridContextProvider, useGridSelector } from '@mui/x-data-grid-pro';
8
- import { propValidatorsDataGrid, propValidatorsDataGridPro, validateProps, useGridApiInitialization, getRowValue } from '@mui/x-data-grid-pro/internals';
8
+ import { propValidatorsDataGrid, propValidatorsDataGridPro, validateProps, useGridApiInitialization, getRowValue, GridMultiSelectMeasurer } from '@mui/x-data-grid-pro/internals';
9
9
  import { useMaterialCSSVariables } from '@mui/x-data-grid/material';
10
10
  import { forwardRef } from '@mui/x-internals/forwardRef';
11
11
  import { useDataGridPremiumComponent } from "./useDataGridPremiumComponent.mjs";
@@ -19,7 +19,7 @@ import { useGridRowsOverridableMethods } from "../hooks/features/rows/useGridRow
19
19
  import { useGridParamsOverridableMethods } from "../hooks/features/rows/useGridParamsOverridableMethods.mjs";
20
20
  import { gridSidebarOpenSelector } from "../hooks/features/sidebar/index.mjs";
21
21
  import { useIsCellEditable } from "../hooks/features/editing/useGridCellEditable.mjs";
22
- import { jsx as _jsx } from "react/jsx-runtime";
22
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
23
23
  const configuration = {
24
24
  hooks: {
25
25
  useCSSVariables: useMaterialCSSVariables,
@@ -44,8 +44,8 @@ const configuration = {
44
44
  }
45
45
  };
46
46
  const packageInfo = {
47
- releaseDate: "MTc3OTMyMTYwMDAwMA==",
48
- version: "9.3.0",
47
+ releaseDate: "MTc4MTEzNjAwMDAwMA==",
48
+ version: "9.5.0",
49
49
  name: 'x-data-grid-premium'
50
50
  };
51
51
  const watermark = /*#__PURE__*/_jsx(Watermark, {
@@ -69,14 +69,14 @@ const DataGridPremiumRaw = forwardRef(function DataGridPremium(inProps, ref) {
69
69
  privateApiRef: privateApiRef,
70
70
  configuration: configuration,
71
71
  props: props,
72
- children: /*#__PURE__*/_jsx(GridRoot, _extends({
72
+ children: /*#__PURE__*/_jsxs(GridRoot, _extends({
73
73
  className: props.className,
74
74
  style: props.style,
75
75
  sx: props.sx
76
76
  }, props.slotProps?.root, {
77
77
  ref: ref,
78
78
  sidePanel: sidePanel,
79
- children: watermark
79
+ children: [watermark, /*#__PURE__*/_jsx(GridMultiSelectMeasurer, {})]
80
80
  }))
81
81
  });
82
82
  });
@@ -28,6 +28,7 @@ var _useGridChartsIntegration = require("../hooks/features/chartsIntegration/use
28
28
  var _useGridHistory = require("../hooks/features/history/useGridHistory");
29
29
  // Premium-only features
30
30
 
31
+ (0, _internals.registerMultiSelectColumnType)();
31
32
  const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
32
33
  const pivotPropsOverrides = (0, _xDataGridPro.useGridSelector)(apiRef, _gridPivotingSelectors.gridPivotPropsOverridesSelector);
33
34
  const props = React.useMemo(() => {
@@ -135,6 +136,7 @@ const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
135
136
  (0, _internals.useGridInfiniteLoader)(apiRef, props);
136
137
  (0, _internals.useGridLazyLoader)(apiRef, props);
137
138
  (0, _internals.useGridDataSourceLazyLoader)(apiRef, props);
139
+ (0, _internals.useGridDataSourceNestedLazyLoader)(apiRef, props);
138
140
  (0, _internals.useGridInfiniteLoadingIntersection)(apiRef, props);
139
141
  (0, _internals.useGridColumnMenu)(apiRef);
140
142
  (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, registerMultiSelectColumnType } 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
@@ -20,6 +20,7 @@ import { useGridAiAssistant, aiAssistantStateInitializer } from "../hooks/featur
20
20
  import { useGridSidebar, sidebarStateInitializer } from "../hooks/features/sidebar/useGridSidebar.mjs";
21
21
  import { chartsIntegrationStateInitializer, useGridChartsIntegration } from "../hooks/features/chartsIntegration/useGridChartsIntegration.mjs";
22
22
  import { historyStateInitializer, useGridHistory } from "../hooks/features/history/useGridHistory.mjs";
23
+ registerMultiSelectColumnType();
23
24
  export const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
24
25
  const pivotPropsOverrides = useGridSelector(apiRef, gridPivotPropsOverridesSelector);
25
26
  const props = React.useMemo(() => {
@@ -127,6 +128,7 @@ export const useDataGridPremiumComponent = (apiRef, inProps, configuration) => {
127
128
  useGridInfiniteLoader(apiRef, props);
128
129
  useGridLazyLoader(apiRef, props);
129
130
  useGridDataSourceLazyLoader(apiRef, props);
131
+ useGridDataSourceNestedLazyLoader(apiRef, props);
130
132
  useGridInfiniteLoadingIntersection(apiRef, props);
131
133
  useGridColumnMenu(apiRef);
132
134
  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, {
@@ -155,7 +155,8 @@ function GridPivotPanelBody({
155
155
  if (pivotModelFields.has(field)) {
156
156
  return false;
157
157
  }
158
- if (initialColumns.get(field)?.pivotable === false) {
158
+ const column = initialColumns.get(field);
159
+ if (column?.pivotable === false || column?.type === 'multiSelect') {
159
160
  return false;
160
161
  }
161
162
  if (searchValue) {
@@ -148,7 +148,8 @@ function GridPivotPanelBody({
148
148
  if (pivotModelFields.has(field)) {
149
149
  return false;
150
150
  }
151
- if (initialColumns.get(field)?.pivotable === false) {
151
+ const column = initialColumns.get(field);
152
+ if (column?.pivotable === false || column?.type === 'multiSelect') {
152
153
  return false;
153
154
  }
154
155
  if (searchValue) {
@@ -102,13 +102,22 @@ const getGroupAggregatedValue = (groupId, apiRef, aggregationRowsScope, aggregat
102
102
  aggregatedValues
103
103
  };
104
104
  };
105
- const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position) => {
105
+ const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position, aggregationRules, columnsLookup) => {
106
106
  const groupAggregationLookup = {};
107
+ const rowLookup = (0, _xDataGridPro.gridRowsLookupSelector)(apiRef);
107
108
  for (let j = 0; j < aggregatedFields.length; j += 1) {
108
109
  const aggregatedField = aggregatedFields[j];
110
+ const value = apiRef.current.resolveGroupAggregation?.(groupId, aggregatedField) ?? '';
111
+ const aggregationFunction = aggregationRules[aggregatedField]?.aggregationFunction;
112
+ const rowForFormatter = rowLookup[groupId] || {
113
+ id: groupId,
114
+ [aggregatedField]: value
115
+ };
116
+ const formattedValue = aggregationFunction?.valueFormatter ? aggregationFunction.valueFormatter(value, rowForFormatter, columnsLookup[aggregatedField], apiRef) : undefined;
109
117
  groupAggregationLookup[aggregatedField] = {
110
118
  position,
111
- value: apiRef.current.resolveGroupAggregation?.(groupId, aggregatedField) ?? ''
119
+ value,
120
+ formattedValue
112
121
  };
113
122
  }
114
123
  return groupAggregationLookup;
@@ -154,7 +163,7 @@ const createAggregationLookup = ({
154
163
  const position = getAggregationPosition(groupNode);
155
164
  if (isDataSource) {
156
165
  if (position !== null) {
157
- aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position);
166
+ aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position, aggregationRules, columnsLookup);
158
167
  }
159
168
  } else if (groupNode.children.length) {
160
169
  const result = getGroupAggregatedValue(groupNode.id, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, apiRef.current, groupAggregatedValuesLookup, columnsLookup);
@@ -95,13 +95,22 @@ const getGroupAggregatedValue = (groupId, apiRef, aggregationRowsScope, aggregat
95
95
  aggregatedValues
96
96
  };
97
97
  };
98
- const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position) => {
98
+ const getGroupAggregatedValueDataSource = (groupId, apiRef, aggregatedFields, position, aggregationRules, columnsLookup) => {
99
99
  const groupAggregationLookup = {};
100
+ const rowLookup = gridRowsLookupSelector(apiRef);
100
101
  for (let j = 0; j < aggregatedFields.length; j += 1) {
101
102
  const aggregatedField = aggregatedFields[j];
103
+ const value = apiRef.current.resolveGroupAggregation?.(groupId, aggregatedField) ?? '';
104
+ const aggregationFunction = aggregationRules[aggregatedField]?.aggregationFunction;
105
+ const rowForFormatter = rowLookup[groupId] || {
106
+ id: groupId,
107
+ [aggregatedField]: value
108
+ };
109
+ const formattedValue = aggregationFunction?.valueFormatter ? aggregationFunction.valueFormatter(value, rowForFormatter, columnsLookup[aggregatedField], apiRef) : undefined;
102
110
  groupAggregationLookup[aggregatedField] = {
103
111
  position,
104
- value: apiRef.current.resolveGroupAggregation?.(groupId, aggregatedField) ?? ''
112
+ value,
113
+ formattedValue
105
114
  };
106
115
  }
107
116
  return groupAggregationLookup;
@@ -147,7 +156,7 @@ export const createAggregationLookup = ({
147
156
  const position = getAggregationPosition(groupNode);
148
157
  if (isDataSource) {
149
158
  if (position !== null) {
150
- aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position);
159
+ aggregationLookup[groupNode.id] = getGroupAggregatedValueDataSource(groupNode.id, apiRef, aggregatedFields, position, aggregationRules, columnsLookup);
151
160
  }
152
161
  } else if (groupNode.children.length) {
153
162
  const result = getGroupAggregatedValue(groupNode.id, apiRef, aggregationRowsScope, aggregatedFields, aggregationRules, position, applySorting, valueGetters, apiRef.current, groupAggregatedValuesLookup, columnsLookup);
@@ -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);
@@ -91,8 +91,8 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
91
91
  const rowNode = (0, _xDataGridPro.gridRowNodeSelector)(apiRef, rowId);
92
92
  if (rowNode?.type === 'group') {
93
93
  const originalColDef = rowNode.groupingField ? columnsLookup[rowNode.groupingField] : null;
94
- if (originalColDef?.type === 'singleSelect') {
95
- // the default valueFormatter of a singleSelect colDef won't work with the grouping column values
94
+ if (originalColDef?.type === 'singleSelect' || originalColDef?.type === 'multiSelect') {
95
+ // the default valueFormatter of singleSelect/multiSelect colDef won't work with the grouping column values
96
96
  return value;
97
97
  }
98
98
  const columnValueFormatter = originalColDef?.valueFormatter;
@@ -102,6 +102,9 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
102
102
  }
103
103
  return value;
104
104
  };
105
+ } else if (groupedByColDef.type === 'multiSelect') {
106
+ // The default valueFormatter of multiSelect expects an array; the grouping key is a string.
107
+ valueFormatter = undefined;
105
108
  } else {
106
109
  valueFormatter = groupedByColDef.valueFormatter ? groupedByColValueFormatter(groupedByColDef) : undefined;
107
110
  }
@@ -84,8 +84,8 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
84
84
  const rowNode = gridRowNodeSelector(apiRef, rowId);
85
85
  if (rowNode?.type === 'group') {
86
86
  const originalColDef = rowNode.groupingField ? columnsLookup[rowNode.groupingField] : null;
87
- if (originalColDef?.type === 'singleSelect') {
88
- // the default valueFormatter of a singleSelect colDef won't work with the grouping column values
87
+ if (originalColDef?.type === 'singleSelect' || originalColDef?.type === 'multiSelect') {
88
+ // the default valueFormatter of singleSelect/multiSelect colDef won't work with the grouping column values
89
89
  return value;
90
90
  }
91
91
  const columnValueFormatter = originalColDef?.valueFormatter;
@@ -95,6 +95,9 @@ function getGroupingCriteriaProperties(groupedByColDef, rowGroupingColumnMode, r
95
95
  }
96
96
  return value;
97
97
  };
98
+ } else if (groupedByColDef.type === 'multiSelect') {
99
+ // The default valueFormatter of multiSelect expects an array; the grouping key is a string.
100
+ valueFormatter = undefined;
98
101
  } else {
99
102
  valueFormatter = groupedByColDef.valueFormatter ? groupedByColValueFormatter(groupedByColDef) : undefined;
100
103
  }
@@ -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.d.mts CHANGED
@@ -8,6 +8,7 @@ export * from '@mui/x-data-grid/models';
8
8
  export * from '@mui/x-data-grid-pro/models';
9
9
  export * from '@mui/x-data-grid/context';
10
10
  export * from '@mui/x-data-grid/colDef';
11
+ export * from '@mui/x-data-grid-pro/colDef';
11
12
  export * from '@mui/x-data-grid/utils';
12
13
  export * from '@mui/x-data-grid-pro/utils';
13
14
  export * from "./DataGridPremium/index.mjs";
package/index.d.ts CHANGED
@@ -8,6 +8,7 @@ export * from '@mui/x-data-grid/models';
8
8
  export * from '@mui/x-data-grid-pro/models';
9
9
  export * from '@mui/x-data-grid/context';
10
10
  export * from '@mui/x-data-grid/colDef';
11
+ export * from '@mui/x-data-grid-pro/colDef';
11
12
  export * from '@mui/x-data-grid/utils';
12
13
  export * from '@mui/x-data-grid-pro/utils';
13
14
  export * from "./DataGridPremium/index.js";
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.5.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
@@ -184,6 +184,18 @@ Object.keys(_colDef).forEach(function (key) {
184
184
  }
185
185
  });
186
186
  });
187
+ var _colDef2 = require("@mui/x-data-grid-pro/colDef");
188
+ Object.keys(_colDef2).forEach(function (key) {
189
+ if (key === "default" || key === "__esModule") return;
190
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
191
+ if (key in exports && exports[key] === _colDef2[key]) return;
192
+ Object.defineProperty(exports, key, {
193
+ enumerable: true,
194
+ get: function () {
195
+ return _colDef2[key];
196
+ }
197
+ });
198
+ });
187
199
  var _utils = require("@mui/x-data-grid/utils");
188
200
  Object.keys(_utils).forEach(function (key) {
189
201
  if (key === "default" || key === "__esModule") return;
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.5.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
@@ -15,6 +15,7 @@ export * from '@mui/x-data-grid/models';
15
15
  export * from '@mui/x-data-grid-pro/models';
16
16
  export * from '@mui/x-data-grid/context';
17
17
  export * from '@mui/x-data-grid/colDef';
18
+ export * from '@mui/x-data-grid-pro/colDef';
18
19
  export * from '@mui/x-data-grid/utils';
19
20
  export * from '@mui/x-data-grid-pro/utils';
20
21
  export * from "./DataGridPremium/index.mjs";
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.5.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",
43
41
  "@mui/x-internals": "^9.1.0",
44
- "@mui/x-license": "^9.2.0"
42
+ "@mui/x-license": "^9.4.0",
43
+ "@mui/x-data-grid-pro": "^9.5.0",
44
+ "@mui/x-data-grid": "^9.5.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": {