@mui/x-data-grid 7.18.0 → 7.20.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 +213 -11
- package/DataGrid/DataGrid.js +12 -0
- package/components/cell/GridCell.js +7 -8
- package/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
- package/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
- package/components/columnSelection/GridHeaderCheckbox.d.ts +1 -1
- package/components/containers/GridRoot.js +1 -1
- package/components/containers/GridRootStyles.js +32 -23
- package/components/containers/GridToolbarContainer.js +1 -1
- package/components/menu/GridMenu.js +1 -1
- package/components/panel/GridPanel.d.ts +1 -1
- package/components/panel/GridPanel.js +1 -1
- package/components/panel/GridPanelContent.js +1 -1
- package/components/panel/GridPanelFooter.js +1 -1
- package/components/panel/GridPanelHeader.js +1 -1
- package/components/panel/GridPanelWrapper.js +1 -1
- package/components/panel/filterPanel/filterPanelUtils.d.ts +1 -1
- package/components/toolbar/GridToolbarQuickFilter.js +1 -1
- package/components/virtualization/GridBottomContainer.d.ts +1 -1
- package/components/virtualization/GridBottomContainer.js +18 -1
- package/components/virtualization/GridMainContainer.js +3 -1
- package/components/virtualization/GridTopContainer.d.ts +1 -1
- package/components/virtualization/GridTopContainer.js +1 -1
- package/components/virtualization/GridVirtualScrollbar.js +1 -7
- package/components/virtualization/GridVirtualScroller.js +1 -0
- package/components/virtualization/GridVirtualScrollerFiller.js +3 -4
- package/hooks/core/useGridRefs.js +4 -0
- package/hooks/features/columnGrouping/gridColumnGroupsSelector.d.ts +4 -4
- package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -1
- package/hooks/features/columnResize/columnResizeSelector.d.ts +1 -1
- package/hooks/features/columns/gridColumnsSelector.d.ts +12 -12
- package/hooks/features/columns/gridColumnsUtils.js +3 -2
- package/hooks/features/density/densitySelector.d.ts +1 -1
- package/hooks/features/dimensions/useGridDimensions.js +2 -2
- package/hooks/features/editing/useGridCellEditing.js +4 -2
- package/hooks/features/editing/useGridRowEditing.js +4 -2
- package/hooks/features/events/useGridEvents.d.ts +1 -1
- package/hooks/features/events/useGridEvents.js +1 -0
- package/hooks/features/filter/gridFilterSelector.d.ts +17 -17
- package/hooks/features/filter/gridFilterUtils.js +1 -1
- package/hooks/features/focus/gridFocusStateSelector.d.ts +8 -8
- package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.d.ts +3 -3
- package/hooks/features/keyboardNavigation/utils.d.ts +1 -1
- package/hooks/features/pagination/gridPaginationSelector.d.ts +9 -9
- package/hooks/features/rowSelection/gridRowSelectionSelector.d.ts +3 -3
- package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
- package/hooks/features/rowSelection/useGridRowSelection.js +105 -29
- package/hooks/features/rowSelection/utils.d.ts +10 -0
- package/hooks/features/rowSelection/utils.js +156 -1
- package/hooks/features/rows/gridRowSpanningSelectors.d.ts +3 -3
- package/hooks/features/rows/gridRowsSelector.d.ts +14 -14
- package/hooks/features/rows/gridRowsUtils.js +1 -1
- package/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/hooks/features/rows/useGridRows.d.ts +1 -1
- package/hooks/features/rows/useGridRows.js +7 -1
- package/hooks/features/scroll/useGridScroll.js +26 -22
- package/hooks/features/sorting/gridSortingSelector.d.ts +4 -4
- package/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +5 -5
- package/hooks/features/virtualization/useGridVirtualScroller.js +2 -2
- package/hooks/utils/useGridApiContext.js +1 -1
- package/hooks/utils/useGridApiEventHandler.d.ts +1 -1
- package/hooks/utils/useGridApiEventHandler.js +1 -1
- package/hooks/utils/useGridConfiguration.js +1 -1
- package/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/hooks/utils/useGridVisibleRows.d.ts +2 -2
- package/index.d.ts +2 -2
- package/index.js +3 -3
- package/internals/index.d.ts +1 -0
- package/internals/index.js +1 -0
- package/joy/icons.js +0 -1
- package/locales/bgBG.js +8 -9
- package/locales/deDE.js +4 -4
- package/locales/frFR.js +4 -4
- package/locales/hrHR.d.ts +1 -1
- package/locales/hrHR.js +69 -46
- package/locales/jaJP.js +5 -6
- package/locales/ptPT.d.ts +1 -1
- package/locales/ptPT.js +4 -4
- package/locales/viVN.js +20 -20
- package/locales/zhHK.d.ts +1 -1
- package/models/api/gridApiCommunity.d.ts +1 -1
- package/models/api/gridCoreApi.d.ts +9 -1
- package/models/api/gridFilterApi.d.ts +1 -1
- package/models/events/gridEventLookup.d.ts +7 -0
- package/models/gridRowSelectionModel.d.ts +4 -0
- package/models/gridStateCommunity.d.ts +2 -2
- package/models/props/DataGridProps.d.ts +38 -10
- package/modern/DataGrid/DataGrid.js +12 -0
- package/modern/components/cell/GridCell.js +7 -8
- package/modern/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
- package/modern/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/modern/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
- package/modern/components/containers/GridRoot.js +1 -1
- package/modern/components/containers/GridRootStyles.js +32 -23
- package/modern/components/containers/GridToolbarContainer.js +1 -1
- package/modern/components/menu/GridMenu.js +1 -1
- package/modern/components/panel/GridPanel.js +1 -1
- package/modern/components/panel/GridPanelContent.js +1 -1
- package/modern/components/panel/GridPanelFooter.js +1 -1
- package/modern/components/panel/GridPanelHeader.js +1 -1
- package/modern/components/panel/GridPanelWrapper.js +1 -1
- package/modern/components/toolbar/GridToolbarQuickFilter.js +1 -1
- package/modern/components/virtualization/GridBottomContainer.js +18 -1
- package/modern/components/virtualization/GridMainContainer.js +3 -1
- package/modern/components/virtualization/GridTopContainer.js +1 -1
- package/modern/components/virtualization/GridVirtualScrollbar.js +1 -7
- package/modern/components/virtualization/GridVirtualScroller.js +1 -0
- package/modern/components/virtualization/GridVirtualScrollerFiller.js +3 -4
- package/modern/hooks/core/useGridRefs.js +4 -0
- package/modern/hooks/features/columns/gridColumnsUtils.js +3 -2
- package/modern/hooks/features/dimensions/useGridDimensions.js +2 -2
- package/modern/hooks/features/editing/useGridCellEditing.js +4 -2
- package/modern/hooks/features/editing/useGridRowEditing.js +4 -2
- package/modern/hooks/features/events/useGridEvents.js +1 -0
- package/modern/hooks/features/filter/gridFilterUtils.js +1 -1
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +105 -29
- package/modern/hooks/features/rowSelection/utils.js +156 -1
- package/modern/hooks/features/rows/gridRowsUtils.js +1 -1
- package/modern/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/modern/hooks/features/rows/useGridRows.js +7 -1
- package/modern/hooks/features/scroll/useGridScroll.js +26 -22
- package/modern/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +2 -2
- package/modern/hooks/utils/useGridApiContext.js +1 -1
- package/modern/hooks/utils/useGridApiEventHandler.js +1 -1
- package/modern/hooks/utils/useGridConfiguration.js +1 -1
- package/modern/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/modern/index.js +3 -3
- package/modern/internals/index.js +1 -0
- package/modern/joy/icons.js +0 -1
- package/modern/locales/bgBG.js +8 -9
- package/modern/locales/deDE.js +4 -4
- package/modern/locales/frFR.js +4 -4
- package/modern/locales/hrHR.js +69 -46
- package/modern/locales/jaJP.js +5 -6
- package/modern/locales/ptPT.js +4 -4
- package/modern/locales/viVN.js +20 -20
- package/modern/utils/createSelector.js +6 -0
- package/modern/utils/domUtils.js +1 -1
- package/node/DataGrid/DataGrid.js +12 -0
- package/node/components/cell/GridCell.js +7 -8
- package/node/components/columnHeaders/GridBaseColumnHeaders.js +1 -1
- package/node/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/node/components/columnSelection/GridCellCheckboxRenderer.js +12 -4
- package/node/components/containers/GridRoot.js +1 -1
- package/node/components/containers/GridRootStyles.js +32 -23
- package/node/components/containers/GridToolbarContainer.js +1 -1
- package/node/components/menu/GridMenu.js +1 -1
- package/node/components/panel/GridPanel.js +1 -1
- package/node/components/panel/GridPanelContent.js +1 -1
- package/node/components/panel/GridPanelFooter.js +1 -1
- package/node/components/panel/GridPanelHeader.js +1 -1
- package/node/components/panel/GridPanelWrapper.js +1 -1
- package/node/components/toolbar/GridToolbarQuickFilter.js +1 -1
- package/node/components/virtualization/GridBottomContainer.js +18 -1
- package/node/components/virtualization/GridMainContainer.js +3 -1
- package/node/components/virtualization/GridTopContainer.js +1 -1
- package/node/components/virtualization/GridVirtualScrollbar.js +1 -7
- package/node/components/virtualization/GridVirtualScroller.js +1 -0
- package/node/components/virtualization/GridVirtualScrollerFiller.js +3 -4
- package/node/hooks/core/useGridRefs.js +4 -0
- package/node/hooks/features/columns/gridColumnsUtils.js +3 -2
- package/node/hooks/features/dimensions/useGridDimensions.js +2 -2
- package/node/hooks/features/editing/useGridCellEditing.js +4 -2
- package/node/hooks/features/editing/useGridRowEditing.js +4 -2
- package/node/hooks/features/events/useGridEvents.js +1 -0
- package/node/hooks/features/filter/gridFilterUtils.js +1 -1
- package/node/hooks/features/rowSelection/useGridRowSelection.js +102 -26
- package/node/hooks/features/rowSelection/utils.js +160 -1
- package/node/hooks/features/rows/gridRowsUtils.js +1 -1
- package/node/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/node/hooks/features/rows/useGridRows.js +7 -1
- package/node/hooks/features/scroll/useGridScroll.js +26 -22
- package/node/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +2 -2
- package/node/hooks/utils/useGridApiContext.js +1 -1
- package/node/hooks/utils/useGridApiEventHandler.js +1 -1
- package/node/hooks/utils/useGridConfiguration.js +1 -1
- package/node/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/node/index.js +1 -1
- package/node/internals/index.js +23 -15
- package/node/joy/icons.js +0 -1
- package/node/locales/bgBG.js +8 -9
- package/node/locales/deDE.js +4 -4
- package/node/locales/frFR.js +4 -4
- package/node/locales/hrHR.js +69 -46
- package/node/locales/jaJP.js +5 -6
- package/node/locales/ptPT.js +4 -4
- package/node/locales/viVN.js +20 -20
- package/node/utils/createSelector.js +6 -0
- package/node/utils/domUtils.js +1 -1
- package/package.json +4 -4
- package/utils/createSelector.js +6 -0
- package/utils/domUtils.js +1 -1
|
@@ -48,7 +48,7 @@ const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper
|
|
|
48
48
|
children: /*#__PURE__*/_jsx(GridPanelWrapperRoot, _extends({
|
|
49
49
|
ref: ref,
|
|
50
50
|
tabIndex: -1,
|
|
51
|
-
className: clsx(
|
|
51
|
+
className: clsx(classes.root, className),
|
|
52
52
|
ownerState: rootProps
|
|
53
53
|
}, other))
|
|
54
54
|
}));
|
|
@@ -93,7 +93,7 @@ function GridToolbarQuickFilter(props) {
|
|
|
93
93
|
variant: "standard",
|
|
94
94
|
value: searchValue,
|
|
95
95
|
onChange: handleSearchValueChange,
|
|
96
|
-
className: clsx(
|
|
96
|
+
className: clsx(classes.root, className),
|
|
97
97
|
placeholder: apiRef.current.getLocaleText('toolbarQuickFilterPlaceholder'),
|
|
98
98
|
"aria-label": apiRef.current.getLocaleText('toolbarQuickFilterLabel'),
|
|
99
99
|
type: "search"
|
|
@@ -4,6 +4,9 @@ import clsx from 'clsx';
|
|
|
4
4
|
import { styled } from '@mui/system';
|
|
5
5
|
import composeClasses from '@mui/utils/composeClasses';
|
|
6
6
|
import { gridClasses, getDataGridUtilityClass } from "../../constants/gridClasses.js";
|
|
7
|
+
import { gridDimensionsSelector } from "../../hooks/features/dimensions/gridDimensionsSelectors.js";
|
|
8
|
+
import { useGridApiContext } from "../../hooks/utils/useGridApiContext.js";
|
|
9
|
+
import { useGridSelector } from "../../hooks/utils/useGridSelector.js";
|
|
7
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
11
|
const useUtilityClasses = () => {
|
|
9
12
|
const slots = {
|
|
@@ -18,8 +21,22 @@ const Element = styled('div')({
|
|
|
18
21
|
});
|
|
19
22
|
export function GridBottomContainer(props) {
|
|
20
23
|
const classes = useUtilityClasses();
|
|
24
|
+
const apiRef = useGridApiContext();
|
|
25
|
+
const {
|
|
26
|
+
viewportOuterSize,
|
|
27
|
+
minimumSize,
|
|
28
|
+
hasScrollX,
|
|
29
|
+
scrollbarSize
|
|
30
|
+
} = useGridSelector(apiRef, gridDimensionsSelector);
|
|
31
|
+
const scrollHeight = hasScrollX ? scrollbarSize : 0;
|
|
32
|
+
const offset = Math.max(viewportOuterSize.height - minimumSize.height -
|
|
33
|
+
// Subtract scroll height twice to account for GridVirtualScrollerFiller and horizontal scrollbar
|
|
34
|
+
2 * scrollHeight, 0);
|
|
21
35
|
return /*#__PURE__*/_jsx(Element, _extends({}, props, {
|
|
22
|
-
className: clsx(classes.root,
|
|
36
|
+
className: clsx(classes.root, gridClasses['container--bottom']),
|
|
37
|
+
style: {
|
|
38
|
+
transform: `translateY(${offset}px)`
|
|
39
|
+
},
|
|
23
40
|
role: "presentation"
|
|
24
41
|
}));
|
|
25
42
|
}
|
|
@@ -16,7 +16,9 @@ const Element = styled('div', {
|
|
|
16
16
|
})({
|
|
17
17
|
flexGrow: 1,
|
|
18
18
|
position: 'relative',
|
|
19
|
-
overflow: 'hidden'
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
display: 'flex',
|
|
21
|
+
flexDirection: 'column'
|
|
20
22
|
});
|
|
21
23
|
export const GridMainContainer = /*#__PURE__*/React.forwardRef((props, ref) => {
|
|
22
24
|
const rootProps = useGridRootProps();
|
|
@@ -19,7 +19,7 @@ const Element = styled('div')({
|
|
|
19
19
|
export function GridTopContainer(props) {
|
|
20
20
|
const classes = useUtilityClasses();
|
|
21
21
|
return /*#__PURE__*/_jsx(Element, _extends({}, props, {
|
|
22
|
-
className: clsx(classes.root,
|
|
22
|
+
className: clsx(classes.root, gridClasses['container--top']),
|
|
23
23
|
role: "presentation"
|
|
24
24
|
}));
|
|
25
25
|
}
|
|
@@ -21,9 +21,6 @@ const Scrollbar = styled('div')({
|
|
|
21
21
|
position: 'absolute',
|
|
22
22
|
display: 'inline-block',
|
|
23
23
|
zIndex: 6,
|
|
24
|
-
'& > div': {
|
|
25
|
-
display: 'inline-block'
|
|
26
|
-
},
|
|
27
24
|
// In macOS Safari and Gnome Web, scrollbars are overlaid and don't affect the layout. So we consider
|
|
28
25
|
// their size to be 0px throughout all the calculations, but the floating scrollbar container does need
|
|
29
26
|
// to appear and have a real size. We set it to 14px because it seems like an acceptable value and we
|
|
@@ -55,9 +52,6 @@ const ScrollbarHorizontal = styled(Scrollbar)({
|
|
|
55
52
|
},
|
|
56
53
|
bottom: '0px'
|
|
57
54
|
});
|
|
58
|
-
const Content = styled('div')({
|
|
59
|
-
display: 'inline-block'
|
|
60
|
-
});
|
|
61
55
|
const GridVirtualScrollbar = /*#__PURE__*/React.forwardRef(function GridVirtualScrollbar(props, ref) {
|
|
62
56
|
const apiRef = useGridPrivateApiContext();
|
|
63
57
|
const rootProps = useGridRootProps();
|
|
@@ -127,7 +121,7 @@ const GridVirtualScrollbar = /*#__PURE__*/React.forwardRef(function GridVirtualS
|
|
|
127
121
|
className: classes.root,
|
|
128
122
|
tabIndex: -1,
|
|
129
123
|
"aria-hidden": "true",
|
|
130
|
-
children: /*#__PURE__*/_jsx(
|
|
124
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
131
125
|
ref: contentRef,
|
|
132
126
|
className: classes.content
|
|
133
127
|
})
|
|
@@ -44,10 +44,9 @@ function GridVirtualScrollerFiller({
|
|
|
44
44
|
leftPinnedWidth,
|
|
45
45
|
rightPinnedWidth
|
|
46
46
|
} = useGridSelector(apiRef, gridDimensionsSelector);
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
if (height === 0) {
|
|
47
|
+
const height = hasScrollX ? scrollbarSize : 0;
|
|
48
|
+
const needsLastRowBorder = viewportOuterSize.height - minimumSize.height > 0;
|
|
49
|
+
if (height === 0 && !needsLastRowBorder) {
|
|
51
50
|
return null;
|
|
52
51
|
}
|
|
53
52
|
return /*#__PURE__*/_jsxs(Filler, {
|
|
@@ -3,6 +3,8 @@ export const useGridRefs = apiRef => {
|
|
|
3
3
|
const rootElementRef = React.useRef(null);
|
|
4
4
|
const mainElementRef = React.useRef(null);
|
|
5
5
|
const virtualScrollerRef = React.useRef(null);
|
|
6
|
+
const virtualScrollbarVerticalRef = React.useRef(null);
|
|
7
|
+
const virtualScrollbarHorizontalRef = React.useRef(null);
|
|
6
8
|
const columnHeadersContainerRef = React.useRef(null);
|
|
7
9
|
apiRef.current.register('public', {
|
|
8
10
|
rootElementRef
|
|
@@ -10,6 +12,8 @@ export const useGridRefs = apiRef => {
|
|
|
10
12
|
apiRef.current.register('private', {
|
|
11
13
|
mainElementRef,
|
|
12
14
|
virtualScrollerRef,
|
|
15
|
+
virtualScrollbarVerticalRef,
|
|
16
|
+
virtualScrollbarHorizontalRef,
|
|
13
17
|
columnHeadersContainerRef
|
|
14
18
|
});
|
|
15
19
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
import resolveProps from '@mui/utils/resolveProps';
|
|
2
3
|
import { DEFAULT_GRID_COL_TYPE_KEY, GRID_STRING_COL_DEF, getGridDefaultColumnTypes } from "../../../colDef/index.js";
|
|
3
4
|
import { gridColumnsStateSelector, gridColumnVisibilityModelSelector } from "./gridColumnsSelector.js";
|
|
4
5
|
import { clamp } from "../../../utils/utils.js";
|
|
@@ -275,9 +276,9 @@ export const createColumnsState = ({
|
|
|
275
276
|
}
|
|
276
277
|
}
|
|
277
278
|
});
|
|
278
|
-
columnsState.lookup[field] = _extends({},
|
|
279
|
+
columnsState.lookup[field] = resolveProps(existingState, _extends({}, newColumn, {
|
|
279
280
|
hasBeenResized
|
|
280
|
-
});
|
|
281
|
+
}));
|
|
281
282
|
});
|
|
282
283
|
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
|
|
283
284
|
Object.keys(columnsState.lookup).forEach(field => {
|
|
@@ -238,11 +238,11 @@ export function useGridDimensions(apiRef, props) {
|
|
|
238
238
|
// jsdom has no layout capabilities
|
|
239
239
|
const isJSDOM = /jsdom/.test(window.navigator.userAgent);
|
|
240
240
|
if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
|
|
241
|
-
logger.error(['The parent DOM element of the
|
|
241
|
+
logger.error(['The parent DOM element of the Data Grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
|
|
242
242
|
errorShown.current = true;
|
|
243
243
|
}
|
|
244
244
|
if (size.width === 0 && !errorShown.current && !isJSDOM) {
|
|
245
|
-
logger.error(['The parent DOM element of the
|
|
245
|
+
logger.error(['The parent DOM element of the Data Grid has an empty width.', 'Please make sure that this element has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
|
|
246
246
|
errorShown.current = true;
|
|
247
247
|
}
|
|
248
248
|
if (isFirstSizing.current) {
|
|
@@ -68,7 +68,7 @@ export const useGridCellEditing = (apiRef, props) => {
|
|
|
68
68
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
69
69
|
if (params.cellMode === GridCellModes.Edit) {
|
|
70
70
|
// Wait until IME is settled for Asian languages like Japanese and Chinese
|
|
71
|
-
// TODO:
|
|
71
|
+
// TODO: to replace at one point. See https://github.com/mui/material-ui/pull/39713#discussion_r1381678957.
|
|
72
72
|
if (event.which === 229) {
|
|
73
73
|
return;
|
|
74
74
|
}
|
|
@@ -324,7 +324,9 @@ export const useGridCellEditing = (apiRef, props) => {
|
|
|
324
324
|
};
|
|
325
325
|
try {
|
|
326
326
|
const row = apiRef.current.getRow(id);
|
|
327
|
-
Promise.resolve(processRowUpdate(rowUpdate, row
|
|
327
|
+
Promise.resolve(processRowUpdate(rowUpdate, row, {
|
|
328
|
+
rowId: id
|
|
329
|
+
})).then(finalRowUpdate => {
|
|
328
330
|
apiRef.current.updateRows([finalRowUpdate]);
|
|
329
331
|
finishCellEditMode();
|
|
330
332
|
}).catch(handleError);
|
|
@@ -110,7 +110,7 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
110
110
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
111
111
|
if (params.cellMode === GridRowModes.Edit) {
|
|
112
112
|
// Wait until IME is settled for Asian languages like Japanese and Chinese
|
|
113
|
-
// TODO:
|
|
113
|
+
// TODO: to replace at one point. See https://github.com/mui/material-ui/pull/39713#discussion_r1381678957.
|
|
114
114
|
if (event.which === 229) {
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
@@ -397,7 +397,9 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
397
397
|
}
|
|
398
398
|
};
|
|
399
399
|
try {
|
|
400
|
-
Promise.resolve(processRowUpdate(rowUpdate, row
|
|
400
|
+
Promise.resolve(processRowUpdate(rowUpdate, row, {
|
|
401
|
+
rowId: id
|
|
402
|
+
})).then(finalRowUpdate => {
|
|
401
403
|
apiRef.current.updateRows([finalRowUpdate]);
|
|
402
404
|
finishRowEditMode();
|
|
403
405
|
}).catch(handleError);
|
|
@@ -5,6 +5,7 @@ import { useGridApiOptionHandler } from "../../utils/useGridApiEventHandler.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export function useGridEvents(apiRef, props) {
|
|
7
7
|
useGridApiOptionHandler(apiRef, 'columnHeaderClick', props.onColumnHeaderClick);
|
|
8
|
+
useGridApiOptionHandler(apiRef, 'columnHeaderContextMenu', props.onColumnHeaderContextMenu);
|
|
8
9
|
useGridApiOptionHandler(apiRef, 'columnHeaderDoubleClick', props.onColumnHeaderDoubleClick);
|
|
9
10
|
useGridApiOptionHandler(apiRef, 'columnHeaderOver', props.onColumnHeaderOver);
|
|
10
11
|
useGridApiOptionHandler(apiRef, 'columnHeaderOut', props.onColumnHeaderOut);
|
|
@@ -41,7 +41,7 @@ export const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiR
|
|
|
41
41
|
let items;
|
|
42
42
|
if (hasSeveralItems && disableMultipleColumnsFiltering) {
|
|
43
43
|
if (process.env.NODE_ENV !== 'production') {
|
|
44
|
-
warnOnce(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the
|
|
44
|
+
warnOnce(['MUI X: The `filterModel` can only contain a single item when the `disableMultipleColumnsFiltering` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
|
|
45
45
|
}
|
|
46
46
|
items = [model.items[0]];
|
|
47
47
|
} else {
|
|
@@ -3,11 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { GridSignature, useGridApiEventHandler } from "../../utils/useGridApiEventHandler.js";
|
|
4
4
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
|
|
5
5
|
import { useGridLogger } from "../../utils/useGridLogger.js";
|
|
6
|
-
import {
|
|
6
|
+
import { useGridSelector } from "../../utils/useGridSelector.js";
|
|
7
|
+
import { gridRowMaximumTreeDepthSelector, gridRowTreeSelector } from "../rows/gridRowsSelector.js";
|
|
7
8
|
import { gridRowSelectionStateSelector, selectedGridRowsSelector, selectedIdsLookupSelector } from "./gridRowSelectionSelector.js";
|
|
8
9
|
import { gridPaginatedVisibleSortedGridRowIdsSelector } from "../pagination/index.js";
|
|
9
10
|
import { gridFocusCellSelector } from "../focus/gridFocusStateSelector.js";
|
|
10
|
-
import { gridExpandedSortedRowIdsSelector,
|
|
11
|
+
import { gridExpandedSortedRowIdsSelector, gridFilteredRowsLookupSelector } from "../filter/gridFilterSelector.js";
|
|
11
12
|
import { GRID_CHECKBOX_SELECTION_COL_DEF, GRID_ACTIONS_COLUMN_TYPE } from "../../../colDef/index.js";
|
|
12
13
|
import { GridCellModes } from "../../../models/gridEditRowModel.js";
|
|
13
14
|
import { isKeyboardEvent, isNavigationKey } from "../../../utils/keyboardUtils.js";
|
|
@@ -15,7 +16,7 @@ import { useGridVisibleRows } from "../../utils/useGridVisibleRows.js";
|
|
|
15
16
|
import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from "../../../constants/gridDetailPanelToggleField.js";
|
|
16
17
|
import { gridClasses } from "../../../constants/gridClasses.js";
|
|
17
18
|
import { isEventTargetInPortal } from "../../../utils/domUtils.js";
|
|
18
|
-
import { isMultipleRowSelectionEnabled } from "./utils.js";
|
|
19
|
+
import { isMultipleRowSelectionEnabled, findRowsToSelect, findRowsToDeselect } from "./utils.js";
|
|
19
20
|
const getSelectionModelPropValue = (selectionModelProp, prevSelectionModel) => {
|
|
20
21
|
if (selectionModelProp == null) {
|
|
21
22
|
return selectionModelProp;
|
|
@@ -40,11 +41,12 @@ export const rowSelectionStateInitializer = (state, props) => _extends({}, state
|
|
|
40
41
|
*/
|
|
41
42
|
export const useGridRowSelection = (apiRef, props) => {
|
|
42
43
|
const logger = useGridLogger(apiRef, 'useGridSelection');
|
|
43
|
-
const runIfRowSelectionIsEnabled = callback => (...args) => {
|
|
44
|
+
const runIfRowSelectionIsEnabled = React.useCallback(callback => (...args) => {
|
|
44
45
|
if (props.rowSelection) {
|
|
45
46
|
callback(...args);
|
|
46
47
|
}
|
|
47
|
-
};
|
|
48
|
+
}, [props.rowSelection]);
|
|
49
|
+
const applyAutoSelection = props.signature !== GridSignature.DataGrid && (props.rowSelectionPropagation?.parents || props.rowSelectionPropagation?.descendants);
|
|
48
50
|
const propRowSelectionModel = React.useMemo(() => {
|
|
49
51
|
return getSelectionModelPropValue(props.rowSelectionModel, gridRowSelectionStateSelector(apiRef.current.state));
|
|
50
52
|
}, [apiRef, props.rowSelectionModel]);
|
|
@@ -63,6 +65,8 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
63
65
|
} = props;
|
|
64
66
|
const canHaveMultipleSelection = isMultipleRowSelectionEnabled(props);
|
|
65
67
|
const visibleRows = useGridVisibleRows(apiRef, props);
|
|
68
|
+
const tree = useGridSelector(apiRef, gridRowTreeSelector);
|
|
69
|
+
const isNestedData = useGridSelector(apiRef, gridRowMaximumTreeDepthSelector) > 1;
|
|
66
70
|
const expandMouseRowRangeSelection = React.useCallback(id => {
|
|
67
71
|
let endId = id;
|
|
68
72
|
const startId = lastRowToggled.current ?? id;
|
|
@@ -87,7 +91,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
87
91
|
}, !isSelected);
|
|
88
92
|
}, [apiRef]);
|
|
89
93
|
|
|
90
|
-
|
|
94
|
+
/*
|
|
91
95
|
* API METHODS
|
|
92
96
|
*/
|
|
93
97
|
const setRowSelectionModel = React.useCallback(model => {
|
|
@@ -125,34 +129,80 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
125
129
|
lastRowToggled.current = id;
|
|
126
130
|
if (resetSelection) {
|
|
127
131
|
logger.debug(`Setting selection for row ${id}`);
|
|
128
|
-
|
|
132
|
+
const newSelection = [];
|
|
133
|
+
const addRow = rowId => {
|
|
134
|
+
newSelection.push(rowId);
|
|
135
|
+
};
|
|
136
|
+
if (isSelected) {
|
|
137
|
+
addRow(id);
|
|
138
|
+
if (applyAutoSelection) {
|
|
139
|
+
findRowsToSelect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
apiRef.current.setRowSelectionModel(newSelection);
|
|
129
143
|
} else {
|
|
130
144
|
logger.debug(`Toggling selection for row ${id}`);
|
|
131
145
|
const selection = gridRowSelectionStateSelector(apiRef.current.state);
|
|
132
|
-
const newSelection = selection
|
|
146
|
+
const newSelection = new Set(selection);
|
|
147
|
+
newSelection.delete(id);
|
|
148
|
+
const addRow = rowId => {
|
|
149
|
+
newSelection.add(rowId);
|
|
150
|
+
};
|
|
151
|
+
const removeRow = rowId => {
|
|
152
|
+
newSelection.delete(rowId);
|
|
153
|
+
};
|
|
133
154
|
if (isSelected) {
|
|
134
|
-
|
|
155
|
+
addRow(id);
|
|
156
|
+
if (applyAutoSelection) {
|
|
157
|
+
findRowsToSelect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
|
|
158
|
+
}
|
|
159
|
+
} else if (applyAutoSelection) {
|
|
160
|
+
findRowsToDeselect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, removeRow);
|
|
135
161
|
}
|
|
136
|
-
const isSelectionValid = newSelection.
|
|
162
|
+
const isSelectionValid = newSelection.size < 2 || canHaveMultipleSelection;
|
|
137
163
|
if (isSelectionValid) {
|
|
138
|
-
apiRef.current.setRowSelectionModel(newSelection);
|
|
164
|
+
apiRef.current.setRowSelectionModel(Array.from(newSelection));
|
|
139
165
|
}
|
|
140
166
|
}
|
|
141
|
-
}, [apiRef, logger, canHaveMultipleSelection]);
|
|
167
|
+
}, [apiRef, logger, applyAutoSelection, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents, canHaveMultipleSelection]);
|
|
142
168
|
const selectRows = React.useCallback((ids, isSelected = true, resetSelection = false) => {
|
|
143
169
|
logger.debug(`Setting selection for several rows`);
|
|
144
170
|
const selectableIds = ids.filter(id => apiRef.current.isRowSelectable(id));
|
|
145
171
|
let newSelection;
|
|
146
172
|
if (resetSelection) {
|
|
147
|
-
|
|
173
|
+
if (isSelected) {
|
|
174
|
+
newSelection = selectableIds;
|
|
175
|
+
if (applyAutoSelection) {
|
|
176
|
+
const addRow = rowId => {
|
|
177
|
+
newSelection.push(rowId);
|
|
178
|
+
};
|
|
179
|
+
selectableIds.forEach(id => {
|
|
180
|
+
findRowsToSelect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
newSelection = [];
|
|
185
|
+
}
|
|
148
186
|
} else {
|
|
149
187
|
// We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
|
|
150
188
|
const selectionLookup = _extends({}, selectedIdsLookupSelector(apiRef));
|
|
189
|
+
const addRow = rowId => {
|
|
190
|
+
selectionLookup[rowId] = rowId;
|
|
191
|
+
};
|
|
192
|
+
const removeRow = rowId => {
|
|
193
|
+
delete selectionLookup[rowId];
|
|
194
|
+
};
|
|
151
195
|
selectableIds.forEach(id => {
|
|
152
196
|
if (isSelected) {
|
|
153
197
|
selectionLookup[id] = id;
|
|
198
|
+
if (applyAutoSelection) {
|
|
199
|
+
findRowsToSelect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
|
|
200
|
+
}
|
|
154
201
|
} else {
|
|
155
|
-
|
|
202
|
+
removeRow(id);
|
|
203
|
+
if (applyAutoSelection) {
|
|
204
|
+
findRowsToDeselect(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, removeRow);
|
|
205
|
+
}
|
|
156
206
|
}
|
|
157
207
|
});
|
|
158
208
|
newSelection = Object.values(selectionLookup);
|
|
@@ -161,7 +211,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
161
211
|
if (isSelectionValid) {
|
|
162
212
|
apiRef.current.setRowSelectionModel(newSelection);
|
|
163
213
|
}
|
|
164
|
-
}, [apiRef,
|
|
214
|
+
}, [logger, applyAutoSelection, canHaveMultipleSelection, apiRef, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents]);
|
|
165
215
|
const selectRowRange = React.useCallback(({
|
|
166
216
|
startId,
|
|
167
217
|
endId
|
|
@@ -193,29 +243,52 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
193
243
|
useGridApiMethod(apiRef, selectionPublicApi, 'public');
|
|
194
244
|
useGridApiMethod(apiRef, selectionPrivateApi, props.signature === GridSignature.DataGrid ? 'private' : 'public');
|
|
195
245
|
|
|
196
|
-
|
|
246
|
+
/*
|
|
197
247
|
* EVENTS
|
|
198
248
|
*/
|
|
199
|
-
const removeOutdatedSelection = React.useCallback(() => {
|
|
200
|
-
if (props.keepNonExistentRowsSelected) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
249
|
+
const removeOutdatedSelection = React.useCallback((sortModelUpdated = false) => {
|
|
203
250
|
const currentSelection = gridRowSelectionStateSelector(apiRef.current.state);
|
|
204
|
-
const
|
|
251
|
+
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
205
252
|
|
|
206
253
|
// We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
|
|
207
254
|
const selectionLookup = _extends({}, selectedIdsLookupSelector(apiRef));
|
|
208
255
|
let hasChanged = false;
|
|
209
256
|
currentSelection.forEach(id => {
|
|
210
|
-
if (
|
|
257
|
+
if (filteredRowsLookup[id] === false) {
|
|
258
|
+
if (props.keepNonExistentRowsSelected) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
211
261
|
delete selectionLookup[id];
|
|
212
262
|
hasChanged = true;
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
if (!props.rowSelectionPropagation?.parents) {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
const node = tree[id];
|
|
269
|
+
if (node.type === 'group') {
|
|
270
|
+
const isAutoGenerated = node.isAutoGenerated;
|
|
271
|
+
if (isAutoGenerated) {
|
|
272
|
+
delete selectionLookup[id];
|
|
273
|
+
hasChanged = true;
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// Keep previously selected tree data parents selected if all their children are filtered out
|
|
277
|
+
if (!node.children.every(childId => filteredRowsLookup[childId] === false)) {
|
|
278
|
+
delete selectionLookup[id];
|
|
279
|
+
hasChanged = true;
|
|
280
|
+
}
|
|
213
281
|
}
|
|
214
282
|
});
|
|
215
|
-
if (hasChanged) {
|
|
216
|
-
|
|
283
|
+
if (hasChanged || isNestedData && !sortModelUpdated) {
|
|
284
|
+
const newSelection = Object.values(selectionLookup);
|
|
285
|
+
if (isNestedData) {
|
|
286
|
+
apiRef.current.selectRows(newSelection, true, true);
|
|
287
|
+
} else {
|
|
288
|
+
apiRef.current.setRowSelectionModel(newSelection);
|
|
289
|
+
}
|
|
217
290
|
}
|
|
218
|
-
}, [apiRef, props.keepNonExistentRowsSelected]);
|
|
291
|
+
}, [apiRef, isNestedData, props.rowSelectionPropagation?.parents, props.keepNonExistentRowsSelected, tree]);
|
|
219
292
|
const handleSingleRowSelection = React.useCallback((id, event) => {
|
|
220
293
|
const hasCtrlKey = event.metaKey || event.ctrlKey;
|
|
221
294
|
|
|
@@ -276,8 +349,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
276
349
|
}, [apiRef, expandMouseRowRangeSelection, canHaveMultipleSelection]);
|
|
277
350
|
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
|
|
278
351
|
const rowsToBeSelected = props.pagination && props.checkboxSelectionVisibleOnly && props.paginationMode === 'client' ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
|
|
279
|
-
|
|
280
|
-
apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0);
|
|
352
|
+
apiRef.current.selectRows(rowsToBeSelected, params.value);
|
|
281
353
|
}, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination, props.paginationMode]);
|
|
282
354
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
283
355
|
// Get the most recent cell mode because it may have been changed by another listener
|
|
@@ -341,14 +413,15 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
341
413
|
selectRows(apiRef.current.getAllRowIds(), true);
|
|
342
414
|
}
|
|
343
415
|
}, [apiRef, handleSingleRowSelection, selectRows, visibleRows.rows, canHaveMultipleSelection]);
|
|
344
|
-
useGridApiEventHandler(apiRef, 'sortedRowsSet', runIfRowSelectionIsEnabled(removeOutdatedSelection));
|
|
416
|
+
useGridApiEventHandler(apiRef, 'sortedRowsSet', runIfRowSelectionIsEnabled(() => removeOutdatedSelection(true)));
|
|
417
|
+
useGridApiEventHandler(apiRef, 'filteredRowsSet', runIfRowSelectionIsEnabled(removeOutdatedSelection));
|
|
345
418
|
useGridApiEventHandler(apiRef, 'rowClick', runIfRowSelectionIsEnabled(handleRowClick));
|
|
346
419
|
useGridApiEventHandler(apiRef, 'rowSelectionCheckboxChange', runIfRowSelectionIsEnabled(handleRowSelectionCheckboxChange));
|
|
347
420
|
useGridApiEventHandler(apiRef, 'headerSelectionCheckboxChange', handleHeaderSelectionCheckboxChange);
|
|
348
421
|
useGridApiEventHandler(apiRef, 'cellMouseDown', runIfRowSelectionIsEnabled(preventSelectionOnShift));
|
|
349
422
|
useGridApiEventHandler(apiRef, 'cellKeyDown', runIfRowSelectionIsEnabled(handleCellKeyDown));
|
|
350
423
|
|
|
351
|
-
|
|
424
|
+
/*
|
|
352
425
|
* EFFECTS
|
|
353
426
|
*/
|
|
354
427
|
React.useEffect(() => {
|
|
@@ -386,4 +459,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
386
459
|
apiRef.current.setRowSelectionModel([]);
|
|
387
460
|
}
|
|
388
461
|
}, [apiRef, canHaveMultipleSelection, checkboxSelection, isStateControlled, props.rowSelection]);
|
|
462
|
+
React.useEffect(() => {
|
|
463
|
+
runIfRowSelectionIsEnabled(removeOutdatedSelection);
|
|
464
|
+
}, [removeOutdatedSelection, runIfRowSelectionIsEnabled]);
|
|
389
465
|
};
|
|
@@ -1,8 +1,163 @@
|
|
|
1
1
|
import { GridSignature } from "../../utils/useGridApiEventHandler.js";
|
|
2
|
+
import { GRID_ROOT_GROUP_ID } from "../rows/gridRowsUtils.js";
|
|
3
|
+
import { gridFilteredRowsLookupSelector } from "../filter/gridFilterSelector.js";
|
|
4
|
+
import { gridSortedRowIdsSelector } from "../sorting/gridSortingSelector.js";
|
|
5
|
+
import { selectedIdsLookupSelector } from "./gridRowSelectionSelector.js";
|
|
6
|
+
import { gridRowTreeSelector } from "../rows/gridRowsSelector.js";
|
|
7
|
+
import { createSelector } from "../../../utils/createSelector.js";
|
|
8
|
+
export const ROW_SELECTION_PROPAGATION_DEFAULT = {
|
|
9
|
+
parents: false,
|
|
10
|
+
descendants: false
|
|
11
|
+
};
|
|
12
|
+
function getGridRowGroupSelectableDescendants(apiRef, groupId) {
|
|
13
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
14
|
+
const sortedRowIds = gridSortedRowIdsSelector(apiRef);
|
|
15
|
+
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
16
|
+
const groupNode = rowTree[groupId];
|
|
17
|
+
if (!groupNode || groupNode.type !== 'group') {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const descendants = [];
|
|
21
|
+
const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1;
|
|
22
|
+
for (let index = startIndex; index < sortedRowIds.length && rowTree[sortedRowIds[index]]?.depth > groupNode.depth; index += 1) {
|
|
23
|
+
const id = sortedRowIds[index];
|
|
24
|
+
if (filteredRowsLookup[id] !== false && apiRef.current.isRowSelectable(id)) {
|
|
25
|
+
descendants.push(id);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return descendants;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// TODO v8: Use `createSelectorV8`
|
|
32
|
+
export function getCheckboxPropsSelector(groupId, autoSelectParents) {
|
|
33
|
+
return createSelector(gridRowTreeSelector, gridSortedRowIdsSelector, gridFilteredRowsLookupSelector, selectedIdsLookupSelector, (rowTree, sortedRowIds, filteredRowsLookup, rowSelectionLookup) => {
|
|
34
|
+
const groupNode = rowTree[groupId];
|
|
35
|
+
if (!groupNode || groupNode.type !== 'group') {
|
|
36
|
+
return {
|
|
37
|
+
isIndeterminate: false,
|
|
38
|
+
isChecked: rowSelectionLookup[groupId] === groupId
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (rowSelectionLookup[groupId] === groupId) {
|
|
42
|
+
return {
|
|
43
|
+
isIndeterminate: false,
|
|
44
|
+
isChecked: true
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
let selectableDescendantsCount = 0;
|
|
48
|
+
let selectedDescendantsCount = 0;
|
|
49
|
+
const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1;
|
|
50
|
+
for (let index = startIndex; index < sortedRowIds.length && rowTree[sortedRowIds[index]]?.depth > groupNode.depth; index += 1) {
|
|
51
|
+
const id = sortedRowIds[index];
|
|
52
|
+
if (filteredRowsLookup[id] !== false) {
|
|
53
|
+
selectableDescendantsCount += 1;
|
|
54
|
+
if (rowSelectionLookup[id] !== undefined) {
|
|
55
|
+
selectedDescendantsCount += 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
isIndeterminate: selectedDescendantsCount > 0 && selectedDescendantsCount < selectableDescendantsCount || selectedDescendantsCount === selectableDescendantsCount && rowSelectionLookup[groupId] === undefined,
|
|
61
|
+
isChecked: autoSelectParents ? selectedDescendantsCount > 0 : rowSelectionLookup[groupId] === groupId
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
}
|
|
2
65
|
export function isMultipleRowSelectionEnabled(props) {
|
|
3
66
|
if (props.signature === GridSignature.DataGrid) {
|
|
4
67
|
// DataGrid Community has multiple row selection enabled only if checkbox selection is enabled.
|
|
5
68
|
return props.checkboxSelection && props.disableMultipleRowSelection !== true;
|
|
6
69
|
}
|
|
7
70
|
return !props.disableMultipleRowSelection;
|
|
8
|
-
}
|
|
71
|
+
}
|
|
72
|
+
const getRowNodeParents = (tree, id) => {
|
|
73
|
+
const parents = [];
|
|
74
|
+
let parent = id;
|
|
75
|
+
while (parent != null && parent !== GRID_ROOT_GROUP_ID) {
|
|
76
|
+
const node = tree[parent];
|
|
77
|
+
if (!node) {
|
|
78
|
+
return parents;
|
|
79
|
+
}
|
|
80
|
+
parents.push(parent);
|
|
81
|
+
parent = node.parent;
|
|
82
|
+
}
|
|
83
|
+
return parents;
|
|
84
|
+
};
|
|
85
|
+
const getFilteredRowNodeSiblings = (tree, filteredRows, id) => {
|
|
86
|
+
const node = tree[id];
|
|
87
|
+
if (!node) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
const parent = node.parent;
|
|
91
|
+
if (parent == null) {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
const parentNode = tree[parent];
|
|
95
|
+
return parentNode.children.filter(childId => childId !== id && filteredRows[childId]);
|
|
96
|
+
};
|
|
97
|
+
export const findRowsToSelect = (apiRef, tree, selectedRow, autoSelectDescendants, autoSelectParents, addRow) => {
|
|
98
|
+
const filteredRows = gridFilteredRowsLookupSelector(apiRef);
|
|
99
|
+
const selectedIdsLookup = selectedIdsLookupSelector(apiRef);
|
|
100
|
+
const selectedDescendants = new Set([]);
|
|
101
|
+
if (!autoSelectDescendants && !autoSelectParents) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (autoSelectDescendants) {
|
|
105
|
+
const rowNode = tree[selectedRow];
|
|
106
|
+
if (rowNode?.type === 'group') {
|
|
107
|
+
const descendants = getGridRowGroupSelectableDescendants(apiRef, selectedRow);
|
|
108
|
+
descendants.forEach(rowId => {
|
|
109
|
+
addRow(rowId);
|
|
110
|
+
selectedDescendants.add(rowId);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (autoSelectParents) {
|
|
115
|
+
const checkAllDescendantsSelected = rowId => {
|
|
116
|
+
if (selectedIdsLookup[rowId] !== rowId && !selectedDescendants.has(rowId)) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const node = tree[rowId];
|
|
120
|
+
if (node?.type !== 'group') {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
return node.children.every(checkAllDescendantsSelected);
|
|
124
|
+
};
|
|
125
|
+
const traverseParents = rowId => {
|
|
126
|
+
const siblings = getFilteredRowNodeSiblings(tree, filteredRows, rowId);
|
|
127
|
+
if (siblings.length === 0 || siblings.every(checkAllDescendantsSelected)) {
|
|
128
|
+
const rowNode = tree[rowId];
|
|
129
|
+
const parent = rowNode.parent;
|
|
130
|
+
if (parent != null && parent !== GRID_ROOT_GROUP_ID && apiRef.current.isRowSelectable(parent)) {
|
|
131
|
+
addRow(parent);
|
|
132
|
+
selectedDescendants.add(parent);
|
|
133
|
+
traverseParents(parent);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
traverseParents(selectedRow);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
export const findRowsToDeselect = (apiRef, tree, deselectedRow, autoSelectDescendants, autoSelectParents, removeRow) => {
|
|
141
|
+
const selectedIdsLookup = selectedIdsLookupSelector(apiRef);
|
|
142
|
+
if (!autoSelectParents && !autoSelectDescendants) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (autoSelectParents) {
|
|
146
|
+
const allParents = getRowNodeParents(tree, deselectedRow);
|
|
147
|
+
allParents.forEach(parent => {
|
|
148
|
+
const isSelected = selectedIdsLookup[parent] === parent;
|
|
149
|
+
if (isSelected) {
|
|
150
|
+
removeRow(parent);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
if (autoSelectDescendants) {
|
|
155
|
+
const rowNode = tree[deselectedRow];
|
|
156
|
+
if (rowNode?.type === 'group') {
|
|
157
|
+
const descendants = getGridRowGroupSelectableDescendants(apiRef, deselectedRow);
|
|
158
|
+
descendants.forEach(descendant => {
|
|
159
|
+
removeRow(descendant);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
};
|