@mui/x-data-grid 9.13.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.
- package/CHANGELOG.md +149 -0
- package/components/GridScrollArea.js +20 -7
- package/components/GridScrollArea.mjs +21 -8
- package/components/base/GridOverlays.js +6 -5
- package/components/base/GridOverlays.mjs +6 -5
- package/components/cell/GridActionsCell.js +53 -50
- package/components/cell/GridActionsCell.mjs +53 -50
- package/components/cell/GridActionsCellItem.js +0 -1
- package/components/cell/GridActionsCellItem.mjs +0 -1
- package/components/cell/GridCell.js +8 -0
- package/components/cell/GridCell.mjs +8 -0
- package/components/quickFilter/QuickFilter.js +7 -2
- package/components/quickFilter/QuickFilter.mjs +7 -2
- package/components/virtualization/GridVirtualScroller.js +3 -0
- package/components/virtualization/GridVirtualScroller.mjs +3 -0
- package/hooks/features/columnResize/useGridColumnResize.js +4 -1
- package/hooks/features/columnResize/useGridColumnResize.mjs +4 -1
- package/hooks/features/dataSource/useGridDataSourceBase.js +1 -1
- package/hooks/features/dataSource/useGridDataSourceBase.mjs +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.d.mts +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.js +50 -9
- package/hooks/features/rowSelection/useGridRowSelection.mjs +51 -10
- package/hooks/features/rowSelection/utils.js +5 -0
- package/hooks/features/rowSelection/utils.mjs +5 -0
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,154 @@
|
|
|
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` [](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` [](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` [](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` [](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` [](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` [](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` [](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
|
+
|
|
3
152
|
## 9.13.0
|
|
4
153
|
|
|
5
154
|
<!-- generated comparing v9.12.0..master -->
|
|
@@ -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
|
|
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
|
|
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
|
}
|
|
@@ -21,19 +21,21 @@ var _jsxRuntime = require("react/jsx-runtime");
|
|
|
21
21
|
const GridOverlayWrapperRoot = (0, _styles.styled)('div', {
|
|
22
22
|
name: 'MuiDataGrid',
|
|
23
23
|
slot: 'OverlayWrapper',
|
|
24
|
-
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant'
|
|
24
|
+
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant'
|
|
25
25
|
})(({
|
|
26
26
|
overlayType,
|
|
27
|
-
loadingOverlayVariant
|
|
28
|
-
right
|
|
27
|
+
loadingOverlayVariant
|
|
29
28
|
}) =>
|
|
30
29
|
// Skeleton overlay should flow with the scroll container and not be sticky
|
|
31
30
|
loadingOverlayVariant !== 'skeleton' ? {
|
|
32
31
|
position: 'sticky',
|
|
33
32
|
// To stay in place while scrolling
|
|
34
33
|
top: 'var(--DataGrid-topContainerHeight)',
|
|
34
|
+
// Both 0-insets keep the overlay in the viewport in LTR and RTL alike. Sticky insets
|
|
35
|
+
// are independent constraints, and a width: 0 box satisfies both at once, so it
|
|
36
|
+
// clamps at whichever edge the scroll pushes it past.
|
|
35
37
|
left: 0,
|
|
36
|
-
right:
|
|
38
|
+
right: 0,
|
|
37
39
|
width: 0,
|
|
38
40
|
// To stay above the content instead of shifting it down
|
|
39
41
|
height: 0,
|
|
@@ -70,7 +72,6 @@ function GridOverlayWrapper(props) {
|
|
|
70
72
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridOverlayWrapperRoot, (0, _extends2.default)({
|
|
71
73
|
className: classes.root
|
|
72
74
|
}, props, {
|
|
73
|
-
right: dimensions.columnsTotalWidth - dimensions.viewportOuterSize.width,
|
|
74
75
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(GridOverlayWrapperInner, (0, _extends2.default)({
|
|
75
76
|
className: classes.inner,
|
|
76
77
|
style: {
|
|
@@ -13,19 +13,21 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
13
13
|
const GridOverlayWrapperRoot = styled('div', {
|
|
14
14
|
name: 'MuiDataGrid',
|
|
15
15
|
slot: 'OverlayWrapper',
|
|
16
|
-
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant'
|
|
16
|
+
shouldForwardProp: prop => prop !== 'overlayType' && prop !== 'loadingOverlayVariant'
|
|
17
17
|
})(({
|
|
18
18
|
overlayType,
|
|
19
|
-
loadingOverlayVariant
|
|
20
|
-
right
|
|
19
|
+
loadingOverlayVariant
|
|
21
20
|
}) =>
|
|
22
21
|
// Skeleton overlay should flow with the scroll container and not be sticky
|
|
23
22
|
loadingOverlayVariant !== 'skeleton' ? {
|
|
24
23
|
position: 'sticky',
|
|
25
24
|
// To stay in place while scrolling
|
|
26
25
|
top: 'var(--DataGrid-topContainerHeight)',
|
|
26
|
+
// Both 0-insets keep the overlay in the viewport in LTR and RTL alike. Sticky insets
|
|
27
|
+
// are independent constraints, and a width: 0 box satisfies both at once, so it
|
|
28
|
+
// clamps at whichever edge the scroll pushes it past.
|
|
27
29
|
left: 0,
|
|
28
|
-
right:
|
|
30
|
+
right: 0,
|
|
29
31
|
width: 0,
|
|
30
32
|
// To stay above the content instead of shifting it down
|
|
31
33
|
height: 0,
|
|
@@ -62,7 +64,6 @@ export function GridOverlayWrapper(props) {
|
|
|
62
64
|
return /*#__PURE__*/_jsx(GridOverlayWrapperRoot, _extends({
|
|
63
65
|
className: classes.root
|
|
64
66
|
}, props, {
|
|
65
|
-
right: dimensions.columnsTotalWidth - dimensions.viewportOuterSize.width,
|
|
66
67
|
children: /*#__PURE__*/_jsx(GridOverlayWrapperInner, _extends({
|
|
67
68
|
className: classes.inner,
|
|
68
69
|
style: {
|
|
@@ -20,6 +20,7 @@ var _gridClasses = require("../../constants/gridClasses");
|
|
|
20
20
|
var _GridMenu = require("../menu/GridMenu");
|
|
21
21
|
var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
|
|
22
22
|
var _useGridApiContext = require("../../hooks/utils/useGridApiContext");
|
|
23
|
+
var _domUtils = require("../../utils/domUtils");
|
|
23
24
|
var _GridActionsCellItem = require("./GridActionsCellItem");
|
|
24
25
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
26
|
const _excluded = ["api", "colDef", "id", "hasFocus", "isEditable", "field", "value", "formattedValue", "row", "rowNode", "cellMode", "tabIndex", "position", "onMenuOpen", "onMenuClose", "children", "suppressChildrenValidation"];
|
|
@@ -140,7 +141,9 @@ If this is intentional, you can suppress this warning by passing the \`suppressC
|
|
|
140
141
|
}
|
|
141
142
|
};
|
|
142
143
|
const handleRootKeyDown = event => {
|
|
143
|
-
|
|
144
|
+
// The menu renders in a portal, but its key events still bubble through the React tree.
|
|
145
|
+
// They must not move the roving focus between the buttons behind the open menu.
|
|
146
|
+
if (numberOfButtons <= 1 || (0, _domUtils.isEventTargetInPortal)(event)) {
|
|
144
147
|
return;
|
|
145
148
|
}
|
|
146
149
|
const getNewIndex = (index, direction) => {
|
|
@@ -170,55 +173,55 @@ If this is intentional, you can suppress this warning by passing the \`suppressC
|
|
|
170
173
|
setFocusedButtonIndex(newIndex);
|
|
171
174
|
}
|
|
172
175
|
};
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
})
|
|
219
|
-
})
|
|
220
|
-
})
|
|
221
|
-
|
|
176
|
+
return (
|
|
177
|
+
/*#__PURE__*/
|
|
178
|
+
// The wrapper carries no role on purpose: the buttons are plain buttons inside the
|
|
179
|
+
// `gridcell`. It only relays the key events bubbling from them.
|
|
180
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
181
|
+
(0, _jsxRuntime.jsxs)("div", (0, _extends2.default)({
|
|
182
|
+
ref: rootRef,
|
|
183
|
+
tabIndex: -1,
|
|
184
|
+
className: _gridClasses.gridClasses.actionsCell,
|
|
185
|
+
onKeyDown: handleRootKeyDown
|
|
186
|
+
}, other, {
|
|
187
|
+
children: [iconButtons.map((button, index) => /*#__PURE__*/React.cloneElement(button, {
|
|
188
|
+
key: index,
|
|
189
|
+
touchRippleRef: handleTouchRippleRef(index),
|
|
190
|
+
onClick: handleButtonClick(index, button.props.onClick),
|
|
191
|
+
tabIndex: focusedButtonIndex === index ? tabIndex : -1
|
|
192
|
+
})), menuButtons.length > 0 && buttonId && /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.baseIconButton, (0, _extends2.default)({
|
|
193
|
+
ref: buttonRef,
|
|
194
|
+
id: buttonId,
|
|
195
|
+
"aria-label": apiRef.current.getLocaleText('actionsCellMore'),
|
|
196
|
+
"aria-haspopup": "menu",
|
|
197
|
+
"aria-expanded": open,
|
|
198
|
+
"aria-controls": open ? menuId : undefined,
|
|
199
|
+
size: "small",
|
|
200
|
+
onClick: toggleMenu,
|
|
201
|
+
touchRippleRef: handleTouchRippleRef(buttonId),
|
|
202
|
+
tabIndex: focusedButtonIndex === iconButtons.length ? tabIndex : -1
|
|
203
|
+
}, rootProps.slotProps?.baseIconButton, {
|
|
204
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.moreActionsIcon, {
|
|
205
|
+
fontSize: "small"
|
|
206
|
+
})
|
|
207
|
+
})), menuButtons.length > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridMenu.GridMenu, {
|
|
208
|
+
open: open,
|
|
209
|
+
target: buttonRef.current,
|
|
210
|
+
position: position,
|
|
211
|
+
onClose: hideMenu,
|
|
212
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.baseMenuList, {
|
|
213
|
+
id: menuId,
|
|
214
|
+
className: _gridClasses.gridClasses.menuList,
|
|
215
|
+
"aria-labelledby": buttonId,
|
|
216
|
+
autoFocusItem: true,
|
|
217
|
+
children: menuButtons.map((button, index) => /*#__PURE__*/React.cloneElement(button, {
|
|
218
|
+
key: index,
|
|
219
|
+
closeMenu: hideMenu
|
|
220
|
+
}))
|
|
221
|
+
})
|
|
222
|
+
})]
|
|
223
|
+
}))
|
|
224
|
+
);
|
|
222
225
|
}
|
|
223
226
|
process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes /* remove-proptypes */ = {
|
|
224
227
|
// ----------------------------- Warning --------------------------------
|
|
@@ -13,6 +13,7 @@ import { gridClasses } from "../../constants/gridClasses.mjs";
|
|
|
13
13
|
import { GridMenu } from "../menu/GridMenu.mjs";
|
|
14
14
|
import { useGridRootProps } from "../../hooks/utils/useGridRootProps.mjs";
|
|
15
15
|
import { useGridApiContext } from "../../hooks/utils/useGridApiContext.mjs";
|
|
16
|
+
import { isEventTargetInPortal } from "../../utils/domUtils.mjs";
|
|
16
17
|
import { GridActionsCellItem } from "./GridActionsCellItem.mjs";
|
|
17
18
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
19
|
const hasActions = colDef => typeof colDef.getActions === 'function';
|
|
@@ -132,7 +133,9 @@ If this is intentional, you can suppress this warning by passing the \`suppressC
|
|
|
132
133
|
}
|
|
133
134
|
};
|
|
134
135
|
const handleRootKeyDown = event => {
|
|
135
|
-
|
|
136
|
+
// The menu renders in a portal, but its key events still bubble through the React tree.
|
|
137
|
+
// They must not move the roving focus between the buttons behind the open menu.
|
|
138
|
+
if (numberOfButtons <= 1 || isEventTargetInPortal(event)) {
|
|
136
139
|
return;
|
|
137
140
|
}
|
|
138
141
|
const getNewIndex = (index, direction) => {
|
|
@@ -162,55 +165,55 @@ If this is intentional, you can suppress this warning by passing the \`suppressC
|
|
|
162
165
|
setFocusedButtonIndex(newIndex);
|
|
163
166
|
}
|
|
164
167
|
};
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
})
|
|
211
|
-
})
|
|
212
|
-
})
|
|
213
|
-
|
|
168
|
+
return (
|
|
169
|
+
/*#__PURE__*/
|
|
170
|
+
// The wrapper carries no role on purpose: the buttons are plain buttons inside the
|
|
171
|
+
// `gridcell`. It only relays the key events bubbling from them.
|
|
172
|
+
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
|
|
173
|
+
_jsxs("div", _extends({
|
|
174
|
+
ref: rootRef,
|
|
175
|
+
tabIndex: -1,
|
|
176
|
+
className: gridClasses.actionsCell,
|
|
177
|
+
onKeyDown: handleRootKeyDown
|
|
178
|
+
}, other, {
|
|
179
|
+
children: [iconButtons.map((button, index) => /*#__PURE__*/React.cloneElement(button, {
|
|
180
|
+
key: index,
|
|
181
|
+
touchRippleRef: handleTouchRippleRef(index),
|
|
182
|
+
onClick: handleButtonClick(index, button.props.onClick),
|
|
183
|
+
tabIndex: focusedButtonIndex === index ? tabIndex : -1
|
|
184
|
+
})), menuButtons.length > 0 && buttonId && /*#__PURE__*/_jsx(rootProps.slots.baseIconButton, _extends({
|
|
185
|
+
ref: buttonRef,
|
|
186
|
+
id: buttonId,
|
|
187
|
+
"aria-label": apiRef.current.getLocaleText('actionsCellMore'),
|
|
188
|
+
"aria-haspopup": "menu",
|
|
189
|
+
"aria-expanded": open,
|
|
190
|
+
"aria-controls": open ? menuId : undefined,
|
|
191
|
+
size: "small",
|
|
192
|
+
onClick: toggleMenu,
|
|
193
|
+
touchRippleRef: handleTouchRippleRef(buttonId),
|
|
194
|
+
tabIndex: focusedButtonIndex === iconButtons.length ? tabIndex : -1
|
|
195
|
+
}, rootProps.slotProps?.baseIconButton, {
|
|
196
|
+
children: /*#__PURE__*/_jsx(rootProps.slots.moreActionsIcon, {
|
|
197
|
+
fontSize: "small"
|
|
198
|
+
})
|
|
199
|
+
})), menuButtons.length > 0 && /*#__PURE__*/_jsx(GridMenu, {
|
|
200
|
+
open: open,
|
|
201
|
+
target: buttonRef.current,
|
|
202
|
+
position: position,
|
|
203
|
+
onClose: hideMenu,
|
|
204
|
+
children: /*#__PURE__*/_jsx(rootProps.slots.baseMenuList, {
|
|
205
|
+
id: menuId,
|
|
206
|
+
className: gridClasses.menuList,
|
|
207
|
+
"aria-labelledby": buttonId,
|
|
208
|
+
autoFocusItem: true,
|
|
209
|
+
children: menuButtons.map((button, index) => /*#__PURE__*/React.cloneElement(button, {
|
|
210
|
+
key: index,
|
|
211
|
+
closeMenu: hideMenu
|
|
212
|
+
}))
|
|
213
|
+
})
|
|
214
|
+
})]
|
|
215
|
+
}))
|
|
216
|
+
);
|
|
214
217
|
}
|
|
215
218
|
process.env.NODE_ENV !== "production" ? GridActionsCell.propTypes /* remove-proptypes */ = {
|
|
216
219
|
// ----------------------------- Warning --------------------------------
|
|
@@ -30,7 +30,6 @@ const GridActionsCellItem = exports.GridActionsCellItem = (0, _forwardRef.forwar
|
|
|
30
30
|
};
|
|
31
31
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.baseIconButton, (0, _extends2.default)({
|
|
32
32
|
size: "small",
|
|
33
|
-
role: "menuitem",
|
|
34
33
|
"aria-label": label
|
|
35
34
|
}, other, {
|
|
36
35
|
onClick: handleClick
|
|
@@ -177,6 +177,10 @@ const GridCell = (0, _forwardRef.forwardRef)(function GridCell(props, ref) {
|
|
|
177
177
|
};
|
|
178
178
|
const classes = useUtilityClasses(ownerState);
|
|
179
179
|
const publishMouseUp = React.useCallback(eventName => event => {
|
|
180
|
+
// The row might have been deleted during the click
|
|
181
|
+
if (!apiRef.current.getRow(rowId)) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
180
184
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
181
185
|
apiRef.current.publishEvent(eventName, params, event);
|
|
182
186
|
if (onMouseUp) {
|
|
@@ -184,6 +188,10 @@ const GridCell = (0, _forwardRef.forwardRef)(function GridCell(props, ref) {
|
|
|
184
188
|
}
|
|
185
189
|
}, [apiRef, field, onMouseUp, rowId]);
|
|
186
190
|
const publishMouseDown = React.useCallback(eventName => event => {
|
|
191
|
+
// The row might have been deleted during the click
|
|
192
|
+
if (!apiRef.current.getRow(rowId)) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
187
195
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
188
196
|
apiRef.current.publishEvent(eventName, params, event);
|
|
189
197
|
if (onMouseDown) {
|
|
@@ -170,6 +170,10 @@ const GridCell = forwardRef(function GridCell(props, ref) {
|
|
|
170
170
|
};
|
|
171
171
|
const classes = useUtilityClasses(ownerState);
|
|
172
172
|
const publishMouseUp = React.useCallback(eventName => event => {
|
|
173
|
+
// The row might have been deleted during the click
|
|
174
|
+
if (!apiRef.current.getRow(rowId)) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
173
177
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
174
178
|
apiRef.current.publishEvent(eventName, params, event);
|
|
175
179
|
if (onMouseUp) {
|
|
@@ -177,6 +181,10 @@ const GridCell = forwardRef(function GridCell(props, ref) {
|
|
|
177
181
|
}
|
|
178
182
|
}, [apiRef, field, onMouseUp, rowId]);
|
|
179
183
|
const publishMouseDown = React.useCallback(eventName => event => {
|
|
184
|
+
// The row might have been deleted during the click
|
|
185
|
+
if (!apiRef.current.getRow(rowId)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
180
188
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
181
189
|
apiRef.current.publishEvent(eventName, params, event);
|
|
182
190
|
if (onMouseDown) {
|
|
@@ -13,6 +13,7 @@ var React = _interopRequireWildcard(require("react"));
|
|
|
13
13
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
14
14
|
var _debounce = _interopRequireDefault(require("@mui/utils/debounce"));
|
|
15
15
|
var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
|
|
16
|
+
var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
|
|
16
17
|
var _useId = _interopRequireDefault(require("@mui/utils/useId"));
|
|
17
18
|
var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
|
|
18
19
|
var _useComponentRenderer = require("@mui/x-internals/useComponentRenderer");
|
|
@@ -108,11 +109,15 @@ function QuickFilter(props) {
|
|
|
108
109
|
previousExpandedValue.current = expandedValue;
|
|
109
110
|
}
|
|
110
111
|
}, [expandedValue]);
|
|
111
|
-
|
|
112
|
+
|
|
113
|
+
// Identity-stable, so that a re-render with a new `parser` does not recreate the debounced
|
|
114
|
+
// function below and clear a pending commit. See https://github.com/mui/mui-x/issues/23572.
|
|
115
|
+
const commitQuickFilterValue = (0, _useEventCallback.default)(newValue => {
|
|
112
116
|
const newQuickFilterValues = parser(newValue);
|
|
113
117
|
prevQuickFilterValuesRef.current = newQuickFilterValues;
|
|
114
118
|
apiRef.current.setQuickFilterValues(newQuickFilterValues);
|
|
115
|
-
}
|
|
119
|
+
});
|
|
120
|
+
const setQuickFilterValueDebounced = React.useMemo(() => (0, _debounce.default)(commitQuickFilterValue, debounceMs), [commitQuickFilterValue, debounceMs]);
|
|
116
121
|
React.useEffect(() => setQuickFilterValueDebounced.clear, [setQuickFilterValueDebounced]);
|
|
117
122
|
const handleValueChange = React.useCallback(event => {
|
|
118
123
|
const newValue = event.target.value;
|
|
@@ -7,6 +7,7 @@ import * as React from 'react';
|
|
|
7
7
|
import PropTypes from 'prop-types';
|
|
8
8
|
import debounce from '@mui/utils/debounce';
|
|
9
9
|
import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
10
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
10
11
|
import useId from '@mui/utils/useId';
|
|
11
12
|
import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
|
|
12
13
|
import { useComponentRenderer } from '@mui/x-internals/useComponentRenderer';
|
|
@@ -101,11 +102,15 @@ function QuickFilter(props) {
|
|
|
101
102
|
previousExpandedValue.current = expandedValue;
|
|
102
103
|
}
|
|
103
104
|
}, [expandedValue]);
|
|
104
|
-
|
|
105
|
+
|
|
106
|
+
// Identity-stable, so that a re-render with a new `parser` does not recreate the debounced
|
|
107
|
+
// function below and clear a pending commit. See https://github.com/mui/mui-x/issues/23572.
|
|
108
|
+
const commitQuickFilterValue = useEventCallback(newValue => {
|
|
105
109
|
const newQuickFilterValues = parser(newValue);
|
|
106
110
|
prevQuickFilterValuesRef.current = newQuickFilterValues;
|
|
107
111
|
apiRef.current.setQuickFilterValues(newQuickFilterValues);
|
|
108
|
-
}
|
|
112
|
+
});
|
|
113
|
+
const setQuickFilterValueDebounced = React.useMemo(() => debounce(commitQuickFilterValue, debounceMs), [commitQuickFilterValue, debounceMs]);
|
|
109
114
|
React.useEffect(() => setQuickFilterValueDebounced.clear, [setQuickFilterValueDebounced]);
|
|
110
115
|
const handleValueChange = React.useCallback(event => {
|
|
111
116
|
const newValue = event.target.value;
|
|
@@ -93,7 +93,10 @@ const Viewport = (0, _styles.styled)('div', {
|
|
|
93
93
|
display: 'inline-block',
|
|
94
94
|
position: 'sticky',
|
|
95
95
|
top: 0,
|
|
96
|
+
// The viewport spans the scrollport exactly, so both 0-insets resolve to the same
|
|
97
|
+
// offset and it stays pinned in LTR and RTL alike.
|
|
96
98
|
left: 0,
|
|
99
|
+
right: 0,
|
|
97
100
|
overflow: 'hidden'
|
|
98
101
|
}
|
|
99
102
|
});
|
|
@@ -85,7 +85,10 @@ const Viewport = styled('div', {
|
|
|
85
85
|
display: 'inline-block',
|
|
86
86
|
position: 'sticky',
|
|
87
87
|
top: 0,
|
|
88
|
+
// The viewport spans the scrollport exactly, so both 0-insets resolve to the same
|
|
89
|
+
// offset and it stays pinned in LTR and RTL alike.
|
|
88
90
|
left: 0,
|
|
91
|
+
right: 0,
|
|
89
92
|
overflow: 'hidden'
|
|
90
93
|
}
|
|
91
94
|
});
|
|
@@ -464,7 +464,10 @@ const useGridColumnResize = (apiRef, props) => {
|
|
|
464
464
|
});
|
|
465
465
|
const stopListening = React.useCallback(() => {
|
|
466
466
|
const doc = (0, _ownerDocument.default)(apiRef.current.rootElementRef.current);
|
|
467
|
-
|
|
467
|
+
// Also runs as this effect's unmount cleanup, which can execute against a
|
|
468
|
+
// document that no longer has a body. The cursor is only ever set while a
|
|
469
|
+
// resize is in progress, so there is nothing to clear in that case.
|
|
470
|
+
doc.body?.style.removeProperty('cursor');
|
|
468
471
|
doc.removeEventListener('mousemove', handleResizeMouseMove);
|
|
469
472
|
doc.removeEventListener('mouseup', handleResizeMouseUp);
|
|
470
473
|
doc.removeEventListener('touchmove', handleTouchMove);
|
|
@@ -456,7 +456,10 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
456
456
|
});
|
|
457
457
|
const stopListening = React.useCallback(() => {
|
|
458
458
|
const doc = ownerDocument(apiRef.current.rootElementRef.current);
|
|
459
|
-
|
|
459
|
+
// Also runs as this effect's unmount cleanup, which can execute against a
|
|
460
|
+
// document that no longer has a body. The cursor is only ever set while a
|
|
461
|
+
// resize is in progress, so there is nothing to clear in that case.
|
|
462
|
+
doc.body?.style.removeProperty('cursor');
|
|
460
463
|
doc.removeEventListener('mousemove', handleResizeMouseMove);
|
|
461
464
|
doc.removeEventListener('mouseup', handleResizeMouseUp);
|
|
462
465
|
doc.removeEventListener('touchmove', handleTouchMove);
|
|
@@ -83,7 +83,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
83
83
|
// The selector prunes the incomplete items, but a caller passing its own `filterModel`
|
|
84
84
|
// overrides it, so prune again on the merged params.
|
|
85
85
|
fetchParams.filterModel = (0, _gridFilterUtils.removeIncompleteFilterItems)(fetchParams.filterModel, (0, _columns.gridColumnLookupSelector)(apiRef));
|
|
86
|
-
if (parentId && parentId !== _gridRowsUtils.GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
|
|
86
|
+
if (parentId != null && parentId !== _gridRowsUtils.GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
|
|
87
87
|
options.fetchRowChildren?.([parentId], [fetchParams], showChildrenLoading);
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
@@ -76,7 +76,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
76
76
|
// The selector prunes the incomplete items, but a caller passing its own `filterModel`
|
|
77
77
|
// overrides it, so prune again on the merged params.
|
|
78
78
|
fetchParams.filterModel = removeIncompleteFilterItems(fetchParams.filterModel, gridColumnLookupSelector(apiRef));
|
|
79
|
-
if (parentId && parentId !== GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
|
|
79
|
+
if (parentId != null && parentId !== GRID_ROOT_GROUP_ID && props.signature !== 'DataGrid') {
|
|
80
80
|
options.fetchRowChildren?.([parentId], [fetchParams], showChildrenLoading);
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
@@ -9,4 +9,4 @@ export declare const rowSelectionStateInitializer: GridStateInitializer<Pick<Dat
|
|
|
9
9
|
* @requires useGridFocus (state) - can be after
|
|
10
10
|
* @requires useGridKeyboardNavigation (`cellKeyDown` event must first be consumed by it)
|
|
11
11
|
*/
|
|
12
|
-
export declare const useGridRowSelection: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'checkboxSelection' | 'rowSelectionModel' | 'onRowSelectionModelChange' | 'disableMultipleRowSelection' | 'disableRowSelectionOnClick' | 'disableRowSelectionExcludeModel' | 'isRowSelectable' | 'checkboxSelectionVisibleOnly' | 'pagination' | 'paginationMode' | 'filterMode' | 'classes' | 'keepNonExistentRowsSelected' | 'rowSelection' | 'rowSelectionPropagation' | 'signature'>) => void;
|
|
12
|
+
export declare const useGridRowSelection: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'checkboxSelection' | 'rowSelectionModel' | 'onRowSelectionModelChange' | 'disableMultipleRowSelection' | 'disableRowSelectionOnClick' | 'disableRowSelectionExcludeModel' | 'isRowSelectable' | 'checkboxSelectionVisibleOnly' | 'pagination' | 'paginationMode' | 'filterMode' | 'classes' | 'keepNonExistentRowsSelected' | 'rowSelection' | 'rowSelectionPropagation' | 'dataSource' | 'signature'>) => void;
|
|
@@ -9,4 +9,4 @@ export declare const rowSelectionStateInitializer: GridStateInitializer<Pick<Dat
|
|
|
9
9
|
* @requires useGridFocus (state) - can be after
|
|
10
10
|
* @requires useGridKeyboardNavigation (`cellKeyDown` event must first be consumed by it)
|
|
11
11
|
*/
|
|
12
|
-
export declare const useGridRowSelection: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'checkboxSelection' | 'rowSelectionModel' | 'onRowSelectionModelChange' | 'disableMultipleRowSelection' | 'disableRowSelectionOnClick' | 'disableRowSelectionExcludeModel' | 'isRowSelectable' | 'checkboxSelectionVisibleOnly' | 'pagination' | 'paginationMode' | 'filterMode' | 'classes' | 'keepNonExistentRowsSelected' | 'rowSelection' | 'rowSelectionPropagation' | 'signature'>) => void;
|
|
12
|
+
export declare const useGridRowSelection: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'checkboxSelection' | 'rowSelectionModel' | 'onRowSelectionModelChange' | 'disableMultipleRowSelection' | 'disableRowSelectionOnClick' | 'disableRowSelectionExcludeModel' | 'isRowSelectable' | 'checkboxSelectionVisibleOnly' | 'pagination' | 'paginationMode' | 'filterMode' | 'classes' | 'keepNonExistentRowsSelected' | 'rowSelection' | 'rowSelectionPropagation' | 'dataSource' | 'signature'>) => void;
|
|
@@ -17,6 +17,7 @@ var _useGridApiMethod = require("../../utils/useGridApiMethod");
|
|
|
17
17
|
var _useGridLogger = require("../../utils/useGridLogger");
|
|
18
18
|
var _useGridSelector = require("../../utils/useGridSelector");
|
|
19
19
|
var _gridRowsSelector = require("../rows/gridRowsSelector");
|
|
20
|
+
var _gridRowsUtils = require("../rows/gridRowsUtils");
|
|
20
21
|
var _gridRowSelectionSelector = require("./gridRowSelectionSelector");
|
|
21
22
|
var _gridFocusStateSelector = require("../focus/gridFocusStateSelector");
|
|
22
23
|
var _gridFilterSelector = require("../filter/gridFilterSelector");
|
|
@@ -127,6 +128,10 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
127
128
|
if (props.rowSelection === false) {
|
|
128
129
|
return false;
|
|
129
130
|
}
|
|
131
|
+
const rowNode = (0, _gridRowsSelector.gridRowNodeSelector)(apiRef, id);
|
|
132
|
+
if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow' || rowNode?.type === 'skeletonRow') {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
130
135
|
|
|
131
136
|
// If `keepNonExistentRowsSelected` is true, we might run in a case where row selectability is checked for a row that does not exist.
|
|
132
137
|
// Since that row was previously selected (otherwise it would not be checked at this point), we return true.
|
|
@@ -136,10 +141,6 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
136
141
|
if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) {
|
|
137
142
|
return false;
|
|
138
143
|
}
|
|
139
|
-
const rowNode = (0, _gridRowsSelector.gridRowNodeSelector)(apiRef, id);
|
|
140
|
-
if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow') {
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
144
|
return true;
|
|
144
145
|
}, [apiRef, props.rowSelection, props.keepNonExistentRowsSelected, propIsRowSelectable]);
|
|
145
146
|
const getSelectedRows = React.useCallback(() => (0, _gridRowSelectionSelector.gridRowSelectionIdsSelector)(apiRef), [apiRef]);
|
|
@@ -315,6 +316,7 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
315
316
|
* EVENTS
|
|
316
317
|
*/
|
|
317
318
|
const isFirstRender = React.useRef(true);
|
|
319
|
+
const previousRowsLookupRef = React.useRef(null);
|
|
318
320
|
const removeOutdatedSelection = React.useCallback(() => {
|
|
319
321
|
if (isFirstRender.current) {
|
|
320
322
|
return;
|
|
@@ -323,6 +325,11 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
323
325
|
const rowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
|
|
324
326
|
const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
|
|
325
327
|
const filteredRowsLookup = (0, _gridFilterSelector.gridFilteredRowsLookupSelector)(apiRef);
|
|
328
|
+
const previousRowsLookup = previousRowsLookupRef.current;
|
|
329
|
+
previousRowsLookupRef.current = rowsLookup;
|
|
330
|
+
// Read the depth at call time. The event that runs this callback can fire in the same
|
|
331
|
+
// tick as the state update that changes the depth, before the render-scope value updates.
|
|
332
|
+
const isNested = (0, _gridRowsSelector.gridRowMaximumTreeDepthSelector)(apiRef) > 1;
|
|
326
333
|
const isNonExistent = id => {
|
|
327
334
|
if (props.filterMode === 'server') {
|
|
328
335
|
return !rowsLookup[id];
|
|
@@ -350,6 +357,32 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
350
357
|
return node.children.some(childId => isOrHasSelectableDescendant(childId));
|
|
351
358
|
};
|
|
352
359
|
let hasChanged = false;
|
|
360
|
+
|
|
361
|
+
// Rows can load after their parent was selected (server-side lazy loading).
|
|
362
|
+
// They arrive unselected, so the parent re-derivation below would drop the parent.
|
|
363
|
+
// With `rowSelectionPropagation.descendants`, the rows that appeared since the last run
|
|
364
|
+
// inherit the selection state of their closest previously known ancestor instead.
|
|
365
|
+
if (isNested && props.rowSelectionPropagation?.descendants && currentSelection.type === 'include' && currentSelection.ids.size > 0 && previousRowsLookup !== null && previousRowsLookup !== rowsLookup) {
|
|
366
|
+
const isNewRow = id => rowsLookup[id] !== undefined && previousRowsLookup[id] === undefined;
|
|
367
|
+
const inheritsSelection = id => {
|
|
368
|
+
const parentId = rowTree[id]?.parent;
|
|
369
|
+
if (parentId == null || parentId === _gridRowsUtils.GRID_ROOT_GROUP_ID) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
if (selectionManager.has(parentId)) {
|
|
373
|
+
return true;
|
|
374
|
+
}
|
|
375
|
+
// A row that appeared together with its parent reads the state further up the chain.
|
|
376
|
+
return isNewRow(parentId) ? inheritsSelection(parentId) : false;
|
|
377
|
+
};
|
|
378
|
+
const dataRowIds = (0, _gridRowsSelector.gridDataRowIdsSelector)(apiRef);
|
|
379
|
+
for (const id of dataRowIds) {
|
|
380
|
+
if (isNewRow(id) && filteredRowsLookup[id] !== false && inheritsSelection(id) && apiRef.current.isRowSelectable(id)) {
|
|
381
|
+
selectionManager.select(id);
|
|
382
|
+
hasChanged = true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
353
386
|
for (const id of currentSelection.ids) {
|
|
354
387
|
if (isNonExistent(id)) {
|
|
355
388
|
if (props.keepNonExistentRowsSelected) {
|
|
@@ -382,9 +415,10 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
382
415
|
// For nested data, on row tree updation (filtering, adding rows, etc.) when the selection is
|
|
383
416
|
// not empty, we need to re-run scanning of the tree to propagate the selection changes
|
|
384
417
|
// Example: A parent whose de-selected children are filtered out should now be selected
|
|
385
|
-
|
|
386
|
-
//
|
|
387
|
-
|
|
418
|
+
// With a data source, an `exclude` model is left alone: the grid only knows the loaded
|
|
419
|
+
// subset of the rows, so rewriting the model into an `include` of the known rows would
|
|
420
|
+
// drop the "rows that load later are selected too" semantics of the select-all state.
|
|
421
|
+
const shouldReapplyPropagation = isNested && props.rowSelectionPropagation?.parents && (newSelectionModel.type === 'exclude' ? props.dataSource === undefined : newSelectionModel.ids.size > 0);
|
|
388
422
|
if (hasChanged || shouldReapplyPropagation) {
|
|
389
423
|
if (shouldReapplyPropagation) {
|
|
390
424
|
if (newSelectionModel.type === 'exclude') {
|
|
@@ -398,13 +432,20 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
398
432
|
}
|
|
399
433
|
apiRef.current.selectRows(selectedRowIds, true, true);
|
|
400
434
|
} else {
|
|
401
|
-
|
|
435
|
+
// `getPropagatedRowSelectionModel` reads the sibling selection state from the model
|
|
436
|
+
// built above, so the rows selected during this run count for the parent derivation.
|
|
437
|
+
// `selectRows` would read the state from before this run instead.
|
|
438
|
+
const propagatedModel = apiRef.current.getPropagatedRowSelectionModel(newSelectionModel);
|
|
439
|
+
const isSelectionValid = propagatedModel.ids.size < 2 || canHaveMultipleSelection;
|
|
440
|
+
if (isSelectionValid && (propagatedModel.type !== currentSelection.type || propagatedModel.ids.size !== currentSelection.ids.size || !Array.from(propagatedModel.ids).every(id => currentSelection.ids.has(id)))) {
|
|
441
|
+
apiRef.current.setRowSelectionModel(propagatedModel, 'multipleRowsSelection');
|
|
442
|
+
}
|
|
402
443
|
}
|
|
403
444
|
} else {
|
|
404
445
|
apiRef.current.setRowSelectionModel(newSelectionModel, 'multipleRowsSelection');
|
|
405
446
|
}
|
|
406
447
|
}
|
|
407
|
-
}, [apiRef,
|
|
448
|
+
}, [apiRef, props.rowSelectionPropagation?.parents, props.rowSelectionPropagation?.descendants, props.keepNonExistentRowsSelected, props.filterMode, props.dataSource, canHaveMultipleSelection, getRowsToBeSelected]);
|
|
408
449
|
const handleSingleRowSelection = React.useCallback((id, event) => {
|
|
409
450
|
const hasCtrlKey = event.metaKey || event.ctrlKey;
|
|
410
451
|
|
|
@@ -9,7 +9,8 @@ import { useGridEvent } from "../../utils/useGridEvent.mjs";
|
|
|
9
9
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.mjs";
|
|
10
10
|
import { useGridLogger } from "../../utils/useGridLogger.mjs";
|
|
11
11
|
import { useGridSelector } from "../../utils/useGridSelector.mjs";
|
|
12
|
-
import { gridRowsLookupSelector, gridRowMaximumTreeDepthSelector, gridRowNodeSelector, gridRowTreeSelector } from "../rows/gridRowsSelector.mjs";
|
|
12
|
+
import { gridDataRowIdsSelector, gridRowsLookupSelector, gridRowMaximumTreeDepthSelector, gridRowNodeSelector, gridRowTreeSelector } from "../rows/gridRowsSelector.mjs";
|
|
13
|
+
import { GRID_ROOT_GROUP_ID } from "../rows/gridRowsUtils.mjs";
|
|
13
14
|
import { gridRowSelectionManagerSelector, gridRowSelectionStateSelector, gridRowSelectionCountSelector, gridRowSelectionIdsSelector } from "./gridRowSelectionSelector.mjs";
|
|
14
15
|
import { gridFocusCellSelector } from "../focus/gridFocusStateSelector.mjs";
|
|
15
16
|
import { gridExpandedSortedRowIdsSelector, gridFilteredRowsLookupSelector, gridFilterModelSelector, gridQuickFilterValuesSelector } from "../filter/gridFilterSelector.mjs";
|
|
@@ -119,6 +120,10 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
119
120
|
if (props.rowSelection === false) {
|
|
120
121
|
return false;
|
|
121
122
|
}
|
|
123
|
+
const rowNode = gridRowNodeSelector(apiRef, id);
|
|
124
|
+
if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow' || rowNode?.type === 'skeletonRow') {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
122
127
|
|
|
123
128
|
// If `keepNonExistentRowsSelected` is true, we might run in a case where row selectability is checked for a row that does not exist.
|
|
124
129
|
// Since that row was previously selected (otherwise it would not be checked at this point), we return true.
|
|
@@ -128,10 +133,6 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
128
133
|
if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) {
|
|
129
134
|
return false;
|
|
130
135
|
}
|
|
131
|
-
const rowNode = gridRowNodeSelector(apiRef, id);
|
|
132
|
-
if (rowNode?.type === 'footer' || rowNode?.type === 'pinnedRow') {
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
136
|
return true;
|
|
136
137
|
}, [apiRef, props.rowSelection, props.keepNonExistentRowsSelected, propIsRowSelectable]);
|
|
137
138
|
const getSelectedRows = React.useCallback(() => gridRowSelectionIdsSelector(apiRef), [apiRef]);
|
|
@@ -307,6 +308,7 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
307
308
|
* EVENTS
|
|
308
309
|
*/
|
|
309
310
|
const isFirstRender = React.useRef(true);
|
|
311
|
+
const previousRowsLookupRef = React.useRef(null);
|
|
310
312
|
const removeOutdatedSelection = React.useCallback(() => {
|
|
311
313
|
if (isFirstRender.current) {
|
|
312
314
|
return;
|
|
@@ -315,6 +317,11 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
315
317
|
const rowsLookup = gridRowsLookupSelector(apiRef);
|
|
316
318
|
const rowTree = gridRowTreeSelector(apiRef);
|
|
317
319
|
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
320
|
+
const previousRowsLookup = previousRowsLookupRef.current;
|
|
321
|
+
previousRowsLookupRef.current = rowsLookup;
|
|
322
|
+
// Read the depth at call time. The event that runs this callback can fire in the same
|
|
323
|
+
// tick as the state update that changes the depth, before the render-scope value updates.
|
|
324
|
+
const isNested = gridRowMaximumTreeDepthSelector(apiRef) > 1;
|
|
318
325
|
const isNonExistent = id => {
|
|
319
326
|
if (props.filterMode === 'server') {
|
|
320
327
|
return !rowsLookup[id];
|
|
@@ -342,6 +349,32 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
342
349
|
return node.children.some(childId => isOrHasSelectableDescendant(childId));
|
|
343
350
|
};
|
|
344
351
|
let hasChanged = false;
|
|
352
|
+
|
|
353
|
+
// Rows can load after their parent was selected (server-side lazy loading).
|
|
354
|
+
// They arrive unselected, so the parent re-derivation below would drop the parent.
|
|
355
|
+
// With `rowSelectionPropagation.descendants`, the rows that appeared since the last run
|
|
356
|
+
// inherit the selection state of their closest previously known ancestor instead.
|
|
357
|
+
if (isNested && props.rowSelectionPropagation?.descendants && currentSelection.type === 'include' && currentSelection.ids.size > 0 && previousRowsLookup !== null && previousRowsLookup !== rowsLookup) {
|
|
358
|
+
const isNewRow = id => rowsLookup[id] !== undefined && previousRowsLookup[id] === undefined;
|
|
359
|
+
const inheritsSelection = id => {
|
|
360
|
+
const parentId = rowTree[id]?.parent;
|
|
361
|
+
if (parentId == null || parentId === GRID_ROOT_GROUP_ID) {
|
|
362
|
+
return false;
|
|
363
|
+
}
|
|
364
|
+
if (selectionManager.has(parentId)) {
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
// A row that appeared together with its parent reads the state further up the chain.
|
|
368
|
+
return isNewRow(parentId) ? inheritsSelection(parentId) : false;
|
|
369
|
+
};
|
|
370
|
+
const dataRowIds = gridDataRowIdsSelector(apiRef);
|
|
371
|
+
for (const id of dataRowIds) {
|
|
372
|
+
if (isNewRow(id) && filteredRowsLookup[id] !== false && inheritsSelection(id) && apiRef.current.isRowSelectable(id)) {
|
|
373
|
+
selectionManager.select(id);
|
|
374
|
+
hasChanged = true;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
345
378
|
for (const id of currentSelection.ids) {
|
|
346
379
|
if (isNonExistent(id)) {
|
|
347
380
|
if (props.keepNonExistentRowsSelected) {
|
|
@@ -374,9 +407,10 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
374
407
|
// For nested data, on row tree updation (filtering, adding rows, etc.) when the selection is
|
|
375
408
|
// not empty, we need to re-run scanning of the tree to propagate the selection changes
|
|
376
409
|
// Example: A parent whose de-selected children are filtered out should now be selected
|
|
377
|
-
|
|
378
|
-
//
|
|
379
|
-
|
|
410
|
+
// With a data source, an `exclude` model is left alone: the grid only knows the loaded
|
|
411
|
+
// subset of the rows, so rewriting the model into an `include` of the known rows would
|
|
412
|
+
// drop the "rows that load later are selected too" semantics of the select-all state.
|
|
413
|
+
const shouldReapplyPropagation = isNested && props.rowSelectionPropagation?.parents && (newSelectionModel.type === 'exclude' ? props.dataSource === undefined : newSelectionModel.ids.size > 0);
|
|
380
414
|
if (hasChanged || shouldReapplyPropagation) {
|
|
381
415
|
if (shouldReapplyPropagation) {
|
|
382
416
|
if (newSelectionModel.type === 'exclude') {
|
|
@@ -390,13 +424,20 @@ You need to upgrade to DataGridPro or DataGridPremium component to unlock multip
|
|
|
390
424
|
}
|
|
391
425
|
apiRef.current.selectRows(selectedRowIds, true, true);
|
|
392
426
|
} else {
|
|
393
|
-
|
|
427
|
+
// `getPropagatedRowSelectionModel` reads the sibling selection state from the model
|
|
428
|
+
// built above, so the rows selected during this run count for the parent derivation.
|
|
429
|
+
// `selectRows` would read the state from before this run instead.
|
|
430
|
+
const propagatedModel = apiRef.current.getPropagatedRowSelectionModel(newSelectionModel);
|
|
431
|
+
const isSelectionValid = propagatedModel.ids.size < 2 || canHaveMultipleSelection;
|
|
432
|
+
if (isSelectionValid && (propagatedModel.type !== currentSelection.type || propagatedModel.ids.size !== currentSelection.ids.size || !Array.from(propagatedModel.ids).every(id => currentSelection.ids.has(id)))) {
|
|
433
|
+
apiRef.current.setRowSelectionModel(propagatedModel, 'multipleRowsSelection');
|
|
434
|
+
}
|
|
394
435
|
}
|
|
395
436
|
} else {
|
|
396
437
|
apiRef.current.setRowSelectionModel(newSelectionModel, 'multipleRowsSelection');
|
|
397
438
|
}
|
|
398
439
|
}
|
|
399
|
-
}, [apiRef,
|
|
440
|
+
}, [apiRef, props.rowSelectionPropagation?.parents, props.rowSelectionPropagation?.descendants, props.keepNonExistentRowsSelected, props.filterMode, props.dataSource, canHaveMultipleSelection, getRowsToBeSelected]);
|
|
400
441
|
const handleSingleRowSelection = React.useCallback((id, event) => {
|
|
401
442
|
const hasCtrlKey = event.metaKey || event.ctrlKey;
|
|
402
443
|
|
|
@@ -67,6 +67,11 @@ const checkboxPropsSelector = exports.checkboxPropsSelector = (0, _createSelecto
|
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
const node = rowTree[itemToTraverseId];
|
|
70
|
+
// Skeleton rows are placeholders for rows that are not loaded yet.
|
|
71
|
+
// They have no selection state, so they do not affect the parent checkbox state.
|
|
72
|
+
if (node?.type === 'skeletonRow') {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
70
75
|
if (node?.type === 'group') {
|
|
71
76
|
node.children.forEach(traverseDescendants);
|
|
72
77
|
}
|
|
@@ -60,6 +60,11 @@ export const checkboxPropsSelector = createSelector(gridColumnDefinitionsSelecto
|
|
|
60
60
|
return;
|
|
61
61
|
}
|
|
62
62
|
const node = rowTree[itemToTraverseId];
|
|
63
|
+
// Skeleton rows are placeholders for rows that are not loaded yet.
|
|
64
|
+
// They have no selection state, so they do not affect the parent checkbox state.
|
|
65
|
+
if (node?.type === 'skeletonRow') {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
63
68
|
if (node?.type === 'group') {
|
|
64
69
|
node.children.forEach(traverseDescendants);
|
|
65
70
|
}
|
package/index.js
CHANGED
package/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/x-data-grid",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.14.0",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "The Community plan edition of the MUI X Data Grid components.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"@babel/runtime": "^7.29.7",
|
|
41
41
|
"@base-ui/utils": "^0.3.2",
|
|
42
42
|
"@mui/utils": "^9.4.0",
|
|
43
|
-
"@mui/x-internals": "^9.
|
|
44
|
-
"@mui/x-virtualizer": "0.7.
|
|
43
|
+
"@mui/x-internals": "^9.14.0",
|
|
44
|
+
"@mui/x-virtualizer": "0.7.2",
|
|
45
45
|
"clsx": "^2.1.1",
|
|
46
46
|
"prop-types": "^15.8.1",
|
|
47
|
-
"use-sync-external-store": "^1.
|
|
47
|
+
"use-sync-external-store": "^1.7.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@emotion/react": "^11.9.0",
|