@mui/x-data-grid 9.12.0 → 9.14.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 (92) hide show
  1. package/CHANGELOG.md +301 -0
  2. package/DataGrid/DataGrid.js +1 -1
  3. package/DataGrid/DataGrid.mjs +1 -1
  4. package/components/GridPagination.js +1 -1
  5. package/components/GridPagination.mjs +1 -1
  6. package/components/GridRow.d.mts +1 -0
  7. package/components/GridRow.d.ts +1 -0
  8. package/components/GridRow.js +41 -6
  9. package/components/GridRow.mjs +41 -6
  10. package/components/GridScrollArea.js +20 -7
  11. package/components/GridScrollArea.mjs +21 -8
  12. package/components/base/GridOverlays.js +6 -5
  13. package/components/base/GridOverlays.mjs +6 -5
  14. package/components/cell/GridActionsCell.js +53 -50
  15. package/components/cell/GridActionsCell.mjs +53 -50
  16. package/components/cell/GridActionsCellItem.js +0 -1
  17. package/components/cell/GridActionsCellItem.mjs +0 -1
  18. package/components/cell/GridCell.js +15 -4
  19. package/components/cell/GridCell.mjs +15 -4
  20. package/components/cell/GridEditBooleanCell.d.mts +1 -1
  21. package/components/cell/GridEditBooleanCell.d.ts +1 -1
  22. package/components/cell/GridEditBooleanCell.js +4 -4
  23. package/components/cell/GridEditBooleanCell.mjs +4 -4
  24. package/components/cell/GridEditDateCell.d.mts +1 -1
  25. package/components/cell/GridEditDateCell.d.ts +1 -1
  26. package/components/cell/GridEditDateCell.js +5 -5
  27. package/components/cell/GridEditDateCell.mjs +5 -5
  28. package/components/cell/GridEditInputCell.d.mts +1 -1
  29. package/components/cell/GridEditInputCell.d.ts +1 -1
  30. package/components/cell/GridEditInputCell.js +1 -1
  31. package/components/cell/GridEditInputCell.mjs +1 -1
  32. package/components/cell/GridEditLongTextCell.d.mts +1 -1
  33. package/components/cell/GridEditLongTextCell.d.ts +1 -1
  34. package/components/cell/GridEditLongTextCell.js +2 -2
  35. package/components/cell/GridEditLongTextCell.mjs +2 -2
  36. package/components/cell/GridEditSingleSelectCell.d.mts +1 -1
  37. package/components/cell/GridEditSingleSelectCell.d.ts +1 -1
  38. package/components/cell/GridEditSingleSelectCell.js +4 -4
  39. package/components/cell/GridEditSingleSelectCell.mjs +4 -4
  40. package/components/quickFilter/QuickFilter.js +7 -2
  41. package/components/quickFilter/QuickFilter.mjs +7 -2
  42. package/components/toolbarV8/Toolbar.d.mts +5 -1
  43. package/components/toolbarV8/Toolbar.d.ts +5 -1
  44. package/components/toolbarV8/Toolbar.js +34 -12
  45. package/components/toolbarV8/Toolbar.mjs +33 -11
  46. package/components/virtualization/GridVirtualScroller.js +3 -0
  47. package/components/virtualization/GridVirtualScroller.mjs +3 -0
  48. package/hooks/core/useGridVirtualizer.js +14 -1
  49. package/hooks/core/useGridVirtualizer.mjs +14 -1
  50. package/hooks/features/columnResize/useGridColumnResize.js +4 -1
  51. package/hooks/features/columnResize/useGridColumnResize.mjs +4 -1
  52. package/hooks/features/dataSource/models.d.mts +2 -2
  53. package/hooks/features/dataSource/models.d.ts +2 -2
  54. package/hooks/features/dataSource/useGridDataSourceBase.js +12 -8
  55. package/hooks/features/dataSource/useGridDataSourceBase.mjs +13 -9
  56. package/hooks/features/pivoting/gridPivotingInterfaces.d.mts +2 -2
  57. package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +2 -2
  58. package/hooks/features/rowSelection/useGridRowSelection.d.mts +1 -1
  59. package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
  60. package/hooks/features/rowSelection/useGridRowSelection.js +51 -10
  61. package/hooks/features/rowSelection/useGridRowSelection.mjs +53 -12
  62. package/hooks/features/rowSelection/utils.js +5 -0
  63. package/hooks/features/rowSelection/utils.mjs +5 -0
  64. package/hooks/features/rows/gridRowsUtils.d.mts +37 -3
  65. package/hooks/features/rows/gridRowsUtils.d.ts +37 -3
  66. package/hooks/features/rows/gridRowsUtils.js +120 -23
  67. package/hooks/features/rows/gridRowsUtils.mjs +115 -22
  68. package/hooks/features/rows/useGridRows.js +10 -1
  69. package/hooks/features/rows/useGridRows.mjs +10 -1
  70. package/index.js +1 -1
  71. package/index.mjs +1 -1
  72. package/internals/index.d.mts +2 -2
  73. package/internals/index.d.ts +2 -2
  74. package/internals/index.js +28 -0
  75. package/internals/index.mjs +2 -2
  76. package/material/variables.d.mts +6 -1
  77. package/material/variables.d.ts +6 -1
  78. package/material/variables.js +17 -3
  79. package/material/variables.mjs +14 -4
  80. package/models/api/gridRowApi.d.mts +7 -7
  81. package/models/api/gridRowApi.d.ts +7 -7
  82. package/models/gridDataSource.d.mts +3 -0
  83. package/models/gridDataSource.d.ts +3 -0
  84. package/models/gridRows.d.mts +28 -1
  85. package/models/gridRows.d.ts +28 -1
  86. package/models/props/DataGridProps.d.mts +3 -3
  87. package/models/props/DataGridProps.d.ts +3 -3
  88. package/package.json +6 -6
  89. package/utils/keyboardUtils.d.mts +1 -0
  90. package/utils/keyboardUtils.d.ts +1 -0
  91. package/utils/keyboardUtils.js +6 -0
  92. package/utils/keyboardUtils.mjs +5 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,306 @@
1
1
  # Changelog
2
2
 
3
+ ## 9.14.0
4
+
5
+ _Sep 17, 2026_
6
+
7
+ We'd like to extend a big thank you to the 16 contributors who made this release possible. Here are some highlights ✨:
8
+
9
+ - 🌍 Add Hebrew (he-IL) locale to the Scheduler
10
+ - 📅 Scheduler time grid now opens at 7 AM by default, configurable with the new `initialScrollTime` prop
11
+ - 🗓️ Auto-scheduling engine for finish-to-start dependencies in the Premium Event Timeline
12
+ - 🧩 New content slots for the Event Timeline event block and resource title cell
13
+ - ♿️ Charts announce the visible zoom range to screen readers
14
+ - 🐞 Bugfixes
15
+ - 📚 Documentation improvements
16
+
17
+ Special thanks go out to these community members for their valuable contributions:
18
+ @eterry1388, @jamesDin, @kareem-ib, @mateuseap, @mustafajw07
19
+
20
+ The following team members contributed to this release:
21
+ @arminmeh, @bernardobelchior, @brijeshb42, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @MBilalShafi, @michelengelen, @noraleonte, @rita-codes
22
+
23
+ ### Data Grid
24
+
25
+ #### `@mui/x-data-grid@9.14.0`
26
+
27
+ - [DataGrid] Do not crash on unmount when the document has no body (#23431) @eterry1388
28
+ - [DataGrid] Fix `MissingRowIdError` on cell `mousedown`/`mouseup` after row removal (#23261) @kareem-ib
29
+ - [DataGrid] Fix quick filter dropping a pending search on parser identity change (#23575) @michelengelen
30
+ - [DataGrid] Keep overlays sticky in RTL mode (#23492) @arminmeh
31
+ - [DataGrid] Prevent scroll area state update before mount (#23478) @michelengelen
32
+ - [DataGrid] Remove `'menu'` role from the actions cell (#23437) @michelengelen
33
+
34
+ #### `@mui/x-data-grid-pro@9.14.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
35
+
36
+ Same changes as in `@mui/x-data-grid@9.14.0`, plus:
37
+
38
+ - [DataGridPro] Fix data integrity issue in nested server data (#23518) @MBilalShafi
39
+ - [DataGridPro] Keep parent selection when lazily loaded children arrive (#23421) @michelengelen
40
+
41
+ #### `@mui/x-data-grid-premium@9.14.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
42
+
43
+ Same changes as in `@mui/x-data-grid-pro@9.14.0`.
44
+
45
+ ### Date and Time Pickers
46
+
47
+ #### `@mui/x-date-pickers@9.14.0`
48
+
49
+ Internal changes.
50
+
51
+ #### `@mui/x-date-pickers-pro@9.14.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
52
+
53
+ Same changes as in `@mui/x-date-pickers@9.14.0`.
54
+
55
+ ### Charts
56
+
57
+ #### `@mui/x-charts@9.14.0`
58
+
59
+ - [charts] Announce the visible zoom range to screen readers (#23371) @JCQuintas
60
+ - [charts] Fix Premium chart zoom props and `apiRef` forwarding (#23590) @bernardobelchior
61
+
62
+ #### `@mui/x-charts-pro@9.14.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
63
+
64
+ Same changes as in `@mui/x-charts@9.14.0`.
65
+
66
+ #### `@mui/x-charts-premium@9.14.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
67
+
68
+ Same changes as in `@mui/x-charts-pro@9.14.0`, plus:
69
+
70
+ - [charts-premium] Add the Excel data extraction layer (#23569) @JCQuintas
71
+ - [charts-premium] Forward `apiRef` on `RadialBarChart` and `RadialLineChart` (#23625) @JCQuintas
72
+
73
+ ### Tree View
74
+
75
+ #### `@mui/x-tree-view@9.14.0`
76
+
77
+ - [tree view] Optimize lazy loading store writes for nested children (#23489) @noraleonte
78
+ - [tree view] Prune stale children when replacing an item's children (#23598) @JCQuintas
79
+
80
+ #### `@mui/x-tree-view-pro@9.14.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
81
+
82
+ Same changes as in `@mui/x-tree-view@9.14.0`.
83
+
84
+ ### Scheduler
85
+
86
+ #### Breaking changes
87
+
88
+ - The `dataSource` prop has been removed from the Community Event Calendar components:
89
+ `EventCalendar`, `StandaloneDayView`, `StandaloneWeekView`, `StandaloneMonthView`,
90
+ `StandaloneAgendaView`, `StandaloneCompactDayView`, `StandaloneCompactThreeDayView` and
91
+ `StandaloneCompactWeekView`.
92
+
93
+ Lazy loading has always been Premium-only, and the prop never had any effect on these
94
+ components: it left the calendar in a permanent loading state. To load events through a data
95
+ source, use `EventCalendarPremium` (or the Premium standalone views) and `EventTimelinePremium`,
96
+ where `dataSource` is unchanged.
97
+
98
+ ```diff
99
+ -import { EventCalendar } from '@mui/x-scheduler/event-calendar';
100
+ +import { EventCalendarPremium } from '@mui/x-scheduler-premium/event-calendar-premium';
101
+
102
+ -<EventCalendar dataSource={dataSource} />
103
+ +<EventCalendarPremium dataSource={dataSource} />
104
+ ```
105
+
106
+ #### `@mui/x-scheduler@9.0.0-beta.12`
107
+
108
+ - [l10n] Add Hebrew (he-IL) locale (#23577) @jamesDin
109
+ - [scheduler] Add content slots for the Event Timeline event block and resource title cell (#23557) @rita-codes
110
+ - [scheduler] Fix `onPreferencesChange` never being called on `EventCalendar` (#23568) @rita-codes
111
+ - [scheduler] Fix flaky timeline observer absorb (#23523) @JCQuintas
112
+ - [scheduler] Open the time grid at 7 AM by default and add `initialScrollTime` (#23594) @rita-codes
113
+ - [scheduler] Pin sibling scheduler packages to exact versions (#23574) @rita-codes
114
+ - [scheduler] Read form initialization settings without subscriptions (#23614) @flaviendelangle
115
+ - [scheduler] Remove `dataSource` from the Community components (#23483) @mustafajw07
116
+ - [scheduler] Remove redundant recurrence subscriptions (#23610) @flaviendelangle
117
+ - [scheduler] Remove unused more-events popover count (#23619) @flaviendelangle
118
+ - [scheduler] Remove unused refs (#23616) @flaviendelangle
119
+ - [scheduler] Reuse precomputed timeline duration (#23620) @flaviendelangle
120
+ - [scheduler] Reuse recurrence option labels (#23609) @flaviendelangle
121
+ - [scheduler] Reuse recurrence presets for form drafts (#23615) @flaviendelangle
122
+ - [scheduler] Simplify month-view overflow counting (#23617) @flaviendelangle
123
+ - [scheduler] Use form store state to guard submissions (#23613) @flaviendelangle
124
+
125
+ #### `@mui/x-scheduler-premium@9.0.0-beta.12` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
126
+
127
+ Same changes as in `@mui/x-scheduler@9.0.0-beta.12`, plus:
128
+
129
+ - [scheduler-premium] Dependencies - Arrows and terminals for SS, FF and SF (#23524) @rita-codes
130
+ - [scheduler-premium] Dependencies - Auto-scheduling engine (FS) (#23439) @rita-codes
131
+
132
+ ### Docs
133
+
134
+ - [DataGrid][docs] Fix "Apply filters on demand" demo (#23602) @mateuseap
135
+ - [docs] Add recipe for getting the tree view's root DOM element via `ref` (#22941) @michelengelen
136
+ - [docs][pickers] Mention `Moment.js` maintenance mode (#23601) @mateuseap
137
+
138
+ ### Core
139
+
140
+ - [code-infra] Gate the `DataGridScrollRestoration` screenshot on the horizontal restore (#23527) @JCQuintas
141
+ - [code-infra] Let the `NoColumnsOverlay` demo settle before screenshotting (#23529) @JCQuintas
142
+ - [code-infra] Pin the only-allow version in the preinstall hook (#23551) @Janpot
143
+ - [code-infra] Remove disabled Discord release announcement workflow (#23554) @Janpot
144
+ - [code-infra] Trial: Claude CI flake-fix caller (#23556) @Janpot
145
+
146
+ ### Miscellaneous
147
+
148
+ - [chat] Add feedback form to the docs (#23403) @hasdfa
149
+ - [ci] Grant actions: read to the flake-fix caller (#23560) @Janpot
150
+ - [ci] Update flake-fix caller to mui-public#1849 (#23571) @Janpot
151
+
152
+ ## 9.13.0
153
+
154
+ <!-- generated comparing v9.12.0..master -->
155
+
156
+ _Sep 4, 2026_
157
+
158
+ We'd like to extend a big thank you to the 14 contributors who made this release possible. Here are some highlights ✨:
159
+
160
+ - 🦮 Improve keyboard navigation features of the Charts.
161
+ - 🎨 Improved customization of the edit event dialog in the `EventCalendar`
162
+ - 🐞 Bugfixes
163
+ - 📚 Documentation improvements
164
+
165
+ Special thanks go out to these community members for their valuable contributions:
166
+ @Anexus5919, @jvskriubakken, @mustafajw07, @roychan1
167
+
168
+ The following team members contributed to this release:
169
+ @brijeshb42, @flaviendelangle, @hasdfa, @Janpot, @JCQuintas, @LukasTy, @michelengelen, @noraleonte, @rita-codes, @silviuaavram
170
+
171
+ ### Data Grid
172
+
173
+ #### `@mui/x-data-grid@9.13.0`
174
+
175
+ - [DataGrid] Call `onValueChange` after `setEditCellValue` in edit cells (#23417) @michelengelen
176
+ - [DataGrid] Add support for replacing rows instead of merging updates (#23323) @jvskriubakken
177
+ - [DataGrid] Always render `rowHeader` in virtualized setups (#23386) @silviuaavram
178
+ - [DataGrid] Export `ToolbarRoot` (#23322) @JCQuintas
179
+ - [DataGrid] Fix `rowsPerPage` selector appearing when `autoPageSize` is enabled and `pageSize` is one of `pageSizeOptions` (#23401) @roychan1
180
+ - [DataGrid] Fix row tree reset when a data source grid becomes visible (#23288) @JCQuintas
181
+
182
+ #### `@mui/x-data-grid-pro@9.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
183
+
184
+ Same changes as in `@mui/x-data-grid@9.13.0`, plus:
185
+
186
+ - [DataGridPro] Remove rows deleted server-side on nested lazy loading revalidation (#23320) @JCQuintas
187
+ - [DataGridPro] Stop `disableDebounce` from reaching the DOM in multi select filter (#23445) @JCQuintas
188
+
189
+ #### `@mui/x-data-grid-premium@9.13.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
190
+
191
+ Same changes as in `@mui/x-data-grid-pro@9.13.0`, plus:
192
+
193
+ - [DataGridPremium] Refine cell selection and speed up clipboard copy (#23473) @michelengelen
194
+ - [DataGridPremium] Select all cells with Ctrl+A (#23415) @michelengelen
195
+
196
+ ### Date and Time Pickers
197
+
198
+ #### `@mui/x-date-pickers@9.13.0`
199
+
200
+ Internal changes.
201
+
202
+ #### `@mui/x-date-pickers-pro@9.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
203
+
204
+ Same changes as in `@mui/x-date-pickers@9.13.0`.
205
+
206
+ ### Charts
207
+
208
+ #### `@mui/x-charts@9.13.0`
209
+
210
+ - [charts] Activate the focused axis with Enter/Space (#23219) @JCQuintas
211
+ - [charts] Add keyboard zoom and pan (#23369) @JCQuintas
212
+ - [charts] Fix line mark position under browser zoom in Safari (#23387) @noraleonte
213
+ - [charts] Fix y axis tick labels shortened near the top of the chart (#23435) @JCQuintas
214
+ - [charts] Focus the clicked item on radar charts (#23287) @JCQuintas
215
+ - [charts] Stop text measurements leaking into each other (#23430) @JCQuintas
216
+
217
+ #### `@mui/x-charts-pro@9.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
218
+
219
+ Same changes as in `@mui/x-charts@9.13.0`.
220
+
221
+ #### `@mui/x-charts-premium@9.13.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
222
+
223
+ Same changes as in `@mui/x-charts-pro@9.13.0`.
224
+
225
+ ### Tree View
226
+
227
+ #### `@mui/x-tree-view@9.13.0`
228
+
229
+ - [tree view] Add `loading` prop and customizable loading UI (#22251) @michelengelen
230
+ - [tree view] Reduce selector bundle size (#23412) @flaviendelangle
231
+ - [tree view] Remove dead UI from community component (#23487) @noraleonte
232
+ - [tree view] Remove unused dependencies (#23488) @noraleonte
233
+ - [tree view] Use `useId` for the default tree id (#23341) @Anexus5919
234
+
235
+ #### `@mui/x-tree-view-pro@9.13.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
236
+
237
+ Same changes as in `@mui/x-tree-view@9.13.0`.
238
+
239
+ ### Scheduler
240
+
241
+ #### `@mui/x-scheduler@9.0.0-beta.11`
242
+
243
+ - [scheduler] Absorb un-acted `ResizeObserver` deliveries after rendering the timeline (#23444) @rita-codes
244
+ - [scheduler] Add `EventContextMenu` with Edit and Delete actions (#23379) @mustafajw07
245
+ - [scheduler] Add aria-hidden to collapsed side panel and refactor landmark structure (#23425) @mustafajw07
246
+ - [scheduler] Add the `eventDialogGeneralTab` slot (#23338) @rita-codes
247
+ - [scheduler] Fix the un-awaited act warning in the event dialog slot test (#23446) @JCQuintas
248
+ - [scheduler] Improve timeline event layout performance (#23364) @flaviendelangle
249
+ - [scheduler] Keep `aria-expanded` present when ViewSwitcher and PreferencesMenu menus are closed (#23427) @mustafajw07
250
+ - [scheduler] Make the event dialog General-tab building blocks public (#23398) @rita-codes
251
+ - [scheduler] Migrate to the pragmatic-drag-and-drop v3 entry points (#23442) @rita-codes
252
+ - [scheduler] Reduce selector bundle size (#23413) @flaviendelangle
253
+ - [scheduler] Reuse processed events between updates (#23363) @flaviendelangle
254
+ - [scheduler] Add `aria-expanded` and `aria-controls` to side panel toggle button (#23402) @mustafajw07
255
+
256
+ #### `@mui/x-scheduler-premium@9.0.0-beta.11` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
257
+
258
+ Same changes as in `@mui/x-scheduler@9.0.0-beta.11`, plus:
259
+
260
+ - [scheduler-premium] Dependencies - Keep event drags working over the arrow hit-areas (#23441) @rita-codes
261
+ - [scheduler-premium] Dependencies - Reject dependencies that would create a cycle (#23389) @rita-codes
262
+ - [scheduler-premium] Key recurring `exDates` on their data-timezone day (#23467) @rita-codes
263
+
264
+ ### Codemod
265
+
266
+ #### `@mui/x-codemod@9.13.0`
267
+
268
+ Internal changes.
269
+
270
+ ### Docs
271
+
272
+ - [docs] Add synchronized tooltip and crosshair demo to charts (#23368) @JCQuintas
273
+ - [docs] Add sticky headers recipe to `RichTreeView` customization (#22908) @michelengelen
274
+ - [docs] Pin the visible date of the scheduler preferences demos (#23432) @rita-codes
275
+ - [docs] Star-prefix bare :where() dark-mode selectors (#23419) @Janpot
276
+ - [docs] Consolidate demo data into shared dataset files (#23496) @michelengelen
277
+
278
+ ### Core
279
+
280
+ - [code-infra] Consume shared commands from code-infra orb (#23485) @brijeshb42
281
+ - [code-infra] Move the shared spy helpers off Sinon (#23466) @JCQuintas
282
+ - [code-infra] Point the support validator link at frontend-public (#23422) @Janpot
283
+ - [code-infra] Reduce per-page memory in the browser test suite (#23424) @Janpot
284
+ - [code-infra] Remove Sinon (#23476) @JCQuintas
285
+ - [code-infra] Remove the explicit `styled-components` dependency (#23479) @LukasTy
286
+ - [code-infra] Replace the mechanical sinon `spy()` usages with `vi.fn()` (#23443) @JCQuintas
287
+ - [code-infra] Replace the sinon `spy(fn)` usages with `vi.fn(fn)` (#23460) @JCQuintas
288
+ - [code-infra] Replace the sinon spy types with the Vitest ones (#23464) @JCQuintas
289
+ - [code-infra] Replace the sinon spy-on-object calls with `vi.spyOn` (#23474) @JCQuintas
290
+ - [code-infra] Replace the sinon stubs with Vitest mocks (#23472) @JCQuintas
291
+ - [code-infra] Run TypeScript 7 alongside the TS6 JS API (#23471) @brijeshb42
292
+ - [code-infra] Trim the shared browser test setup graph (#23426) @LukasTy
293
+ - [code-infra] Update CircleCI orb (#23418) @JCQuintas
294
+ - [code-infra] Use explicit vitest imports in test files (#23375) @michelengelen
295
+
296
+ ### Miscellaneous
297
+
298
+ - [chat] Enforce top-level type imports (#23037) @Janpot
299
+ - [chat] Fix global preload error from the `remend` import (#23263) @hasdfa
300
+ - [ci] Add Claude PR review via mui-public reusable workflow (#23423) @Janpot
301
+ - [telemetry] Fix get-context test leaking mock from sender test (#23447) @JCQuintas
302
+ - [test] Fail the regression run when a webfont does not load (#23376) @LukasTy
303
+
3
304
  ## 9.12.0
4
305
 
5
306
  _Aug 21, 2026_
@@ -777,7 +777,7 @@ process.env.NODE_ENV !== "production" ? DataGridRaw.propTypes /* remove-proptype
777
777
  * @param {R} newRow Row object with the new values.
778
778
  * @param {R} oldRow Row object with the old values.
779
779
  * @param {{ rowId: GridRowId }} params Additional parameters.
780
- * @returns {Promise<R> | R} The final values to update the row.
780
+ * @returns {Promise<R | GridRowModelReplace<R>> | R | GridRowModelReplace<R>} The final values to update the row, or a `{ _action: 'replace', row }` update to store `row` as the new row without merging.
781
781
  */
782
782
  processRowUpdate: _propTypes.default.func,
783
783
  /**
@@ -770,7 +770,7 @@ process.env.NODE_ENV !== "production" ? DataGridRaw.propTypes /* remove-proptype
770
770
  * @param {R} newRow Row object with the new values.
771
771
  * @param {R} oldRow Row object with the old values.
772
772
  * @param {{ rowId: GridRowId }} params Additional parameters.
773
- * @returns {Promise<R> | R} The final values to update the row.
773
+ * @returns {Promise<R | GridRowModelReplace<R>> | R | GridRowModelReplace<R>} The final values to update the row, or a `{ _action: 'replace', row }` update to store `row` as the new row without merging.
774
774
  */
775
775
  processRowUpdate: PropTypes.func,
776
776
  /**
@@ -71,7 +71,7 @@ function GridPagination() {
71
71
  warnedOnceMissingInPageSizeOptions.current = true;
72
72
  }
73
73
  }
74
- const pageSizeOptions = isPageSizeIncludedInPageSizeOptions(paginationModel.pageSize) ? rootProps.pageSizeOptions : [];
74
+ const pageSizeOptions = !rootProps.autoPageSize && isPageSizeIncludedInPageSizeOptions(paginationModel.pageSize) ? rootProps.pageSizeOptions : [];
75
75
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridPaginationRoot, (0, _extends2.default)({
76
76
  as: rootProps.slots.basePagination,
77
77
  count: rowCount ?? -1,
@@ -64,7 +64,7 @@ function GridPagination() {
64
64
  warnedOnceMissingInPageSizeOptions.current = true;
65
65
  }
66
66
  }
67
- const pageSizeOptions = isPageSizeIncludedInPageSizeOptions(paginationModel.pageSize) ? rootProps.pageSizeOptions : [];
67
+ const pageSizeOptions = !rootProps.autoPageSize && isPageSizeIncludedInPageSizeOptions(paginationModel.pageSize) ? rootProps.pageSizeOptions : [];
68
68
  return /*#__PURE__*/_jsx(GridPaginationRoot, _extends({
69
69
  as: rootProps.slots.basePagination,
70
70
  count: rowCount ?? -1,
@@ -16,6 +16,7 @@ export interface GridRowProps extends React.HTMLAttributes<HTMLDivElement> {
16
16
  columnsTotalWidth: number;
17
17
  firstColumnIndex: number;
18
18
  lastColumnIndex: number;
19
+ retainedColumnIndexes: number[];
19
20
  visibleColumns: GridStateColDef[];
20
21
  pinnedColumns: GridPinnedColumns;
21
22
  /**
@@ -16,6 +16,7 @@ export interface GridRowProps extends React.HTMLAttributes<HTMLDivElement> {
16
16
  columnsTotalWidth: number;
17
17
  firstColumnIndex: number;
18
18
  lastColumnIndex: number;
19
+ retainedColumnIndexes: number[];
19
20
  visibleColumns: GridStateColDef[];
20
21
  pinnedColumns: GridPinnedColumns;
21
22
  /**
@@ -39,7 +39,7 @@ var _useGridConfiguration = require("../hooks/utils/useGridConfiguration");
39
39
  var _useGridPrivateApiContext = require("../hooks/utils/useGridPrivateApiContext");
40
40
  var _createSelector = require("../utils/createSelector");
41
41
  var _jsxRuntime = require("react/jsx-runtime");
42
- const _excluded = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "pinnedColumns", "offsetLeft", "columnsTotalWidth", "firstColumnIndex", "lastColumnIndex", "focusedColumnIndex", "isFirstVisible", "isLastVisible", "isNotVisible", "showBottomBorder", "scrollbarWidth", "gridHasFiller", "onClick", "onDoubleClick", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver"];
42
+ const _excluded = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "pinnedColumns", "offsetLeft", "columnsTotalWidth", "firstColumnIndex", "lastColumnIndex", "retainedColumnIndexes", "focusedColumnIndex", "isFirstVisible", "isLastVisible", "isNotVisible", "showBottomBorder", "scrollbarWidth", "gridHasFiller", "onClick", "onDoubleClick", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver"];
43
43
  const isRowReorderingEnabledSelector = (0, _createSelector.createSelector)(_gridEditingSelectors.gridEditRowsStateSelector, (editRows, {
44
44
  rowReordering,
45
45
  treeData
@@ -65,6 +65,7 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
65
65
  columnsTotalWidth,
66
66
  firstColumnIndex,
67
67
  lastColumnIndex,
68
+ retainedColumnIndexes,
68
69
  focusedColumnIndex,
69
70
  isFirstVisible,
70
71
  isLastVisible,
@@ -231,7 +232,16 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
231
232
  const width = cellColSpanInfo?.cellProps.width ?? column.computedWidth;
232
233
  const colSpan = cellColSpanInfo?.cellProps.colSpan ?? 1;
233
234
  const pinnedOffset = (0, _getPinnedCellOffset.getPinnedCellOffset)(pinnedPosition, column.computedWidth, indexRelativeToAllColumns, columnPositions, columnsTotalWidth, scrollbarWidth);
235
+
236
+ // Virtual cells stay mounted for focus and accessibility relationships, but GridCell collapses
237
+ // them to zero size so they do not participate in the visible row layout.
238
+ const cellIsNotVisible = pinnedPosition === _constants.PinnedColumnPosition.VIRTUAL;
234
239
  if (rowNode.type === 'skeletonRow') {
240
+ // Skeleton cells have no value to expose and don't support the collapsed style, so a virtual
241
+ // one would only add a full-width placeholder that shifts the rest of the row.
242
+ if (cellIsNotVisible) {
243
+ return null;
244
+ }
235
245
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(slots.skeletonCell, {
236
246
  type: column.type,
237
247
  width: width,
@@ -254,7 +264,6 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
254
264
  const canReorderColumn = !(disableColumnReorder || column.disableReorder);
255
265
  const canReorderRow = isRowReorderingEnabled && !sortModel.length;
256
266
  const disableDragEvents = !(canReorderColumn || isReorderCell && canReorderRow || isRowDragActive);
257
- const cellIsNotVisible = pinnedPosition === _constants.PinnedColumnPosition.VIRTUAL;
258
267
  const showLeftBorder = (0, _cellBorderUtils.shouldCellShowLeftBorder)(pinnedPosition, indexInSection, rootProps.showCellVerticalBorder, rootProps.pinnedColumnsSectionSeparator);
259
268
  const showRightBorder = (0, _cellBorderUtils.shouldCellShowRightBorder)(pinnedPosition, indexInSection, sectionLength, rootProps.showCellVerticalBorder, gridHasFiller, rootProps.pinnedColumnsSectionSeparator);
260
269
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(slots.cell, (0, _extends2.default)({
@@ -284,9 +293,27 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
284
293
  return getCell(column, i, indexRelativeToAllColumns, pinnedColumns.right.length, _constants.PinnedColumnPosition.RIGHT);
285
294
  });
286
295
  const middleColumnsLength = visibleColumns.length - pinnedColumns.left.length - pinnedColumns.right.length;
296
+
297
+ // Build the middle section in visual column order:
298
+ // 1. retained or focused virtual cells before the render context;
299
+ // 2. the cells inside the render context;
300
+ // 3. retained or focused virtual cells after the render context.
287
301
  const cells = [];
288
- if (hasVirtualFocusCellLeft) {
289
- cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, _constants.PinnedColumnPosition.VIRTUAL));
302
+ const firstUnpinnedColumnIndex = pinnedColumns.left.length;
303
+ const lastUnpinnedColumnIndex = visibleColumns.length - pinnedColumns.right.length;
304
+
305
+ // Select retained columns before the render context. The unpinned bounds exclude retained
306
+ // columns already rendered by `leftCells` or `rightCells`.
307
+ const virtualColumnIndexesLeft = retainedColumnIndexes.filter(columnIndex => columnIndex >= firstUnpinnedColumnIndex && columnIndex < firstColumnIndex);
308
+
309
+ // The grid already retains a focused cell outside the render context. Add it to the same ordered
310
+ // list, unless the column is a retained row header and is therefore already present.
311
+ if (hasVirtualFocusCellLeft && !virtualColumnIndexesLeft.includes(focusedColumnIndex)) {
312
+ virtualColumnIndexesLeft.push(focusedColumnIndex);
313
+ virtualColumnIndexesLeft.sort((a, b) => a - b);
314
+ }
315
+ for (const columnIndex of virtualColumnIndexesLeft) {
316
+ cells.push(getCell(visibleColumns[columnIndex], columnIndex - pinnedColumns.left.length, columnIndex, middleColumnsLength, _constants.PinnedColumnPosition.VIRTUAL));
290
317
  }
291
318
  for (let i = firstColumnIndex; i < lastColumnIndex; i += 1) {
292
319
  const column = visibleColumns[i];
@@ -296,8 +323,15 @@ const GridRow = (0, _forwardRef.forwardRef)(function GridRow(props, refProp) {
296
323
  }
297
324
  cells.push(getCell(column, indexInSection, i, middleColumnsLength));
298
325
  }
299
- if (hasVirtualFocusCellRight) {
300
- cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, _constants.PinnedColumnPosition.VIRTUAL));
326
+
327
+ // Repeat the retention step for unpinned columns after the render context.
328
+ const virtualColumnIndexesRight = retainedColumnIndexes.filter(columnIndex => columnIndex >= lastColumnIndex && columnIndex < lastUnpinnedColumnIndex);
329
+ if (hasVirtualFocusCellRight && !virtualColumnIndexesRight.includes(focusedColumnIndex)) {
330
+ virtualColumnIndexesRight.push(focusedColumnIndex);
331
+ virtualColumnIndexesRight.sort((a, b) => a - b);
332
+ }
333
+ for (const columnIndex of virtualColumnIndexesRight) {
334
+ cells.push(getCell(visibleColumns[columnIndex], columnIndex - pinnedColumns.left.length, columnIndex, middleColumnsLength, _constants.PinnedColumnPosition.VIRTUAL));
301
335
  }
302
336
  const eventHandlers = row ? {
303
337
  onClick: publishClick,
@@ -358,6 +392,7 @@ process.env.NODE_ENV !== "production" ? GridRow.propTypes /* remove-proptypes */
358
392
  onMouseEnter: _propTypes.default.func,
359
393
  onMouseLeave: _propTypes.default.func,
360
394
  pinnedColumns: _propTypes.default.object.isRequired,
395
+ retainedColumnIndexes: _propTypes.default.arrayOf(_propTypes.default.number).isRequired,
361
396
  row: _propTypes.default.object.isRequired,
362
397
  rowHeight: _propTypes.default.oneOfType([_propTypes.default.oneOf(['auto']), _propTypes.default.number]).isRequired,
363
398
  rowId: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]).isRequired,
@@ -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 = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "pinnedColumns", "offsetLeft", "columnsTotalWidth", "firstColumnIndex", "lastColumnIndex", "focusedColumnIndex", "isFirstVisible", "isLastVisible", "isNotVisible", "showBottomBorder", "scrollbarWidth", "gridHasFiller", "onClick", "onDoubleClick", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver"];
5
+ const _excluded = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "pinnedColumns", "offsetLeft", "columnsTotalWidth", "firstColumnIndex", "lastColumnIndex", "retainedColumnIndexes", "focusedColumnIndex", "isFirstVisible", "isLastVisible", "isNotVisible", "showBottomBorder", "scrollbarWidth", "gridHasFiller", "onClick", "onDoubleClick", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver"];
6
6
  import * as React from 'react';
7
7
  import PropTypes from 'prop-types';
8
8
  import clsx from 'clsx';
@@ -58,6 +58,7 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
58
58
  columnsTotalWidth,
59
59
  firstColumnIndex,
60
60
  lastColumnIndex,
61
+ retainedColumnIndexes,
61
62
  focusedColumnIndex,
62
63
  isFirstVisible,
63
64
  isLastVisible,
@@ -224,7 +225,16 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
224
225
  const width = cellColSpanInfo?.cellProps.width ?? column.computedWidth;
225
226
  const colSpan = cellColSpanInfo?.cellProps.colSpan ?? 1;
226
227
  const pinnedOffset = getPinnedCellOffset(pinnedPosition, column.computedWidth, indexRelativeToAllColumns, columnPositions, columnsTotalWidth, scrollbarWidth);
228
+
229
+ // Virtual cells stay mounted for focus and accessibility relationships, but GridCell collapses
230
+ // them to zero size so they do not participate in the visible row layout.
231
+ const cellIsNotVisible = pinnedPosition === PinnedColumnPosition.VIRTUAL;
227
232
  if (rowNode.type === 'skeletonRow') {
233
+ // Skeleton cells have no value to expose and don't support the collapsed style, so a virtual
234
+ // one would only add a full-width placeholder that shifts the rest of the row.
235
+ if (cellIsNotVisible) {
236
+ return null;
237
+ }
228
238
  return /*#__PURE__*/_jsx(slots.skeletonCell, {
229
239
  type: column.type,
230
240
  width: width,
@@ -247,7 +257,6 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
247
257
  const canReorderColumn = !(disableColumnReorder || column.disableReorder);
248
258
  const canReorderRow = isRowReorderingEnabled && !sortModel.length;
249
259
  const disableDragEvents = !(canReorderColumn || isReorderCell && canReorderRow || isRowDragActive);
250
- const cellIsNotVisible = pinnedPosition === PinnedColumnPosition.VIRTUAL;
251
260
  const showLeftBorder = shouldCellShowLeftBorder(pinnedPosition, indexInSection, rootProps.showCellVerticalBorder, rootProps.pinnedColumnsSectionSeparator);
252
261
  const showRightBorder = shouldCellShowRightBorder(pinnedPosition, indexInSection, sectionLength, rootProps.showCellVerticalBorder, gridHasFiller, rootProps.pinnedColumnsSectionSeparator);
253
262
  return /*#__PURE__*/_jsx(slots.cell, _extends({
@@ -277,9 +286,27 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
277
286
  return getCell(column, i, indexRelativeToAllColumns, pinnedColumns.right.length, PinnedColumnPosition.RIGHT);
278
287
  });
279
288
  const middleColumnsLength = visibleColumns.length - pinnedColumns.left.length - pinnedColumns.right.length;
289
+
290
+ // Build the middle section in visual column order:
291
+ // 1. retained or focused virtual cells before the render context;
292
+ // 2. the cells inside the render context;
293
+ // 3. retained or focused virtual cells after the render context.
280
294
  const cells = [];
281
- if (hasVirtualFocusCellLeft) {
282
- cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, PinnedColumnPosition.VIRTUAL));
295
+ const firstUnpinnedColumnIndex = pinnedColumns.left.length;
296
+ const lastUnpinnedColumnIndex = visibleColumns.length - pinnedColumns.right.length;
297
+
298
+ // Select retained columns before the render context. The unpinned bounds exclude retained
299
+ // columns already rendered by `leftCells` or `rightCells`.
300
+ const virtualColumnIndexesLeft = retainedColumnIndexes.filter(columnIndex => columnIndex >= firstUnpinnedColumnIndex && columnIndex < firstColumnIndex);
301
+
302
+ // The grid already retains a focused cell outside the render context. Add it to the same ordered
303
+ // list, unless the column is a retained row header and is therefore already present.
304
+ if (hasVirtualFocusCellLeft && !virtualColumnIndexesLeft.includes(focusedColumnIndex)) {
305
+ virtualColumnIndexesLeft.push(focusedColumnIndex);
306
+ virtualColumnIndexesLeft.sort((a, b) => a - b);
307
+ }
308
+ for (const columnIndex of virtualColumnIndexesLeft) {
309
+ cells.push(getCell(visibleColumns[columnIndex], columnIndex - pinnedColumns.left.length, columnIndex, middleColumnsLength, PinnedColumnPosition.VIRTUAL));
283
310
  }
284
311
  for (let i = firstColumnIndex; i < lastColumnIndex; i += 1) {
285
312
  const column = visibleColumns[i];
@@ -289,8 +316,15 @@ const GridRow = forwardRef(function GridRow(props, refProp) {
289
316
  }
290
317
  cells.push(getCell(column, indexInSection, i, middleColumnsLength));
291
318
  }
292
- if (hasVirtualFocusCellRight) {
293
- cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, PinnedColumnPosition.VIRTUAL));
319
+
320
+ // Repeat the retention step for unpinned columns after the render context.
321
+ const virtualColumnIndexesRight = retainedColumnIndexes.filter(columnIndex => columnIndex >= lastColumnIndex && columnIndex < lastUnpinnedColumnIndex);
322
+ if (hasVirtualFocusCellRight && !virtualColumnIndexesRight.includes(focusedColumnIndex)) {
323
+ virtualColumnIndexesRight.push(focusedColumnIndex);
324
+ virtualColumnIndexesRight.sort((a, b) => a - b);
325
+ }
326
+ for (const columnIndex of virtualColumnIndexesRight) {
327
+ cells.push(getCell(visibleColumns[columnIndex], columnIndex - pinnedColumns.left.length, columnIndex, middleColumnsLength, PinnedColumnPosition.VIRTUAL));
294
328
  }
295
329
  const eventHandlers = row ? {
296
330
  onClick: publishClick,
@@ -351,6 +385,7 @@ process.env.NODE_ENV !== "production" ? GridRow.propTypes /* remove-proptypes */
351
385
  onMouseEnter: PropTypes.func,
352
386
  onMouseLeave: PropTypes.func,
353
387
  pinnedColumns: PropTypes.object.isRequired,
388
+ retainedColumnIndexes: PropTypes.arrayOf(PropTypes.number).isRequired,
354
389
  row: PropTypes.object.isRequired,
355
390
  rowHeight: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]).isRequired,
356
391
  rowId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
@@ -27,6 +27,7 @@ var _useTimeout = require("../hooks/utils/useTimeout");
27
27
  var _gridColumnsUtils = require("../hooks/features/columns/gridColumnsUtils");
28
28
  var _createSelector = require("../utils/createSelector");
29
29
  var _gridRowsMetaSelector = require("../hooks/features/rows/gridRowsMetaSelector");
30
+ var _gridRowReorderSelector = require("../hooks/features/rowReorder/gridRowReorderSelector");
30
31
  var _jsxRuntime = require("react/jsx-runtime");
31
32
  const CLIFF = 1;
32
33
  const SLOP = 1.5;
@@ -89,15 +90,27 @@ const offsetSelector = (0, _createSelector.createSelector)(_gridDimensionsSelect
89
90
  // For vertical scroll areas, we don't need horizontal offset
90
91
  return 0;
91
92
  });
93
+
94
+ // The `columnReorder` state is only initialized by the Pro package,
95
+ // so it is read defensively here.
96
+ const gridColumnReorderDragColSelector = (0, _createSelector.createRootSelector)(state => state.columnReorder?.dragCol);
97
+
98
+ // The drag direction is derived from the reorder state instead of the drag events.
99
+ // An event handler subscribed during render can fire for a render pass that never mounts.
100
+ // A `setState` call from such a handler triggers a React warning.
101
+ // See https://github.com/mui/mui-x/issues/23469.
102
+ const gridDragDirectionSelector = (0, _createSelector.createSelector)(gridColumnReorderDragColSelector, _gridRowReorderSelector.gridIsRowDragActiveSelector, (dragCol, isRowDragActive) => {
103
+ if (dragCol) {
104
+ return 'horizontal';
105
+ }
106
+ if (isRowDragActive) {
107
+ return 'vertical';
108
+ }
109
+ return 'none';
110
+ });
92
111
  function GridScrollAreaWrapper(props) {
93
112
  const apiRef = (0, _useGridApiContext.useGridApiContext)();
94
- const [dragDirection, setDragDirection] = React.useState('none');
95
-
96
- // Listen for both column and row drag events
97
- (0, _useGridEvent.useGridEvent)(apiRef, 'columnHeaderDragStart', () => setDragDirection('horizontal'));
98
- (0, _useGridEvent.useGridEvent)(apiRef, 'columnHeaderDragEnd', () => setDragDirection('none'));
99
- (0, _useGridEvent.useGridEvent)(apiRef, 'rowDragStart', () => setDragDirection('vertical'));
100
- (0, _useGridEvent.useGridEvent)(apiRef, 'rowDragEnd', () => setDragDirection('none'));
113
+ const dragDirection = (0, _useGridSelector.useGridSelector)(apiRef, gridDragDirectionSelector);
101
114
  if (dragDirection === 'none') {
102
115
  return null;
103
116
  }
@@ -18,8 +18,9 @@ import { gridDimensionsSelector, gridColumnsTotalWidthSelector } from "../hooks/
18
18
  import { gridDensityFactorSelector } from "../hooks/features/density/densitySelector.mjs";
19
19
  import { useTimeout } from "../hooks/utils/useTimeout.mjs";
20
20
  import { getTotalHeaderHeight } from "../hooks/features/columns/gridColumnsUtils.mjs";
21
- import { createSelector } from "../utils/createSelector.mjs";
21
+ import { createRootSelector, createSelector } from "../utils/createSelector.mjs";
22
22
  import { gridRowsMetaSelector } from "../hooks/features/rows/gridRowsMetaSelector.mjs";
23
+ import { gridIsRowDragActiveSelector } from "../hooks/features/rowReorder/gridRowReorderSelector.mjs";
23
24
  import { jsx as _jsx } from "react/jsx-runtime";
24
25
  const CLIFF = 1;
25
26
  const SLOP = 1.5;
@@ -82,15 +83,27 @@ const offsetSelector = createSelector(gridDimensionsSelector, (dimensions, direc
82
83
  // For vertical scroll areas, we don't need horizontal offset
83
84
  return 0;
84
85
  });
86
+
87
+ // The `columnReorder` state is only initialized by the Pro package,
88
+ // so it is read defensively here.
89
+ const gridColumnReorderDragColSelector = createRootSelector(state => state.columnReorder?.dragCol);
90
+
91
+ // The drag direction is derived from the reorder state instead of the drag events.
92
+ // An event handler subscribed during render can fire for a render pass that never mounts.
93
+ // A `setState` call from such a handler triggers a React warning.
94
+ // See https://github.com/mui/mui-x/issues/23469.
95
+ const gridDragDirectionSelector = createSelector(gridColumnReorderDragColSelector, gridIsRowDragActiveSelector, (dragCol, isRowDragActive) => {
96
+ if (dragCol) {
97
+ return 'horizontal';
98
+ }
99
+ if (isRowDragActive) {
100
+ return 'vertical';
101
+ }
102
+ return 'none';
103
+ });
85
104
  function GridScrollAreaWrapper(props) {
86
105
  const apiRef = useGridApiContext();
87
- const [dragDirection, setDragDirection] = React.useState('none');
88
-
89
- // Listen for both column and row drag events
90
- useGridEvent(apiRef, 'columnHeaderDragStart', () => setDragDirection('horizontal'));
91
- useGridEvent(apiRef, 'columnHeaderDragEnd', () => setDragDirection('none'));
92
- useGridEvent(apiRef, 'rowDragStart', () => setDragDirection('vertical'));
93
- useGridEvent(apiRef, 'rowDragEnd', () => setDragDirection('none'));
106
+ const dragDirection = useGridSelector(apiRef, gridDragDirectionSelector);
94
107
  if (dragDirection === 'none') {
95
108
  return null;
96
109
  }