@mui/x-data-grid 9.10.0 → 9.11.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 +224 -0
- package/README.md +1 -11
- package/components/cell/GridEditInputCell.js +1 -1
- package/components/cell/GridEditInputCell.mjs +1 -1
- package/components/cell/GridEditLongTextCell.js +1 -1
- package/components/cell/GridEditLongTextCell.mjs +1 -1
- package/components/toolbarV8/Toolbar.js +2 -125
- package/components/toolbarV8/Toolbar.mjs +2 -125
- package/components/toolbarV8/ToolbarButton.js +11 -50
- package/components/toolbarV8/ToolbarButton.mjs +11 -50
- package/hooks/features/columnResize/useGridColumnResize.js +3 -0
- package/hooks/features/columnResize/useGridColumnResize.mjs +3 -0
- package/hooks/features/columns/useGridColumns.js +5 -1
- package/hooks/features/columns/useGridColumns.mjs +5 -1
- package/hooks/features/dataSource/useGridDataSourceBase.js +33 -4
- package/hooks/features/dataSource/useGridDataSourceBase.mjs +33 -4
- package/hooks/features/editing/useGridCellEditing.js +9 -3
- package/hooks/features/editing/useGridCellEditing.mjs +9 -3
- package/hooks/features/editing/useGridRowEditing.js +7 -5
- package/hooks/features/editing/useGridRowEditing.mjs +7 -5
- package/hooks/features/filter/useGridFilter.js +1 -1
- package/hooks/features/filter/useGridFilter.mjs +1 -1
- package/hooks/features/rows/gridRowsUtils.js +17 -1
- package/hooks/features/rows/gridRowsUtils.mjs +17 -1
- package/hooks/features/rows/useGridParamsApi.d.mts +1 -1
- package/hooks/features/rows/useGridParamsApi.d.ts +1 -1
- package/hooks/features/rows/useGridParamsApi.js +1 -0
- package/hooks/features/rows/useGridParamsApi.mjs +1 -0
- package/hooks/features/sorting/useGridSorting.js +3 -0
- package/hooks/features/sorting/useGridSorting.mjs +3 -0
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/models/api/gridColumnApi.d.mts +2 -2
- package/models/api/gridColumnApi.d.ts +2 -2
- package/package.json +4 -4
- package/components/toolbarV8/ToolbarContext.d.mts +0 -11
- package/components/toolbarV8/ToolbarContext.d.ts +0 -11
- package/components/toolbarV8/ToolbarContext.js +0 -21
- package/components/toolbarV8/ToolbarContext.mjs +0 -13
- package/components/toolbarV8/utils.d.mts +0 -5
- package/components/toolbarV8/utils.d.ts +0 -5
- package/components/toolbarV8/utils.js +0 -23
- package/components/toolbarV8/utils.mjs +0 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,229 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.11.0
|
|
4
|
+
|
|
5
|
+
_Aug 6, 2026_
|
|
6
|
+
|
|
7
|
+
We'd like to extend a big thank you to the 14 contributors who made this release possible. Here are some highlights ✨:
|
|
8
|
+
|
|
9
|
+
- ✨ Add `addItems()` and `getItemSelection()` API methods to Tree View
|
|
10
|
+
|
|
11
|
+
Special thanks go out to these community members for their valuable contributions:
|
|
12
|
+
@12joan, @Anexus5919, @kevincorizi-sbt, @mixelburg, @mustafajw07, @strazto
|
|
13
|
+
|
|
14
|
+
The following team members contributed to this release:
|
|
15
|
+
@flaviendelangle, @hasdfa, @JCQuintas, @LukasTy, @MBilalShafi, @michelengelen, @noraleonte, @rita-codes
|
|
16
|
+
|
|
17
|
+
### Data Grid
|
|
18
|
+
|
|
19
|
+
#### `@mui/x-data-grid@9.11.0`
|
|
20
|
+
|
|
21
|
+
- [DataGrid] Fix `updateRows` stripping class prototypes from rows in datasource mode (#22288) @mixelburg
|
|
22
|
+
- [DataGrid] Do not re-fetch data when an `Activity` becomes visible (#22603) @12joan
|
|
23
|
+
- [DataGrid] Fix toolbar button stealing focus when a sibling's disabled state changes (#23204) @MBilalShafi
|
|
24
|
+
|
|
25
|
+
#### `@mui/x-data-grid-pro@9.11.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
26
|
+
|
|
27
|
+
Same changes as in `@mui/x-data-grid@9.11.0`.
|
|
28
|
+
|
|
29
|
+
#### `@mui/x-data-grid-premium@9.11.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
30
|
+
|
|
31
|
+
Same changes as in `@mui/x-data-grid-pro@9.11.0`.
|
|
32
|
+
|
|
33
|
+
### Date and Time Pickers
|
|
34
|
+
|
|
35
|
+
#### `@mui/x-date-pickers@9.11.0`
|
|
36
|
+
|
|
37
|
+
- [pickers] Fix day shift when editing dates predating timezone standardization (#23296) @JCQuintas
|
|
38
|
+
|
|
39
|
+
#### `@mui/x-date-pickers-pro@9.11.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
40
|
+
|
|
41
|
+
Same changes as in `@mui/x-date-pickers@9.11.0`, plus:
|
|
42
|
+
|
|
43
|
+
- [DateRangePicker] Fix disabled filler cells showing the range highlight (#23293) @JCQuintas
|
|
44
|
+
|
|
45
|
+
### Charts
|
|
46
|
+
|
|
47
|
+
#### `@mui/x-charts@9.11.0`
|
|
48
|
+
|
|
49
|
+
- [charts] Activate the focused item with `Enter`/`Space` (#23218) @JCQuintas
|
|
50
|
+
- [charts] Extract the axis click payload builders (#23215) @JCQuintas
|
|
51
|
+
- [charts] Fix `GestureManager` event listener leak on chart unmount (#23283) @kevincorizi-sbt
|
|
52
|
+
- [charts] Fix `slotProps.legend.position` and `direction` in `RadarChart` (#23254) @JCQuintas
|
|
53
|
+
- [charts] Fix axis clicks being discarded on slight pointer movement (#23244) @noraleonte
|
|
54
|
+
- [charts] Fix image export of charts sized by their parent element (#23255) @JCQuintas
|
|
55
|
+
- [charts] Forward `experimentalFeatures` on `RadarChart` and `Heatmap` (#23216) @JCQuintas
|
|
56
|
+
- [charts] Hide focus indicator when the chart loses focus (#23213) @JCQuintas
|
|
57
|
+
|
|
58
|
+
#### `@mui/x-charts-pro@9.11.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
59
|
+
|
|
60
|
+
Same changes as in `@mui/x-charts@9.11.0`.
|
|
61
|
+
|
|
62
|
+
#### `@mui/x-charts-premium@9.11.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
63
|
+
|
|
64
|
+
Same changes as in `@mui/x-charts-pro@9.11.0`, plus:
|
|
65
|
+
|
|
66
|
+
- [charts-premium] Fix `RangeBar` type override (#23217) @JCQuintas
|
|
67
|
+
|
|
68
|
+
### Tree View
|
|
69
|
+
|
|
70
|
+
#### `@mui/x-tree-view@9.11.0`
|
|
71
|
+
|
|
72
|
+
- [tree view] Add `addItems()` API method (#23159) @JCQuintas
|
|
73
|
+
- [tree view] Add `getItemSelection` API method (#23257) @noraleonte
|
|
74
|
+
- [tree view] Ignore `keepExistingSelection` when `multiSelect` is `false` (#23242) @JCQuintas
|
|
75
|
+
- [tree view] Prevent duplicate ids in multi-select arrow navigation (#23006) @Anexus5919
|
|
76
|
+
|
|
77
|
+
#### `@mui/x-tree-view-pro@9.11.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
78
|
+
|
|
79
|
+
Same changes as in `@mui/x-tree-view@9.11.0`, plus:
|
|
80
|
+
|
|
81
|
+
- [tree view] Discard superseded lazy-loading responses (#23005) @Anexus5919
|
|
82
|
+
|
|
83
|
+
### Scheduler
|
|
84
|
+
|
|
85
|
+
#### `@mui/x-scheduler@9.0.0-beta.8`
|
|
86
|
+
|
|
87
|
+
- [scheduler] Add `localeText` prop to standalone views (#23210) @rita-codes
|
|
88
|
+
- [scheduler] Finetune touch experience for time grid events and introduce editing drawer (#22624) @noraleonte
|
|
89
|
+
- [scheduler] Introduce the edit dialog form context & lifecycle contract (#23284) @rita-codes
|
|
90
|
+
- [scheduler] Refactor edit dialog General tab into section components (#23206) @rita-codes
|
|
91
|
+
- [scheduler] Replace copied Base UI internals with `@base-ui/react/internals` imports (#21972) @flaviendelangle
|
|
92
|
+
- [scheduler] Hide resource picker when no resources are provided (#23290) @mustafajw07
|
|
93
|
+
- [scheduler] Support multi-resource occurrences in `EventTimeline` (#23240) @mustafajw07
|
|
94
|
+
|
|
95
|
+
#### `@mui/x-scheduler-premium@9.0.0-beta.8` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
96
|
+
|
|
97
|
+
Same changes as in `@mui/x-scheduler@9.0.0-beta.8`.
|
|
98
|
+
|
|
99
|
+
### Codemod
|
|
100
|
+
|
|
101
|
+
#### `@mui/x-codemod@9.11.0`
|
|
102
|
+
|
|
103
|
+
- [codemod] Remove unused `@babel/core` and `@babel/traverse` dependencies (#23245) @LukasTy
|
|
104
|
+
|
|
105
|
+
### Docs
|
|
106
|
+
|
|
107
|
+
- [docs] Add recipe for adding new rows from clipboard copy (#22913) @michelengelen
|
|
108
|
+
- [docs] Clarify the package versions in v8 upgrade guides (#22376) @strazto
|
|
109
|
+
- [docs] Replace README peer dependency lists with an npm install command (#23256) @LukasTy
|
|
110
|
+
|
|
111
|
+
### Core
|
|
112
|
+
|
|
113
|
+
- [code-infra] Align action pin version comments (#23238) @LukasTy
|
|
114
|
+
|
|
115
|
+
### Miscellaneous
|
|
116
|
+
|
|
117
|
+
- [chat] Drop the undeclared `@mui/icons-material` dependency (#23252) @LukasTy
|
|
118
|
+
- [chat] Sanitize image part URLs and share the URL allow-list with markdown (#23058) @hasdfa
|
|
119
|
+
- [test] Type the `PickersTextField` test stub instead of `as any` (#23194) @LukasTy
|
|
120
|
+
|
|
121
|
+
## 9.10.1
|
|
122
|
+
|
|
123
|
+
_Jul 23, 2026_
|
|
124
|
+
|
|
125
|
+
We'd like to extend a big thank you to the 11 contributors who made this release possible. Here are some highlights ✨:
|
|
126
|
+
|
|
127
|
+
- 🦮 Improve accessibility of the Charts and Pickers components.
|
|
128
|
+
- 🐞 Bugfixes
|
|
129
|
+
- 📚 Documentation improvements
|
|
130
|
+
|
|
131
|
+
Special thanks go out to these community members for their valuable contributions:
|
|
132
|
+
@kevincorizi-sbt, @mustafajw07, @SamanPandey-in
|
|
133
|
+
|
|
134
|
+
The following team members contributed to this release:
|
|
135
|
+
@brijeshb42, @hasdfa, @JCQuintas, @LukasTy, @michelengelen, @noraleonte, @rita-codes, @silviuaavram
|
|
136
|
+
|
|
137
|
+
### Data Grid
|
|
138
|
+
|
|
139
|
+
#### `@mui/x-data-grid@9.10.1`
|
|
140
|
+
|
|
141
|
+
- [data grid] Fix `getColumn` return type not reflecting that it can return undefined (#23165) @JCQuintas
|
|
142
|
+
|
|
143
|
+
#### `@mui/x-data-grid-pro@9.10.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
144
|
+
|
|
145
|
+
Same changes as in `@mui/x-data-grid@9.10.1`.
|
|
146
|
+
|
|
147
|
+
#### `@mui/x-data-grid-premium@9.10.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
148
|
+
|
|
149
|
+
Same changes as in `@mui/x-data-grid-pro@9.10.1`.
|
|
150
|
+
|
|
151
|
+
### Date and Time Pickers
|
|
152
|
+
|
|
153
|
+
#### `@mui/x-date-pickers@9.10.1`
|
|
154
|
+
|
|
155
|
+
- [pickers] Fix format placeholder brightness with a start adornment (#23189) @LukasTy
|
|
156
|
+
|
|
157
|
+
#### `@mui/x-date-pickers-pro@9.10.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
158
|
+
|
|
159
|
+
Same changes as in `@mui/x-date-pickers@9.10.1`, plus:
|
|
160
|
+
|
|
161
|
+
- [DateRangePicker] Fix broken active range position underline in single input range fields (#23166) @LukasTy
|
|
162
|
+
|
|
163
|
+
### Charts
|
|
164
|
+
|
|
165
|
+
#### `@mui/x-charts@9.10.1`
|
|
166
|
+
|
|
167
|
+
- [charts] Fix pie chart disappearing when an arc spans almost the full circle (#23145) @JCQuintas
|
|
168
|
+
- [charts] Set `aria-hidden` on accessibility proxy divs at initialization (#23186) @kevincorizi-sbt
|
|
169
|
+
- [charts] Fix keyboard navigation on series with different lengths (#23182) @JCQuintas
|
|
170
|
+
- [charts] Fix out of bounds keyboard navigation (#23180) @silviuaavram
|
|
171
|
+
|
|
172
|
+
#### `@mui/x-charts-pro@9.10.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
173
|
+
|
|
174
|
+
Same changes as in `@mui/x-charts@9.10.1`, plus:
|
|
175
|
+
|
|
176
|
+
- [charts-pro] Fix highlight shifting on sampled bar charts (#23190) @noraleonte
|
|
177
|
+
- [charts-pro] Sampled band highlight falls back to single-band width for Date/object values (#23024) @SamanPandey-in
|
|
178
|
+
|
|
179
|
+
#### `@mui/x-charts-premium@9.10.1` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
180
|
+
|
|
181
|
+
Same changes as in `@mui/x-charts-pro@9.10.1`.
|
|
182
|
+
|
|
183
|
+
### Tree View
|
|
184
|
+
|
|
185
|
+
#### `@mui/x-tree-view@9.10.1`
|
|
186
|
+
|
|
187
|
+
- [TreeView] Fix selection propagation to exclude disabled items (#23012) @michelengelen
|
|
188
|
+
|
|
189
|
+
#### `@mui/x-tree-view-pro@9.10.1` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
190
|
+
|
|
191
|
+
Same changes as in `@mui/x-tree-view@9.10.1`.
|
|
192
|
+
|
|
193
|
+
### Scheduler
|
|
194
|
+
|
|
195
|
+
#### `@mui/x-scheduler@9.0.0-beta.7`
|
|
196
|
+
|
|
197
|
+
- [scheduler] Polish `EventCalendar` rendering for multi-resource events (#23161) @mustafajw07
|
|
198
|
+
- [scheduler] Responsive header (#22954) @noraleonte
|
|
199
|
+
|
|
200
|
+
#### `@mui/x-scheduler-premium@9.0.0-beta.7` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
201
|
+
|
|
202
|
+
Same changes as in `@mui/x-scheduler@9.0.0-beta.7`, plus:
|
|
203
|
+
|
|
204
|
+
- [scheduler-premium] Add the dependencies data model (#23117) @rita-codes
|
|
205
|
+
- [scheduler-premium] Dependencies - Render the FS arrow (#23162) @rita-codes
|
|
206
|
+
|
|
207
|
+
### Codemod
|
|
208
|
+
|
|
209
|
+
#### `@mui/x-codemod@9.10.1`
|
|
210
|
+
|
|
211
|
+
Internal changes.
|
|
212
|
+
|
|
213
|
+
### Docs
|
|
214
|
+
|
|
215
|
+
- [docs] Fix clearing, layout shift, and prop leak in Pickers demos (#23191) @LukasTy
|
|
216
|
+
|
|
217
|
+
### Core
|
|
218
|
+
|
|
219
|
+
- [code-infra] Validate working of specific code-infra canary (#23207) @brijeshb42
|
|
220
|
+
|
|
221
|
+
### Miscellaneous
|
|
222
|
+
|
|
223
|
+
- [chat] Normalize message part link URLs (#23187) @hasdfa
|
|
224
|
+
- [x-chat] Fix object URL leaks for submitted attachments (#23198) @hasdfa
|
|
225
|
+
- [internals] Make disposable types self-contained without `esnext.disposable` lib (#23164) @JCQuintas
|
|
226
|
+
|
|
3
227
|
## 9.10.0
|
|
4
228
|
|
|
5
229
|
_Jul 17, 2026_
|
package/README.md
CHANGED
|
@@ -8,17 +8,7 @@ It's part of [MUI X](https://mui.com/x/), an open-core extension of our Core li
|
|
|
8
8
|
Install the package in your project directory with:
|
|
9
9
|
|
|
10
10
|
```bash
|
|
11
|
-
npm install @mui/x-data-grid
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
This component has the following peer dependencies that you need to install as well.
|
|
15
|
-
|
|
16
|
-
```json
|
|
17
|
-
"peerDependencies": {
|
|
18
|
-
"@mui/material": "^5.15.14 || ^6.0.0 || ^7.0.0",
|
|
19
|
-
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
20
|
-
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
21
|
-
},
|
|
11
|
+
npm install @mui/x-data-grid @mui/material @emotion/react @emotion/styled
|
|
22
12
|
```
|
|
23
13
|
|
|
24
14
|
## Documentation
|
|
@@ -64,7 +64,7 @@ const GridEditInputCell = exports.GridEditInputCell = (0, _forwardRef.forwardRef
|
|
|
64
64
|
const newValue = event.target.value;
|
|
65
65
|
const column = apiRef.current.getColumn(field);
|
|
66
66
|
let parsedValue = newValue;
|
|
67
|
-
if (column
|
|
67
|
+
if (column?.valueParser) {
|
|
68
68
|
parsedValue = column.valueParser(newValue, apiRef.current.getRow(id), column, apiRef);
|
|
69
69
|
}
|
|
70
70
|
setValueState(parsedValue);
|
|
@@ -57,7 +57,7 @@ const GridEditInputCell = forwardRef((props, ref) => {
|
|
|
57
57
|
const newValue = event.target.value;
|
|
58
58
|
const column = apiRef.current.getColumn(field);
|
|
59
59
|
let parsedValue = newValue;
|
|
60
|
-
if (column
|
|
60
|
+
if (column?.valueParser) {
|
|
61
61
|
parsedValue = column.valueParser(newValue, apiRef.current.getRow(id), column, apiRef);
|
|
62
62
|
}
|
|
63
63
|
setValueState(parsedValue);
|
|
@@ -274,7 +274,7 @@ function GridEditLongTextarea(props) {
|
|
|
274
274
|
const newValue = event.target.value;
|
|
275
275
|
const column = apiRef.current.getColumn(field);
|
|
276
276
|
let parsedValue = newValue;
|
|
277
|
-
if (column
|
|
277
|
+
if (column?.valueParser) {
|
|
278
278
|
parsedValue = column.valueParser(newValue, apiRef.current.getRow(id), column, apiRef);
|
|
279
279
|
}
|
|
280
280
|
setValueState(parsedValue);
|
|
@@ -266,7 +266,7 @@ function GridEditLongTextarea(props) {
|
|
|
266
266
|
const newValue = event.target.value;
|
|
267
267
|
const column = apiRef.current.getColumn(field);
|
|
268
268
|
let parsedValue = newValue;
|
|
269
|
-
if (column
|
|
269
|
+
if (column?.valueParser) {
|
|
270
270
|
parsedValue = column.valueParser(newValue, apiRef.current.getRow(id), column, apiRef);
|
|
271
271
|
}
|
|
272
272
|
setValueState(parsedValue);
|
|
@@ -16,11 +16,10 @@ var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"
|
|
|
16
16
|
var _clsx = _interopRequireDefault(require("clsx"));
|
|
17
17
|
var _forwardRef = require("@mui/x-internals/forwardRef");
|
|
18
18
|
var _useComponentRenderer = require("@mui/x-internals/useComponentRenderer");
|
|
19
|
+
var _ToolbarContext = require("@mui/x-internals/ToolbarContext");
|
|
19
20
|
var _cssVariables = require("../../constants/cssVariables");
|
|
20
21
|
var _gridClasses = require("../../constants/gridClasses");
|
|
21
|
-
var _ToolbarContext = require("./ToolbarContext");
|
|
22
22
|
var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
|
|
23
|
-
var _utils = require("./utils");
|
|
24
23
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
24
|
const _excluded = ["render", "className"];
|
|
26
25
|
const useUtilityClasses = ownerState => {
|
|
@@ -67,127 +66,6 @@ const Toolbar = exports.Toolbar = (0, _forwardRef.forwardRef)(function Toolbar(p
|
|
|
67
66
|
other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
|
|
68
67
|
const rootProps = (0, _useGridRootProps.useGridRootProps)();
|
|
69
68
|
const classes = useUtilityClasses(rootProps);
|
|
70
|
-
const [focusableItemId, setFocusableItemId] = React.useState(null);
|
|
71
|
-
const [items, setItems] = React.useState([]);
|
|
72
|
-
const getSortedItems = React.useCallback(() => items.sort(_utils.sortByDocumentPosition), [items]);
|
|
73
|
-
const findEnabledItem = React.useCallback((startIndex, step, wrap = true) => {
|
|
74
|
-
let index = startIndex;
|
|
75
|
-
const sortedItems = getSortedItems();
|
|
76
|
-
const itemCount = sortedItems.length;
|
|
77
|
-
|
|
78
|
-
// Look for enabled items in the specified direction
|
|
79
|
-
for (let i = 0; i < itemCount; i += 1) {
|
|
80
|
-
index += step;
|
|
81
|
-
|
|
82
|
-
// Handle wrapping around the ends
|
|
83
|
-
if (index >= itemCount) {
|
|
84
|
-
if (!wrap) {
|
|
85
|
-
return -1;
|
|
86
|
-
}
|
|
87
|
-
index = 0;
|
|
88
|
-
} else if (index < 0) {
|
|
89
|
-
if (!wrap) {
|
|
90
|
-
return -1;
|
|
91
|
-
}
|
|
92
|
-
index = itemCount - 1;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Return if we found an enabled item
|
|
96
|
-
if (!sortedItems[index].ref.current?.disabled && sortedItems[index].ref.current?.ariaDisabled !== 'true') {
|
|
97
|
-
return index;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// If we've checked all items and found none enabled
|
|
102
|
-
return -1;
|
|
103
|
-
}, [getSortedItems]);
|
|
104
|
-
const registerItem = React.useCallback((id, itemRef) => {
|
|
105
|
-
setItems(prevItems => [...prevItems, {
|
|
106
|
-
id,
|
|
107
|
-
ref: itemRef
|
|
108
|
-
}]);
|
|
109
|
-
}, []);
|
|
110
|
-
const unregisterItem = React.useCallback(id => {
|
|
111
|
-
setItems(prevItems => prevItems.filter(i => i.id !== id));
|
|
112
|
-
}, []);
|
|
113
|
-
const onItemKeyDown = React.useCallback(event => {
|
|
114
|
-
if (!focusableItemId) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
const sortedItems = getSortedItems();
|
|
118
|
-
const focusableItemIndex = sortedItems.findIndex(item => item.id === focusableItemId);
|
|
119
|
-
let newIndex = -1;
|
|
120
|
-
if (event.key === 'ArrowRight') {
|
|
121
|
-
event.preventDefault();
|
|
122
|
-
newIndex = findEnabledItem(focusableItemIndex, 1);
|
|
123
|
-
} else if (event.key === 'ArrowLeft') {
|
|
124
|
-
event.preventDefault();
|
|
125
|
-
newIndex = findEnabledItem(focusableItemIndex, -1);
|
|
126
|
-
} else if (event.key === 'Home') {
|
|
127
|
-
event.preventDefault();
|
|
128
|
-
newIndex = findEnabledItem(-1, 1, false);
|
|
129
|
-
} else if (event.key === 'End') {
|
|
130
|
-
event.preventDefault();
|
|
131
|
-
newIndex = findEnabledItem(sortedItems.length, -1, false);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// TODO: Check why this is necessary
|
|
135
|
-
if (newIndex >= 0 && newIndex < sortedItems.length) {
|
|
136
|
-
const item = sortedItems[newIndex];
|
|
137
|
-
setFocusableItemId(item.id);
|
|
138
|
-
item.ref.current?.focus();
|
|
139
|
-
}
|
|
140
|
-
}, [getSortedItems, focusableItemId, findEnabledItem]);
|
|
141
|
-
const onItemFocus = React.useCallback(id => {
|
|
142
|
-
if (focusableItemId !== id) {
|
|
143
|
-
setFocusableItemId(id);
|
|
144
|
-
}
|
|
145
|
-
}, [focusableItemId, setFocusableItemId]);
|
|
146
|
-
const onItemDisabled = React.useCallback(id => {
|
|
147
|
-
const sortedItems = getSortedItems();
|
|
148
|
-
const currentIndex = sortedItems.findIndex(item => item.id === id);
|
|
149
|
-
const newIndex = findEnabledItem(currentIndex, 1);
|
|
150
|
-
if (newIndex >= 0 && newIndex < sortedItems.length) {
|
|
151
|
-
const item = sortedItems[newIndex];
|
|
152
|
-
setFocusableItemId(item.id);
|
|
153
|
-
item.ref.current?.focus();
|
|
154
|
-
}
|
|
155
|
-
}, [getSortedItems, findEnabledItem]);
|
|
156
|
-
React.useEffect(() => {
|
|
157
|
-
const sortedItems = getSortedItems();
|
|
158
|
-
if (sortedItems.length > 0) {
|
|
159
|
-
// Set initial focusable item
|
|
160
|
-
if (!focusableItemId) {
|
|
161
|
-
setFocusableItemId(sortedItems[0].id);
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const focusableItemIndex = sortedItems.findIndex(item => item.id === focusableItemId);
|
|
165
|
-
if (!sortedItems[focusableItemIndex]) {
|
|
166
|
-
// Last item has been removed from the items array
|
|
167
|
-
const item = sortedItems[sortedItems.length - 1];
|
|
168
|
-
if (item) {
|
|
169
|
-
setFocusableItemId(item.id);
|
|
170
|
-
item.ref.current?.focus();
|
|
171
|
-
}
|
|
172
|
-
} else if (focusableItemIndex === -1) {
|
|
173
|
-
// Focused item has been removed from the items array
|
|
174
|
-
const item = sortedItems[focusableItemIndex];
|
|
175
|
-
if (item) {
|
|
176
|
-
setFocusableItemId(item.id);
|
|
177
|
-
item.ref.current?.focus();
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
182
|
-
}, [getSortedItems, findEnabledItem]);
|
|
183
|
-
const contextValue = React.useMemo(() => ({
|
|
184
|
-
focusableItemId,
|
|
185
|
-
registerItem,
|
|
186
|
-
unregisterItem,
|
|
187
|
-
onItemKeyDown,
|
|
188
|
-
onItemFocus,
|
|
189
|
-
onItemDisabled
|
|
190
|
-
}), [focusableItemId, registerItem, unregisterItem, onItemKeyDown, onItemFocus, onItemDisabled]);
|
|
191
69
|
const element = (0, _useComponentRenderer.useComponentRenderer)(ToolbarRoot, render, (0, _extends2.default)({
|
|
192
70
|
role: 'toolbar',
|
|
193
71
|
'aria-orientation': 'horizontal',
|
|
@@ -196,8 +74,7 @@ const Toolbar = exports.Toolbar = (0, _forwardRef.forwardRef)(function Toolbar(p
|
|
|
196
74
|
}, other, {
|
|
197
75
|
ref
|
|
198
76
|
}));
|
|
199
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ToolbarContext.
|
|
200
|
-
value: contextValue,
|
|
77
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ToolbarContext.ToolbarContextProvider, {
|
|
201
78
|
children: element
|
|
202
79
|
});
|
|
203
80
|
});
|
|
@@ -10,11 +10,10 @@ import composeClasses from '@mui/utils/composeClasses';
|
|
|
10
10
|
import clsx from 'clsx';
|
|
11
11
|
import { forwardRef } from '@mui/x-internals/forwardRef';
|
|
12
12
|
import { useComponentRenderer } from '@mui/x-internals/useComponentRenderer';
|
|
13
|
+
import { ToolbarContextProvider } from '@mui/x-internals/ToolbarContext';
|
|
13
14
|
import { vars } from "../../constants/cssVariables.mjs";
|
|
14
15
|
import { getDataGridUtilityClass } from "../../constants/gridClasses.mjs";
|
|
15
|
-
import { ToolbarContext } from "./ToolbarContext.mjs";
|
|
16
16
|
import { useGridRootProps } from "../../hooks/utils/useGridRootProps.mjs";
|
|
17
|
-
import { sortByDocumentPosition } from "./utils.mjs";
|
|
18
17
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
19
18
|
const useUtilityClasses = ownerState => {
|
|
20
19
|
const {
|
|
@@ -60,127 +59,6 @@ const Toolbar = forwardRef(function Toolbar(props, ref) {
|
|
|
60
59
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
61
60
|
const rootProps = useGridRootProps();
|
|
62
61
|
const classes = useUtilityClasses(rootProps);
|
|
63
|
-
const [focusableItemId, setFocusableItemId] = React.useState(null);
|
|
64
|
-
const [items, setItems] = React.useState([]);
|
|
65
|
-
const getSortedItems = React.useCallback(() => items.sort(sortByDocumentPosition), [items]);
|
|
66
|
-
const findEnabledItem = React.useCallback((startIndex, step, wrap = true) => {
|
|
67
|
-
let index = startIndex;
|
|
68
|
-
const sortedItems = getSortedItems();
|
|
69
|
-
const itemCount = sortedItems.length;
|
|
70
|
-
|
|
71
|
-
// Look for enabled items in the specified direction
|
|
72
|
-
for (let i = 0; i < itemCount; i += 1) {
|
|
73
|
-
index += step;
|
|
74
|
-
|
|
75
|
-
// Handle wrapping around the ends
|
|
76
|
-
if (index >= itemCount) {
|
|
77
|
-
if (!wrap) {
|
|
78
|
-
return -1;
|
|
79
|
-
}
|
|
80
|
-
index = 0;
|
|
81
|
-
} else if (index < 0) {
|
|
82
|
-
if (!wrap) {
|
|
83
|
-
return -1;
|
|
84
|
-
}
|
|
85
|
-
index = itemCount - 1;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Return if we found an enabled item
|
|
89
|
-
if (!sortedItems[index].ref.current?.disabled && sortedItems[index].ref.current?.ariaDisabled !== 'true') {
|
|
90
|
-
return index;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// If we've checked all items and found none enabled
|
|
95
|
-
return -1;
|
|
96
|
-
}, [getSortedItems]);
|
|
97
|
-
const registerItem = React.useCallback((id, itemRef) => {
|
|
98
|
-
setItems(prevItems => [...prevItems, {
|
|
99
|
-
id,
|
|
100
|
-
ref: itemRef
|
|
101
|
-
}]);
|
|
102
|
-
}, []);
|
|
103
|
-
const unregisterItem = React.useCallback(id => {
|
|
104
|
-
setItems(prevItems => prevItems.filter(i => i.id !== id));
|
|
105
|
-
}, []);
|
|
106
|
-
const onItemKeyDown = React.useCallback(event => {
|
|
107
|
-
if (!focusableItemId) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const sortedItems = getSortedItems();
|
|
111
|
-
const focusableItemIndex = sortedItems.findIndex(item => item.id === focusableItemId);
|
|
112
|
-
let newIndex = -1;
|
|
113
|
-
if (event.key === 'ArrowRight') {
|
|
114
|
-
event.preventDefault();
|
|
115
|
-
newIndex = findEnabledItem(focusableItemIndex, 1);
|
|
116
|
-
} else if (event.key === 'ArrowLeft') {
|
|
117
|
-
event.preventDefault();
|
|
118
|
-
newIndex = findEnabledItem(focusableItemIndex, -1);
|
|
119
|
-
} else if (event.key === 'Home') {
|
|
120
|
-
event.preventDefault();
|
|
121
|
-
newIndex = findEnabledItem(-1, 1, false);
|
|
122
|
-
} else if (event.key === 'End') {
|
|
123
|
-
event.preventDefault();
|
|
124
|
-
newIndex = findEnabledItem(sortedItems.length, -1, false);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// TODO: Check why this is necessary
|
|
128
|
-
if (newIndex >= 0 && newIndex < sortedItems.length) {
|
|
129
|
-
const item = sortedItems[newIndex];
|
|
130
|
-
setFocusableItemId(item.id);
|
|
131
|
-
item.ref.current?.focus();
|
|
132
|
-
}
|
|
133
|
-
}, [getSortedItems, focusableItemId, findEnabledItem]);
|
|
134
|
-
const onItemFocus = React.useCallback(id => {
|
|
135
|
-
if (focusableItemId !== id) {
|
|
136
|
-
setFocusableItemId(id);
|
|
137
|
-
}
|
|
138
|
-
}, [focusableItemId, setFocusableItemId]);
|
|
139
|
-
const onItemDisabled = React.useCallback(id => {
|
|
140
|
-
const sortedItems = getSortedItems();
|
|
141
|
-
const currentIndex = sortedItems.findIndex(item => item.id === id);
|
|
142
|
-
const newIndex = findEnabledItem(currentIndex, 1);
|
|
143
|
-
if (newIndex >= 0 && newIndex < sortedItems.length) {
|
|
144
|
-
const item = sortedItems[newIndex];
|
|
145
|
-
setFocusableItemId(item.id);
|
|
146
|
-
item.ref.current?.focus();
|
|
147
|
-
}
|
|
148
|
-
}, [getSortedItems, findEnabledItem]);
|
|
149
|
-
React.useEffect(() => {
|
|
150
|
-
const sortedItems = getSortedItems();
|
|
151
|
-
if (sortedItems.length > 0) {
|
|
152
|
-
// Set initial focusable item
|
|
153
|
-
if (!focusableItemId) {
|
|
154
|
-
setFocusableItemId(sortedItems[0].id);
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
const focusableItemIndex = sortedItems.findIndex(item => item.id === focusableItemId);
|
|
158
|
-
if (!sortedItems[focusableItemIndex]) {
|
|
159
|
-
// Last item has been removed from the items array
|
|
160
|
-
const item = sortedItems[sortedItems.length - 1];
|
|
161
|
-
if (item) {
|
|
162
|
-
setFocusableItemId(item.id);
|
|
163
|
-
item.ref.current?.focus();
|
|
164
|
-
}
|
|
165
|
-
} else if (focusableItemIndex === -1) {
|
|
166
|
-
// Focused item has been removed from the items array
|
|
167
|
-
const item = sortedItems[focusableItemIndex];
|
|
168
|
-
if (item) {
|
|
169
|
-
setFocusableItemId(item.id);
|
|
170
|
-
item.ref.current?.focus();
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
175
|
-
}, [getSortedItems, findEnabledItem]);
|
|
176
|
-
const contextValue = React.useMemo(() => ({
|
|
177
|
-
focusableItemId,
|
|
178
|
-
registerItem,
|
|
179
|
-
unregisterItem,
|
|
180
|
-
onItemKeyDown,
|
|
181
|
-
onItemFocus,
|
|
182
|
-
onItemDisabled
|
|
183
|
-
}), [focusableItemId, registerItem, unregisterItem, onItemKeyDown, onItemFocus, onItemDisabled]);
|
|
184
62
|
const element = useComponentRenderer(ToolbarRoot, render, _extends({
|
|
185
63
|
role: 'toolbar',
|
|
186
64
|
'aria-orientation': 'horizontal',
|
|
@@ -189,8 +67,7 @@ const Toolbar = forwardRef(function Toolbar(props, ref) {
|
|
|
189
67
|
}, other, {
|
|
190
68
|
ref
|
|
191
69
|
}));
|
|
192
|
-
return /*#__PURE__*/_jsx(
|
|
193
|
-
value: contextValue,
|
|
70
|
+
return /*#__PURE__*/_jsx(ToolbarContextProvider, {
|
|
194
71
|
children: element
|
|
195
72
|
});
|
|
196
73
|
});
|
|
@@ -12,13 +12,13 @@ var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runt
|
|
|
12
12
|
var React = _interopRequireWildcard(require("react"));
|
|
13
13
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
14
14
|
var _useForkRef = _interopRequireDefault(require("@mui/utils/useForkRef"));
|
|
15
|
-
var _useId = _interopRequireDefault(require("@mui/utils/useId"));
|
|
16
15
|
var _forwardRef = require("@mui/x-internals/forwardRef");
|
|
17
16
|
var _useComponentRenderer = require("@mui/x-internals/useComponentRenderer");
|
|
17
|
+
var _ToolbarContext = require("@mui/x-internals/ToolbarContext");
|
|
18
18
|
var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
|
|
19
|
-
var _ToolbarContext = require("./ToolbarContext");
|
|
20
19
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
|
-
const _excluded = ["render", "onKeyDown", "onFocus", "disabled", "aria-disabled"]
|
|
20
|
+
const _excluded = ["render", "onKeyDown", "onFocus", "onBlur", "disabled", "aria-disabled"],
|
|
21
|
+
_excluded2 = ["tabIndex"];
|
|
22
22
|
/**
|
|
23
23
|
* A button for performing actions from the toolbar.
|
|
24
24
|
* It renders the `baseIconButton` slot.
|
|
@@ -33,59 +33,20 @@ const _excluded = ["render", "onKeyDown", "onFocus", "disabled", "aria-disabled"
|
|
|
33
33
|
*/
|
|
34
34
|
const ToolbarButton = exports.ToolbarButton = (0, _forwardRef.forwardRef)(function ToolbarButton(props, ref) {
|
|
35
35
|
const {
|
|
36
|
-
render
|
|
37
|
-
onKeyDown,
|
|
38
|
-
onFocus,
|
|
39
|
-
disabled,
|
|
40
|
-
'aria-disabled': ariaDisabled
|
|
36
|
+
render
|
|
41
37
|
} = props,
|
|
42
38
|
other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
|
|
43
|
-
const id = (0, _useId.default)();
|
|
44
39
|
const rootProps = (0, _useGridRootProps.useGridRootProps)();
|
|
45
40
|
const buttonRef = React.useRef(null);
|
|
46
41
|
const handleRef = (0, _useForkRef.default)(buttonRef, ref);
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
onItemFocus,
|
|
53
|
-
onItemDisabled
|
|
54
|
-
} = (0, _ToolbarContext.useToolbarContext)();
|
|
55
|
-
const handleKeyDown = event => {
|
|
56
|
-
onItemKeyDown(event);
|
|
57
|
-
onKeyDown?.(event);
|
|
58
|
-
};
|
|
59
|
-
const handleFocus = event => {
|
|
60
|
-
onItemFocus(id);
|
|
61
|
-
onFocus?.(event);
|
|
62
|
-
};
|
|
63
|
-
React.useEffect(() => {
|
|
64
|
-
registerItem(id, buttonRef);
|
|
65
|
-
return () => unregisterItem(id);
|
|
66
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
-
}, []);
|
|
68
|
-
const previousDisabled = React.useRef(disabled);
|
|
69
|
-
React.useEffect(() => {
|
|
70
|
-
if (previousDisabled.current !== disabled && disabled === true) {
|
|
71
|
-
onItemDisabled(id, disabled);
|
|
72
|
-
}
|
|
73
|
-
previousDisabled.current = disabled;
|
|
74
|
-
}, [disabled, id, onItemDisabled]);
|
|
75
|
-
const previousAriaDisabled = React.useRef(ariaDisabled);
|
|
76
|
-
React.useEffect(() => {
|
|
77
|
-
if (previousAriaDisabled.current !== ariaDisabled && ariaDisabled === true) {
|
|
78
|
-
onItemDisabled(id, true);
|
|
79
|
-
}
|
|
80
|
-
previousAriaDisabled.current = ariaDisabled;
|
|
81
|
-
}, [ariaDisabled, id, onItemDisabled]);
|
|
42
|
+
const _useRegisterToolbarBu = (0, _ToolbarContext.useRegisterToolbarButton)(props, buttonRef),
|
|
43
|
+
{
|
|
44
|
+
tabIndex
|
|
45
|
+
} = _useRegisterToolbarBu,
|
|
46
|
+
toolbarButtonProps = (0, _objectWithoutPropertiesLoose2.default)(_useRegisterToolbarBu, _excluded2);
|
|
82
47
|
const element = (0, _useComponentRenderer.useComponentRenderer)(rootProps.slots.baseIconButton, render, (0, _extends2.default)({}, rootProps.slotProps?.baseIconButton, {
|
|
83
|
-
tabIndex
|
|
84
|
-
}, other, {
|
|
85
|
-
disabled,
|
|
86
|
-
'aria-disabled': ariaDisabled,
|
|
87
|
-
onKeyDown: handleKeyDown,
|
|
88
|
-
onFocus: handleFocus,
|
|
48
|
+
tabIndex
|
|
49
|
+
}, other, toolbarButtonProps, {
|
|
89
50
|
ref: handleRef
|
|
90
51
|
}));
|
|
91
52
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(React.Fragment, {
|