@mui/x-data-grid 9.12.0 → 9.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +301 -0
- package/DataGrid/DataGrid.js +1 -1
- package/DataGrid/DataGrid.mjs +1 -1
- package/components/GridPagination.js +1 -1
- package/components/GridPagination.mjs +1 -1
- package/components/GridRow.d.mts +1 -0
- package/components/GridRow.d.ts +1 -0
- package/components/GridRow.js +41 -6
- package/components/GridRow.mjs +41 -6
- 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 +15 -4
- package/components/cell/GridCell.mjs +15 -4
- package/components/cell/GridEditBooleanCell.d.mts +1 -1
- package/components/cell/GridEditBooleanCell.d.ts +1 -1
- package/components/cell/GridEditBooleanCell.js +4 -4
- package/components/cell/GridEditBooleanCell.mjs +4 -4
- package/components/cell/GridEditDateCell.d.mts +1 -1
- package/components/cell/GridEditDateCell.d.ts +1 -1
- package/components/cell/GridEditDateCell.js +5 -5
- package/components/cell/GridEditDateCell.mjs +5 -5
- package/components/cell/GridEditInputCell.d.mts +1 -1
- package/components/cell/GridEditInputCell.d.ts +1 -1
- package/components/cell/GridEditInputCell.js +1 -1
- package/components/cell/GridEditInputCell.mjs +1 -1
- package/components/cell/GridEditLongTextCell.d.mts +1 -1
- package/components/cell/GridEditLongTextCell.d.ts +1 -1
- package/components/cell/GridEditLongTextCell.js +2 -2
- package/components/cell/GridEditLongTextCell.mjs +2 -2
- package/components/cell/GridEditSingleSelectCell.d.mts +1 -1
- package/components/cell/GridEditSingleSelectCell.d.ts +1 -1
- package/components/cell/GridEditSingleSelectCell.js +4 -4
- package/components/cell/GridEditSingleSelectCell.mjs +4 -4
- package/components/quickFilter/QuickFilter.js +7 -2
- package/components/quickFilter/QuickFilter.mjs +7 -2
- package/components/toolbarV8/Toolbar.d.mts +5 -1
- package/components/toolbarV8/Toolbar.d.ts +5 -1
- package/components/toolbarV8/Toolbar.js +34 -12
- package/components/toolbarV8/Toolbar.mjs +33 -11
- package/components/virtualization/GridVirtualScroller.js +3 -0
- package/components/virtualization/GridVirtualScroller.mjs +3 -0
- package/hooks/core/useGridVirtualizer.js +14 -1
- package/hooks/core/useGridVirtualizer.mjs +14 -1
- package/hooks/features/columnResize/useGridColumnResize.js +4 -1
- package/hooks/features/columnResize/useGridColumnResize.mjs +4 -1
- package/hooks/features/dataSource/models.d.mts +2 -2
- package/hooks/features/dataSource/models.d.ts +2 -2
- package/hooks/features/dataSource/useGridDataSourceBase.js +12 -8
- package/hooks/features/dataSource/useGridDataSourceBase.mjs +13 -9
- package/hooks/features/pivoting/gridPivotingInterfaces.d.mts +2 -2
- package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +2 -2
- package/hooks/features/rowSelection/useGridRowSelection.d.mts +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.js +51 -10
- package/hooks/features/rowSelection/useGridRowSelection.mjs +53 -12
- package/hooks/features/rowSelection/utils.js +5 -0
- package/hooks/features/rowSelection/utils.mjs +5 -0
- package/hooks/features/rows/gridRowsUtils.d.mts +37 -3
- package/hooks/features/rows/gridRowsUtils.d.ts +37 -3
- package/hooks/features/rows/gridRowsUtils.js +120 -23
- package/hooks/features/rows/gridRowsUtils.mjs +115 -22
- package/hooks/features/rows/useGridRows.js +10 -1
- package/hooks/features/rows/useGridRows.mjs +10 -1
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/internals/index.d.mts +2 -2
- package/internals/index.d.ts +2 -2
- package/internals/index.js +28 -0
- package/internals/index.mjs +2 -2
- package/material/variables.d.mts +6 -1
- package/material/variables.d.ts +6 -1
- package/material/variables.js +17 -3
- package/material/variables.mjs +14 -4
- package/models/api/gridRowApi.d.mts +7 -7
- package/models/api/gridRowApi.d.ts +7 -7
- package/models/gridDataSource.d.mts +3 -0
- package/models/gridDataSource.d.ts +3 -0
- package/models/gridRows.d.mts +28 -1
- package/models/gridRows.d.ts +28 -1
- package/models/props/DataGridProps.d.mts +3 -3
- package/models/props/DataGridProps.d.ts +3 -3
- package/package.json +6 -6
- package/utils/keyboardUtils.d.mts +1 -0
- package/utils/keyboardUtils.d.ts +1 -0
- package/utils/keyboardUtils.js +6 -0
- package/utils/keyboardUtils.mjs +5 -0
|
@@ -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
|
|
@@ -101,14 +101,17 @@ const GridCell = (0, _forwardRef.forwardRef)(function GridCell(props, ref) {
|
|
|
101
101
|
value: forcedValue,
|
|
102
102
|
formattedValue: forcedFormattedValue
|
|
103
103
|
} = cellAggregationResult || {};
|
|
104
|
+
const stateTabIndex = (0, _useGridSelector.useGridSelector)(apiRef, () => {
|
|
105
|
+
const cellTabIndex = (0, _gridFocusStateSelector.gridTabIndexCellSelector)(apiRef);
|
|
106
|
+
return cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === rowId ? 0 : -1;
|
|
107
|
+
});
|
|
104
108
|
const cellParams = apiRef.current.getCellParamsForRow(rowId, field, row, {
|
|
105
109
|
colDef: column,
|
|
106
110
|
cellMode,
|
|
107
111
|
rowNode: rowNode,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}),
|
|
112
|
+
// A cell kept mounted outside the render context is collapsed to zero size, so it must not
|
|
113
|
+
// become the grid's tab stop: tabbing in would move focus to something the user can't see.
|
|
114
|
+
tabIndex: isNotVisible ? -1 : stateTabIndex,
|
|
112
115
|
hasFocus: (0, _useGridSelector.useGridSelector)(apiRef, () => {
|
|
113
116
|
const focus = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
|
|
114
117
|
return focus?.id === rowId && focus.field === field;
|
|
@@ -174,6 +177,10 @@ const GridCell = (0, _forwardRef.forwardRef)(function GridCell(props, ref) {
|
|
|
174
177
|
};
|
|
175
178
|
const classes = useUtilityClasses(ownerState);
|
|
176
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
|
+
}
|
|
177
184
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
178
185
|
apiRef.current.publishEvent(eventName, params, event);
|
|
179
186
|
if (onMouseUp) {
|
|
@@ -181,6 +188,10 @@ const GridCell = (0, _forwardRef.forwardRef)(function GridCell(props, ref) {
|
|
|
181
188
|
}
|
|
182
189
|
}, [apiRef, field, onMouseUp, rowId]);
|
|
183
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
|
+
}
|
|
184
195
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
185
196
|
apiRef.current.publishEvent(eventName, params, event);
|
|
186
197
|
if (onMouseDown) {
|
|
@@ -94,14 +94,17 @@ const GridCell = forwardRef(function GridCell(props, ref) {
|
|
|
94
94
|
value: forcedValue,
|
|
95
95
|
formattedValue: forcedFormattedValue
|
|
96
96
|
} = cellAggregationResult || {};
|
|
97
|
+
const stateTabIndex = useGridSelector(apiRef, () => {
|
|
98
|
+
const cellTabIndex = gridTabIndexCellSelector(apiRef);
|
|
99
|
+
return cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === rowId ? 0 : -1;
|
|
100
|
+
});
|
|
97
101
|
const cellParams = apiRef.current.getCellParamsForRow(rowId, field, row, {
|
|
98
102
|
colDef: column,
|
|
99
103
|
cellMode,
|
|
100
104
|
rowNode: rowNode,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}),
|
|
105
|
+
// A cell kept mounted outside the render context is collapsed to zero size, so it must not
|
|
106
|
+
// become the grid's tab stop: tabbing in would move focus to something the user can't see.
|
|
107
|
+
tabIndex: isNotVisible ? -1 : stateTabIndex,
|
|
105
108
|
hasFocus: useGridSelector(apiRef, () => {
|
|
106
109
|
const focus = gridFocusCellSelector(apiRef);
|
|
107
110
|
return focus?.id === rowId && focus.field === field;
|
|
@@ -167,6 +170,10 @@ const GridCell = forwardRef(function GridCell(props, ref) {
|
|
|
167
170
|
};
|
|
168
171
|
const classes = useUtilityClasses(ownerState);
|
|
169
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
|
+
}
|
|
170
177
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
171
178
|
apiRef.current.publishEvent(eventName, params, event);
|
|
172
179
|
if (onMouseUp) {
|
|
@@ -174,6 +181,10 @@ const GridCell = forwardRef(function GridCell(props, ref) {
|
|
|
174
181
|
}
|
|
175
182
|
}, [apiRef, field, onMouseUp, rowId]);
|
|
176
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
|
+
}
|
|
177
188
|
const params = apiRef.current.getCellParams(rowId, field || '');
|
|
178
189
|
apiRef.current.publishEvent(eventName, params, event);
|
|
179
190
|
if (onMouseDown) {
|
|
@@ -5,7 +5,7 @@ export interface GridEditBooleanCellProps extends GridRenderEditCellParams, Omit
|
|
|
5
5
|
* Callback called when the value is changed by the user.
|
|
6
6
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
7
7
|
* @param {boolean} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
8
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
8
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
9
9
|
*/
|
|
10
10
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: boolean) => Promise<void> | void;
|
|
11
11
|
}
|
|
@@ -5,7 +5,7 @@ export interface GridEditBooleanCellProps extends GridRenderEditCellParams, Omit
|
|
|
5
5
|
* Callback called when the value is changed by the user.
|
|
6
6
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
7
7
|
* @param {boolean} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
8
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
8
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
9
9
|
*/
|
|
10
10
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: boolean) => Promise<void> | void;
|
|
11
11
|
}
|
|
@@ -51,15 +51,15 @@ function GridEditBooleanCell(props) {
|
|
|
51
51
|
const classes = useUtilityClasses(ownerState);
|
|
52
52
|
const handleChange = React.useCallback(async event => {
|
|
53
53
|
const newValue = event.target.checked;
|
|
54
|
-
if (onValueChange) {
|
|
55
|
-
await onValueChange(event, newValue);
|
|
56
|
-
}
|
|
57
54
|
setValueState(newValue);
|
|
58
55
|
await apiRef.current.setEditCellValue({
|
|
59
56
|
id: idProp,
|
|
60
57
|
field,
|
|
61
58
|
value: newValue
|
|
62
59
|
}, event);
|
|
60
|
+
if (onValueChange) {
|
|
61
|
+
await onValueChange(event, newValue);
|
|
62
|
+
}
|
|
63
63
|
}, [apiRef, field, idProp, onValueChange]);
|
|
64
64
|
React.useEffect(() => {
|
|
65
65
|
setValueState(value);
|
|
@@ -126,7 +126,7 @@ process.env.NODE_ENV !== "production" ? GridEditBooleanCell.propTypes /* remove-
|
|
|
126
126
|
* Callback called when the value is changed by the user.
|
|
127
127
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
128
128
|
* @param {boolean} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
129
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
129
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
130
130
|
*/
|
|
131
131
|
onValueChange: _propTypes.default.func,
|
|
132
132
|
/**
|
|
@@ -43,15 +43,15 @@ function GridEditBooleanCell(props) {
|
|
|
43
43
|
const classes = useUtilityClasses(ownerState);
|
|
44
44
|
const handleChange = React.useCallback(async event => {
|
|
45
45
|
const newValue = event.target.checked;
|
|
46
|
-
if (onValueChange) {
|
|
47
|
-
await onValueChange(event, newValue);
|
|
48
|
-
}
|
|
49
46
|
setValueState(newValue);
|
|
50
47
|
await apiRef.current.setEditCellValue({
|
|
51
48
|
id: idProp,
|
|
52
49
|
field,
|
|
53
50
|
value: newValue
|
|
54
51
|
}, event);
|
|
52
|
+
if (onValueChange) {
|
|
53
|
+
await onValueChange(event, newValue);
|
|
54
|
+
}
|
|
55
55
|
}, [apiRef, field, idProp, onValueChange]);
|
|
56
56
|
React.useEffect(() => {
|
|
57
57
|
setValueState(value);
|
|
@@ -118,7 +118,7 @@ process.env.NODE_ENV !== "production" ? GridEditBooleanCell.propTypes /* remove-
|
|
|
118
118
|
* Callback called when the value is changed by the user.
|
|
119
119
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
120
120
|
* @param {boolean} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
121
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
121
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
122
122
|
*/
|
|
123
123
|
onValueChange: PropTypes.func,
|
|
124
124
|
/**
|
|
@@ -6,7 +6,7 @@ export interface GridEditDateCellProps extends GridRenderEditCellParams {
|
|
|
6
6
|
* Callback called when the value is changed by the user.
|
|
7
7
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
8
8
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
9
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
9
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
10
10
|
*/
|
|
11
11
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: Date | null) => Promise<void> | void;
|
|
12
12
|
slotProps?: {
|
|
@@ -6,7 +6,7 @@ export interface GridEditDateCellProps extends GridRenderEditCellParams {
|
|
|
6
6
|
* Callback called when the value is changed by the user.
|
|
7
7
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
8
8
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
9
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
9
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
10
10
|
*/
|
|
11
11
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: Date | null) => Promise<void> | void;
|
|
12
12
|
slotProps?: {
|
|
@@ -94,18 +94,18 @@ function GridEditDateCell(props) {
|
|
|
94
94
|
const handleChange = React.useCallback(async event => {
|
|
95
95
|
const newFormattedDate = event.target.value;
|
|
96
96
|
const newParsedDate = parseValueToDate(newFormattedDate);
|
|
97
|
-
if (onValueChange) {
|
|
98
|
-
await onValueChange(event, newParsedDate);
|
|
99
|
-
}
|
|
100
97
|
setValueState({
|
|
101
98
|
parsed: newParsedDate,
|
|
102
99
|
formatted: newFormattedDate
|
|
103
100
|
});
|
|
104
|
-
apiRef.current.setEditCellValue({
|
|
101
|
+
await apiRef.current.setEditCellValue({
|
|
105
102
|
id,
|
|
106
103
|
field,
|
|
107
104
|
value: newParsedDate
|
|
108
105
|
}, event);
|
|
106
|
+
if (onValueChange) {
|
|
107
|
+
await onValueChange(event, newParsedDate);
|
|
108
|
+
}
|
|
109
109
|
}, [apiRef, field, id, onValueChange, parseValueToDate]);
|
|
110
110
|
React.useEffect(() => {
|
|
111
111
|
setValueState(state => {
|
|
@@ -180,7 +180,7 @@ process.env.NODE_ENV !== "production" ? GridEditDateCell.propTypes /* remove-pro
|
|
|
180
180
|
* Callback called when the value is changed by the user.
|
|
181
181
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
182
182
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
183
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
183
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
184
184
|
*/
|
|
185
185
|
onValueChange: _propTypes.default.func,
|
|
186
186
|
/**
|
|
@@ -86,18 +86,18 @@ function GridEditDateCell(props) {
|
|
|
86
86
|
const handleChange = React.useCallback(async event => {
|
|
87
87
|
const newFormattedDate = event.target.value;
|
|
88
88
|
const newParsedDate = parseValueToDate(newFormattedDate);
|
|
89
|
-
if (onValueChange) {
|
|
90
|
-
await onValueChange(event, newParsedDate);
|
|
91
|
-
}
|
|
92
89
|
setValueState({
|
|
93
90
|
parsed: newParsedDate,
|
|
94
91
|
formatted: newFormattedDate
|
|
95
92
|
});
|
|
96
|
-
apiRef.current.setEditCellValue({
|
|
93
|
+
await apiRef.current.setEditCellValue({
|
|
97
94
|
id,
|
|
98
95
|
field,
|
|
99
96
|
value: newParsedDate
|
|
100
97
|
}, event);
|
|
98
|
+
if (onValueChange) {
|
|
99
|
+
await onValueChange(event, newParsedDate);
|
|
100
|
+
}
|
|
101
101
|
}, [apiRef, field, id, onValueChange, parseValueToDate]);
|
|
102
102
|
React.useEffect(() => {
|
|
103
103
|
setValueState(state => {
|
|
@@ -172,7 +172,7 @@ process.env.NODE_ENV !== "production" ? GridEditDateCell.propTypes /* remove-pro
|
|
|
172
172
|
* Callback called when the value is changed by the user.
|
|
173
173
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
174
174
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
175
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
175
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
176
176
|
*/
|
|
177
177
|
onValueChange: PropTypes.func,
|
|
178
178
|
/**
|
|
@@ -7,7 +7,7 @@ export interface GridEditInputCellProps extends GridRenderEditCellParams {
|
|
|
7
7
|
* Callback called when the value is changed by the user.
|
|
8
8
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
9
9
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
10
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
10
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
11
11
|
*/
|
|
12
12
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: string) => Promise<void> | void;
|
|
13
13
|
slotProps?: {
|
|
@@ -7,7 +7,7 @@ export interface GridEditInputCellProps extends GridRenderEditCellParams {
|
|
|
7
7
|
* Callback called when the value is changed by the user.
|
|
8
8
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
9
9
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
10
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
10
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
11
11
|
*/
|
|
12
12
|
onValueChange?: (event: React.ChangeEvent<HTMLInputElement>, newValue: string) => Promise<void> | void;
|
|
13
13
|
slotProps?: {
|
|
@@ -153,7 +153,7 @@ process.env.NODE_ENV !== "production" ? GridEditInputCell.propTypes /* remove-pr
|
|
|
153
153
|
* Callback called when the value is changed by the user.
|
|
154
154
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
155
155
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
156
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
156
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
157
157
|
*/
|
|
158
158
|
onValueChange: _propTypes.default.func,
|
|
159
159
|
/**
|
|
@@ -146,7 +146,7 @@ process.env.NODE_ENV !== "production" ? GridEditInputCell.propTypes /* remove-pr
|
|
|
146
146
|
* Callback called when the value is changed by the user.
|
|
147
147
|
* @param {React.ChangeEvent<HTMLInputElement>} event The event source of the callback.
|
|
148
148
|
* @param {Date | null} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
|
|
149
|
-
* @returns {Promise<void> | void} A promise to be awaited
|
|
149
|
+
* @returns {Promise<void> | void} A promise to be awaited after `apiRef.current.setEditCellValue` is called
|
|
150
150
|
*/
|
|
151
151
|
onValueChange: PropTypes.func,
|
|
152
152
|
/**
|