@mui/x-data-grid 8.8.0 → 8.9.1
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 +131 -24
- package/DataGrid/index.d.ts +0 -1
- package/DataGrid/useDataGridComponent.js +8 -0
- package/components/GridScrollArea.js +1 -1
- package/components/containers/GridRootStyles.js +39 -0
- package/constants/gridClasses.d.ts +12 -0
- package/constants/gridClasses.js +3 -1
- package/esm/DataGrid/index.d.ts +0 -1
- package/esm/DataGrid/useDataGridComponent.js +8 -0
- package/esm/components/GridScrollArea.js +1 -1
- package/esm/components/containers/GridRootStyles.js +39 -0
- package/esm/constants/gridClasses.d.ts +12 -0
- package/esm/constants/gridClasses.js +3 -1
- package/esm/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
- package/esm/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
- package/esm/hooks/core/useGridProps.d.ts +2 -2
- package/esm/hooks/core/useGridProps.js +3 -1
- package/esm/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
- package/esm/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
- package/esm/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
- package/esm/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
- package/esm/hooks/features/columns/gridColumnsSelector.js +6 -2
- package/esm/hooks/features/columns/gridColumnsUtils.js +6 -4
- package/esm/hooks/features/columns/useGridColumns.js +8 -10
- package/esm/hooks/features/export/utils.js +1 -1
- package/esm/hooks/features/filter/useGridFilter.js +3 -3
- package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
- package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +5 -9
- package/esm/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
- package/esm/hooks/features/listView/gridListViewSelectors.js +7 -0
- package/esm/hooks/features/rowSelection/useGridRowSelection.js +5 -4
- package/esm/hooks/features/rows/gridRowsUtils.d.ts +1 -1
- package/esm/hooks/features/rows/gridRowsUtils.js +5 -2
- package/esm/hooks/features/rows/useGridRows.js +4 -3
- package/esm/hooks/features/scroll/useGridScroll.d.ts +1 -1
- package/esm/hooks/features/scroll/useGridScroll.js +2 -3
- package/esm/hooks/features/virtualization/useGridVirtualScroller.js +3 -6
- package/esm/hooks/utils/index.d.ts +1 -0
- package/esm/hooks/utils/index.js +2 -1
- package/esm/hooks/utils/useGridInitializeState.d.ts +1 -1
- package/esm/hooks/utils/useGridInitializeState.js +6 -1
- package/esm/hooks/utils/useRunOncePerLoop.d.ts +1 -0
- package/esm/hooks/utils/useRunOncePerLoop.js +26 -0
- package/esm/index.js +1 -1
- package/esm/models/api/gridRowApi.d.ts +5 -0
- package/esm/models/events/gridEventLookup.d.ts +2 -1
- package/esm/models/gridApiCaches.d.ts +8 -2
- package/esm/models/gridStateCommunity.d.ts +2 -2
- package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
- package/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
- package/hooks/core/useGridProps.d.ts +2 -2
- package/hooks/core/useGridProps.js +3 -1
- package/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
- package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
- package/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
- package/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
- package/hooks/features/columns/gridColumnsSelector.js +6 -2
- package/hooks/features/columns/gridColumnsUtils.js +6 -4
- package/hooks/features/columns/useGridColumns.js +8 -10
- package/hooks/features/export/utils.js +1 -1
- package/hooks/features/filter/useGridFilter.js +3 -3
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +5 -9
- package/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
- package/hooks/features/listView/gridListViewSelectors.js +8 -1
- package/hooks/features/rowSelection/useGridRowSelection.js +5 -4
- package/hooks/features/rows/gridRowsUtils.d.ts +1 -1
- package/hooks/features/rows/gridRowsUtils.js +5 -2
- package/hooks/features/rows/useGridRows.js +4 -3
- package/hooks/features/scroll/useGridScroll.d.ts +1 -1
- package/hooks/features/scroll/useGridScroll.js +2 -3
- package/hooks/features/virtualization/useGridVirtualScroller.js +3 -6
- package/hooks/utils/index.d.ts +1 -0
- package/hooks/utils/index.js +12 -0
- package/hooks/utils/useGridInitializeState.d.ts +1 -1
- package/hooks/utils/useGridInitializeState.js +6 -1
- package/hooks/utils/useRunOncePerLoop.d.ts +1 -0
- package/hooks/utils/useRunOncePerLoop.js +33 -0
- package/index.js +1 -1
- package/models/api/gridRowApi.d.ts +5 -0
- package/models/events/gridEventLookup.d.ts +2 -1
- package/models/gridApiCaches.d.ts +8 -2
- package/models/gridStateCommunity.d.ts +2 -2
- package/package.json +1 -1
|
@@ -49,7 +49,8 @@ export const useGridPipeProcessing = apiRef => {
|
|
|
49
49
|
cache.current[group] = {
|
|
50
50
|
processors: new Map(),
|
|
51
51
|
processorsAsArray: [],
|
|
52
|
-
appliers: {}
|
|
52
|
+
appliers: {},
|
|
53
|
+
processorsUpdated: false
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
56
|
const groupCache = cache.current[group];
|
|
@@ -57,19 +58,20 @@ export const useGridPipeProcessing = apiRef => {
|
|
|
57
58
|
if (oldProcessor !== processor) {
|
|
58
59
|
groupCache.processors.set(id, processor);
|
|
59
60
|
groupCache.processorsAsArray = Array.from(cache.current[group].processors.values()).filter(processorValue => processorValue !== null);
|
|
60
|
-
|
|
61
|
+
groupCache.processorsUpdated = true;
|
|
61
62
|
}
|
|
62
63
|
return () => {
|
|
63
64
|
cache.current[group].processors.set(id, null);
|
|
64
65
|
cache.current[group].processorsAsArray = Array.from(cache.current[group].processors.values()).filter(processorValue => processorValue !== null);
|
|
65
66
|
};
|
|
66
|
-
}, [
|
|
67
|
+
}, []);
|
|
67
68
|
const registerPipeApplier = React.useCallback((group, id, applier) => {
|
|
68
69
|
if (!cache.current[group]) {
|
|
69
70
|
cache.current[group] = {
|
|
70
71
|
processors: new Map(),
|
|
71
72
|
processorsAsArray: [],
|
|
72
|
-
appliers: {}
|
|
73
|
+
appliers: {},
|
|
74
|
+
processorsUpdated: false
|
|
73
75
|
};
|
|
74
76
|
}
|
|
75
77
|
cache.current[group].appliers[id] = applier;
|
|
@@ -82,6 +84,18 @@ export const useGridPipeProcessing = apiRef => {
|
|
|
82
84
|
const requestPipeProcessorsApplication = React.useCallback(group => {
|
|
83
85
|
runAppliers(cache.current[group]);
|
|
84
86
|
}, [runAppliers]);
|
|
87
|
+
const runAppliersForPendingProcessors = React.useCallback(() => {
|
|
88
|
+
for (const group in cache.current) {
|
|
89
|
+
if (!Object.prototype.hasOwnProperty.call(cache.current, group)) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const groupCache = cache.current[group];
|
|
93
|
+
if (groupCache.processorsUpdated) {
|
|
94
|
+
groupCache.processorsUpdated = false;
|
|
95
|
+
runAppliers(groupCache);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}, [runAppliers]);
|
|
85
99
|
const applyPipeProcessors = React.useCallback((...args) => {
|
|
86
100
|
const [group, value, context] = args;
|
|
87
101
|
if (!cache.current[group]) {
|
|
@@ -97,7 +111,8 @@ export const useGridPipeProcessing = apiRef => {
|
|
|
97
111
|
const preProcessingPrivateApi = {
|
|
98
112
|
registerPipeProcessor,
|
|
99
113
|
registerPipeApplier,
|
|
100
|
-
requestPipeProcessorsApplication
|
|
114
|
+
requestPipeProcessorsApplication,
|
|
115
|
+
runAppliersForPendingProcessors
|
|
101
116
|
};
|
|
102
117
|
const preProcessingPublicApi = {
|
|
103
118
|
unstable_applyPipeProcessors: applyPipeProcessors
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { RefObject } from '@mui/x-internals/types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { DataGridProcessedProps } from "../../models/props/DataGridProps.js";
|
|
3
3
|
import type { GridPrivateApiCommon } from "../../models/api/gridApiCommon.js";
|
|
4
4
|
import type { GridStateInitializer } from "../utils/useGridInitializeState.js";
|
|
5
|
-
type Props = Pick<
|
|
5
|
+
type Props = Pick<DataGridProcessedProps, 'getRowId' | 'listView'>;
|
|
6
6
|
export declare const propsStateInitializer: GridStateInitializer<Props>;
|
|
7
7
|
export declare const useGridProps: <PrivateApi extends GridPrivateApiCommon>(apiRef: RefObject<PrivateApi>, props: Props) => void;
|
|
8
8
|
export {};
|
|
@@ -5,6 +5,7 @@ import * as React from 'react';
|
|
|
5
5
|
export const propsStateInitializer = (state, props) => {
|
|
6
6
|
return _extends({}, state, {
|
|
7
7
|
props: {
|
|
8
|
+
listView: props.listView,
|
|
8
9
|
getRowId: props.getRowId
|
|
9
10
|
}
|
|
10
11
|
});
|
|
@@ -13,8 +14,9 @@ export const useGridProps = (apiRef, props) => {
|
|
|
13
14
|
React.useEffect(() => {
|
|
14
15
|
apiRef.current.setState(state => _extends({}, state, {
|
|
15
16
|
props: {
|
|
17
|
+
listView: props.listView,
|
|
16
18
|
getRowId: props.getRowId
|
|
17
19
|
}
|
|
18
20
|
}));
|
|
19
|
-
}, [apiRef, props.getRowId]);
|
|
21
|
+
}, [apiRef, props.listView, props.getRowId]);
|
|
20
22
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GridColumnGroup } from "../../../models/gridColumnGrouping.js";
|
|
1
|
+
import { GridColumnGroup, GridColumnGroupingModel } from "../../../models/gridColumnGrouping.js";
|
|
2
2
|
export type GridColumnGroupLookup = {
|
|
3
3
|
[groupId: string]: Omit<GridColumnGroup, 'children'>;
|
|
4
4
|
};
|
|
@@ -13,4 +13,7 @@ export interface GridColumnsGroupingState {
|
|
|
13
13
|
[columnField: string]: GridColumnGroup['groupId'][];
|
|
14
14
|
};
|
|
15
15
|
maxDepth: number;
|
|
16
|
+
}
|
|
17
|
+
export interface GridColumnGroupingInternalCache {
|
|
18
|
+
lastColumnGroupingModel?: GridColumnGroupingModel;
|
|
16
19
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
|
|
2
1
|
import { isLeaf } from "../../../models/gridColumnGrouping.js";
|
|
3
2
|
// This is the recurrence function that help writing `unwrapGroupingColumnModel()`
|
|
4
3
|
const recurrentUnwrapGroupingColumnModel = (columnGroupNode, parents, unwrappedGroupingModelToComplete) => {
|
|
@@ -37,45 +36,49 @@ export const unwrapGroupingColumnModel = columnGroupingModel => {
|
|
|
37
36
|
export const getColumnGroupsHeaderStructure = (orderedColumns, unwrappedGroupingModel, pinnedFields) => {
|
|
38
37
|
const getParents = field => unwrappedGroupingModel[field] ?? [];
|
|
39
38
|
const groupingHeaderStructure = [];
|
|
40
|
-
const maxDepth = Math.max(...orderedColumns.map(field => getParents(field).length));
|
|
41
|
-
const haveSameParents = (field1, field2, depth) =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
39
|
+
const maxDepth = Math.max(0, ...orderedColumns.map(field => getParents(field).length));
|
|
40
|
+
const haveSameParents = (field1, field2, depth) => {
|
|
41
|
+
const a = getParents(field1);
|
|
42
|
+
const b = getParents(field2);
|
|
43
|
+
for (let i = 0; i <= depth; i += 1) {
|
|
44
|
+
if (a[i] !== b[i]) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
48
47
|
}
|
|
49
|
-
return
|
|
48
|
+
return true;
|
|
49
|
+
};
|
|
50
|
+
const haveDifferentContainers = (field1, field2) => {
|
|
51
|
+
const left = pinnedFields?.left;
|
|
52
|
+
const right = pinnedFields?.right;
|
|
53
|
+
const inLeft1 = !!left?.includes(field1);
|
|
54
|
+
const inLeft2 = !!left?.includes(field2);
|
|
55
|
+
const inRight1 = !!right?.includes(field1);
|
|
56
|
+
const inRight2 = !!right?.includes(field2);
|
|
57
|
+
return inLeft1 !== inLeft2 || inRight1 !== inRight2;
|
|
50
58
|
};
|
|
51
59
|
for (let depth = 0; depth < maxDepth; depth += 1) {
|
|
52
|
-
const depthStructure =
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
const depthStructure = [];
|
|
61
|
+
for (let i = 0; i < orderedColumns.length; i += 1) {
|
|
62
|
+
const field = orderedColumns[i];
|
|
63
|
+
const groupId = getParents(field)[depth] ?? null;
|
|
64
|
+
if (depthStructure.length === 0) {
|
|
65
|
+
depthStructure.push({
|
|
66
|
+
columnFields: [field],
|
|
57
67
|
groupId
|
|
58
|
-
}
|
|
68
|
+
});
|
|
69
|
+
continue;
|
|
59
70
|
}
|
|
60
|
-
const lastGroup =
|
|
71
|
+
const lastGroup = depthStructure[depthStructure.length - 1];
|
|
61
72
|
const prevField = lastGroup.columnFields[lastGroup.columnFields.length - 1];
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
haveDifferentContainers(prevField, newField)) {
|
|
66
|
-
// It's a new group
|
|
67
|
-
return [...structure, {
|
|
68
|
-
columnFields: [newField],
|
|
73
|
+
if (lastGroup.groupId !== groupId || !haveSameParents(prevField, field, depth) || haveDifferentContainers(prevField, field)) {
|
|
74
|
+
depthStructure.push({
|
|
75
|
+
columnFields: [field],
|
|
69
76
|
groupId
|
|
70
|
-
}
|
|
77
|
+
});
|
|
78
|
+
} else {
|
|
79
|
+
lastGroup.columnFields.push(field);
|
|
71
80
|
}
|
|
72
|
-
|
|
73
|
-
// It extends the previous group
|
|
74
|
-
return [...structure.slice(0, structure.length - 1), {
|
|
75
|
-
columnFields: [...lastGroup.columnFields, newField],
|
|
76
|
-
groupId
|
|
77
|
-
}];
|
|
78
|
-
}, []);
|
|
81
|
+
}
|
|
79
82
|
groupingHeaderStructure.push(depthStructure);
|
|
80
83
|
}
|
|
81
84
|
return groupingHeaderStructure;
|
|
@@ -11,10 +11,11 @@ import { getColumnGroupsHeaderStructure, unwrapGroupingColumnModel } from "./gri
|
|
|
11
11
|
import { useGridEvent } from "../../utils/useGridEvent.js";
|
|
12
12
|
import { gridColumnFieldsSelector, gridVisibleColumnFieldsSelector } from "../columns/index.js";
|
|
13
13
|
const createGroupLookup = columnGroupingModel => {
|
|
14
|
-
|
|
15
|
-
columnGroupingModel.
|
|
14
|
+
const groupLookup = {};
|
|
15
|
+
for (let i = 0; i < columnGroupingModel.length; i += 1) {
|
|
16
|
+
const node = columnGroupingModel[i];
|
|
16
17
|
if (isLeaf(node)) {
|
|
17
|
-
|
|
18
|
+
continue;
|
|
18
19
|
}
|
|
19
20
|
const {
|
|
20
21
|
groupId,
|
|
@@ -24,10 +25,8 @@ const createGroupLookup = columnGroupingModel => {
|
|
|
24
25
|
if (!groupId) {
|
|
25
26
|
throw new Error('MUI X: An element of the columnGroupingModel does not have either `field` or `groupId`.');
|
|
26
27
|
}
|
|
27
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
28
|
-
|
|
29
|
-
console.warn(`MUI X: group groupId=${groupId} has no children.`);
|
|
30
|
-
}
|
|
28
|
+
if (process.env.NODE_ENV !== 'production' && !children) {
|
|
29
|
+
console.warn(`MUI X: group groupId=${groupId} has no children.`);
|
|
31
30
|
}
|
|
32
31
|
const groupParam = _extends({}, other, {
|
|
33
32
|
groupId
|
|
@@ -36,13 +35,15 @@ const createGroupLookup = columnGroupingModel => {
|
|
|
36
35
|
if (subTreeLookup[groupId] !== undefined || groupLookup[groupId] !== undefined) {
|
|
37
36
|
throw new Error(`MUI X: The groupId ${groupId} is used multiple times in the columnGroupingModel.`);
|
|
38
37
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return _extends({}, groupLookup);
|
|
38
|
+
Object.assign(groupLookup, subTreeLookup);
|
|
39
|
+
groupLookup[groupId] = groupParam;
|
|
40
|
+
}
|
|
41
|
+
return groupLookup;
|
|
44
42
|
};
|
|
45
43
|
export const columnGroupsStateInitializer = (state, props, apiRef) => {
|
|
44
|
+
apiRef.current.caches.columnGrouping = {
|
|
45
|
+
lastColumnGroupingModel: props.columnGroupingModel
|
|
46
|
+
};
|
|
46
47
|
if (!props.columnGroupingModel) {
|
|
47
48
|
return state;
|
|
48
49
|
}
|
|
@@ -97,6 +98,7 @@ export const useGridColumnGrouping = (apiRef, props) => {
|
|
|
97
98
|
});
|
|
98
99
|
}, [apiRef, props.columnGroupingModel]);
|
|
99
100
|
const updateColumnGroupingState = React.useCallback(columnGroupingModel => {
|
|
101
|
+
apiRef.current.caches.columnGrouping.lastColumnGroupingModel = columnGroupingModel;
|
|
100
102
|
// @ts-expect-error Move this logic to `Pro` package
|
|
101
103
|
const pinnedColumns = apiRef.current.getPinnedColumns?.() ?? {};
|
|
102
104
|
const columnFields = gridColumnFieldsSelector(apiRef);
|
|
@@ -128,6 +130,9 @@ export const useGridColumnGrouping = (apiRef, props) => {
|
|
|
128
130
|
* EFFECTS
|
|
129
131
|
*/
|
|
130
132
|
React.useEffect(() => {
|
|
133
|
+
if (props.columnGroupingModel === apiRef.current.caches.columnGrouping.lastColumnGroupingModel) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
131
136
|
updateColumnGroupingState(props.columnGroupingModel);
|
|
132
|
-
}, [updateColumnGroupingState, props.columnGroupingModel]);
|
|
137
|
+
}, [apiRef, updateColumnGroupingState, props.columnGroupingModel]);
|
|
133
138
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GridColDef, GridStateColDef } from "../../../models/colDef/gridColDef.js";
|
|
1
|
+
import type { GridColDef, GridStateColDef } from "../../../models/colDef/gridColDef.js";
|
|
2
2
|
import type { GridColumnDimensionProperties } from "./gridColumnsUtils.js";
|
|
3
3
|
export declare enum GridPinnedColumnPosition {
|
|
4
4
|
LEFT = "left",
|
|
@@ -21,8 +21,8 @@ export interface GridPinnedColumnFields {
|
|
|
21
21
|
right?: string[];
|
|
22
22
|
}
|
|
23
23
|
export declare const EMPTY_PINNED_COLUMN_FIELDS: {
|
|
24
|
-
left:
|
|
25
|
-
right:
|
|
24
|
+
left: never[];
|
|
25
|
+
right: never[];
|
|
26
26
|
};
|
|
27
27
|
export interface GridPinnedColumns {
|
|
28
28
|
left: GridStateColDef[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createSelector, createSelectorMemoized, createRootSelector } from "../../../utils/createSelector.js";
|
|
2
2
|
import { EMPTY_PINNED_COLUMN_FIELDS } from "./gridColumnsInterfaces.js";
|
|
3
3
|
import { gridIsRtlSelector } from "../../core/gridCoreSelector.js";
|
|
4
|
+
import { gridListColumnSelector, gridListViewSelector } from "../listView/index.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Get the columns state
|
|
@@ -45,7 +46,7 @@ export const gridInitialColumnVisibilityModelSelector = createSelector(gridColum
|
|
|
45
46
|
* Get the visible columns as a lookup (an object containing the field for keys and the definition for values).
|
|
46
47
|
* @category Visible Columns
|
|
47
48
|
*/
|
|
48
|
-
export const gridVisibleColumnDefinitionsSelector = createSelectorMemoized(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, (columns, columnVisibilityModel) => columns.filter(column => columnVisibilityModel[column.field] !== false));
|
|
49
|
+
export const gridVisibleColumnDefinitionsSelector = createSelectorMemoized(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, gridListViewSelector, gridListColumnSelector, (columns, columnVisibilityModel, listView, listColumn) => listView && listColumn ? [listColumn] : columns.filter(column => columnVisibilityModel[column.field] !== false));
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Get the field of each visible column.
|
|
@@ -70,7 +71,10 @@ export const gridExistingPinnedColumnSelector = createSelectorMemoized(gridPinne
|
|
|
70
71
|
* Get the visible pinned columns.
|
|
71
72
|
* @category Visible Columns
|
|
72
73
|
*/
|
|
73
|
-
export const gridVisiblePinnedColumnDefinitionsSelector = createSelectorMemoized(gridColumnsStateSelector, gridPinnedColumnsSelector, gridVisibleColumnFieldsSelector, gridIsRtlSelector, (columnsState, model, visibleColumnFields, isRtl) => {
|
|
74
|
+
export const gridVisiblePinnedColumnDefinitionsSelector = createSelectorMemoized(gridColumnsStateSelector, gridPinnedColumnsSelector, gridVisibleColumnFieldsSelector, gridIsRtlSelector, gridListViewSelector, (columnsState, model, visibleColumnFields, isRtl, listView) => {
|
|
75
|
+
if (listView) {
|
|
76
|
+
return EMPTY_PINNED_COLUMN_FIELDS;
|
|
77
|
+
}
|
|
74
78
|
const visiblePinnedFields = filterMissingColumns(model, visibleColumnFields, isRtl);
|
|
75
79
|
const visiblePinnedColumns = {
|
|
76
80
|
left: visiblePinnedFields.left.map(field => columnsState.lookup[field]),
|
|
@@ -242,11 +242,13 @@ export const createColumnsState = ({
|
|
|
242
242
|
initialColumnVisibilityModel: updateInitialVisibilityModel ? columnVisibilityModel : currentState.initialColumnVisibilityModel
|
|
243
243
|
};
|
|
244
244
|
}
|
|
245
|
-
|
|
245
|
+
const columnsToKeep = {};
|
|
246
246
|
if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
for (const key in columnsState.lookup) {
|
|
248
|
+
if (Object.prototype.hasOwnProperty.call(columnsState.lookup, key)) {
|
|
249
|
+
columnsToKeep[key] = false;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
250
252
|
}
|
|
251
253
|
const columnsToUpsertLookup = {};
|
|
252
254
|
columnsToUpsert.forEach(newColumn => {
|
|
@@ -14,6 +14,9 @@ import { GridPreferencePanelsValue } from "../preferencesPanel/index.js";
|
|
|
14
14
|
import { gridPivotActiveSelector } from "../pivoting/index.js";
|
|
15
15
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
16
|
export const columnsStateInitializer = (state, props, apiRef) => {
|
|
17
|
+
apiRef.current.caches.columns = {
|
|
18
|
+
lastColumnsProp: props.columns
|
|
19
|
+
};
|
|
17
20
|
const columnsState = createColumnsState({
|
|
18
21
|
apiRef,
|
|
19
22
|
columnsToUpsert: props.columns,
|
|
@@ -36,7 +39,6 @@ export const columnsStateInitializer = (state, props, apiRef) => {
|
|
|
36
39
|
*/
|
|
37
40
|
export function useGridColumns(apiRef, props) {
|
|
38
41
|
const logger = useGridLogger(apiRef, 'useGridColumns');
|
|
39
|
-
const previousColumnsProp = React.useRef(props.columns);
|
|
40
42
|
apiRef.current.registerControlState({
|
|
41
43
|
stateId: 'visibleColumns',
|
|
42
44
|
propModel: props.columnVisibilityModel,
|
|
@@ -299,27 +301,23 @@ export function useGridColumns(apiRef, props) {
|
|
|
299
301
|
*/
|
|
300
302
|
// The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridColumns`
|
|
301
303
|
// As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
|
|
302
|
-
const isFirstRender = React.useRef(true);
|
|
303
304
|
React.useEffect(() => {
|
|
304
|
-
if (
|
|
305
|
-
isFirstRender.current = false;
|
|
305
|
+
if (apiRef.current.caches.columns.lastColumnsProp === props.columns) {
|
|
306
306
|
return;
|
|
307
307
|
}
|
|
308
|
+
apiRef.current.caches.columns.lastColumnsProp = props.columns;
|
|
308
309
|
logger.info(`GridColumns have changed, new length ${props.columns.length}`);
|
|
309
|
-
if (previousColumnsProp.current === props.columns) {
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
310
|
const columnsState = createColumnsState({
|
|
313
311
|
apiRef,
|
|
314
312
|
initialState: undefined,
|
|
315
313
|
// If the user provides a model, we don't want to set it in the state here because it has it's dedicated `useEffect` which calls `setColumnVisibilityModel`
|
|
316
314
|
columnsToUpsert: props.columns,
|
|
317
315
|
keepOnlyColumnsToUpsert: true,
|
|
318
|
-
updateInitialVisibilityModel: true
|
|
316
|
+
updateInitialVisibilityModel: true,
|
|
317
|
+
columnVisibilityModel: props.columnVisibilityModel
|
|
319
318
|
});
|
|
320
|
-
previousColumnsProp.current = props.columns;
|
|
321
319
|
setGridColumnsState(columnsState);
|
|
322
|
-
}, [logger, apiRef, setGridColumnsState, props.columns]);
|
|
320
|
+
}, [logger, apiRef, setGridColumnsState, props.columns, props.columnVisibilityModel]);
|
|
323
321
|
React.useEffect(() => {
|
|
324
322
|
if (props.columnVisibilityModel !== undefined) {
|
|
325
323
|
apiRef.current.setColumnVisibilityModel(props.columnVisibilityModel);
|
|
@@ -17,7 +17,7 @@ export const getColumnsToExport = ({
|
|
|
17
17
|
}, []);
|
|
18
18
|
}
|
|
19
19
|
const validColumns = options.allColumns ? columns : gridVisibleColumnDefinitionsSelector(apiRef);
|
|
20
|
-
return validColumns.filter(column =>
|
|
20
|
+
return validColumns.filter(column => column.disableExport !== true);
|
|
21
21
|
};
|
|
22
22
|
export const defaultGetRowsToExport = ({
|
|
23
23
|
apiRef
|
|
@@ -342,9 +342,9 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
342
342
|
useGridEvent(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
|
|
343
343
|
useGridEvent(apiRef, 'columnVisibilityModelChange', () => {
|
|
344
344
|
const filterModel = gridFilterModelSelector(apiRef);
|
|
345
|
-
if (filterModel.quickFilterValues && shouldQuickFilterExcludeHiddenColumns(filterModel)) {
|
|
345
|
+
if (filterModel.quickFilterValues?.length && shouldQuickFilterExcludeHiddenColumns(filterModel)) {
|
|
346
346
|
// re-apply filters because the quick filter results may have changed
|
|
347
|
-
|
|
347
|
+
updateFilteredRows();
|
|
348
348
|
}
|
|
349
349
|
});
|
|
350
350
|
|
|
@@ -352,7 +352,7 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
352
352
|
* 1ST RENDER
|
|
353
353
|
*/
|
|
354
354
|
useFirstRender(() => {
|
|
355
|
-
|
|
355
|
+
updateFilteredRows();
|
|
356
356
|
});
|
|
357
357
|
|
|
358
358
|
/**
|
|
@@ -10,4 +10,4 @@ import { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
|
|
|
10
10
|
* @requires useGridScroll (method) - can be after
|
|
11
11
|
* @requires useGridColumnSpanning (method) - can be after
|
|
12
12
|
*/
|
|
13
|
-
export declare const useGridKeyboardNavigation: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, "pagination" | "paginationMode" | "getRowId" | "signature" | "headerFilters"
|
|
13
|
+
export declare const useGridKeyboardNavigation: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, "pagination" | "paginationMode" | "getRowId" | "signature" | "headerFilters">) => void;
|
|
@@ -16,7 +16,6 @@ import { gridHeaderFilteringEditFieldSelector, gridHeaderFilteringMenuSelector }
|
|
|
16
16
|
import { useGridRegisterPipeProcessor } from "../../core/pipeProcessing/index.js";
|
|
17
17
|
import { isEventTargetInPortal } from "../../../utils/domUtils.js";
|
|
18
18
|
import { getLeftColumnIndex, getRightColumnIndex, findNonRowSpannedCell } from "./utils.js";
|
|
19
|
-
import { gridListColumnSelector } from "../listView/gridListViewSelectors.js";
|
|
20
19
|
import { createSelectorMemoized } from "../../../utils/createSelector.js";
|
|
21
20
|
import { gridVisibleRowsSelector } from "../pagination/index.js";
|
|
22
21
|
import { gridPinnedRowsSelector } from "../rows/gridRowsSelector.js";
|
|
@@ -36,7 +35,6 @@ const gridVisibleRowsWithPinnedRowsSelector = createSelectorMemoized(gridVisible
|
|
|
36
35
|
export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
37
36
|
const logger = useGridLogger(apiRef, 'useGridKeyboardNavigation');
|
|
38
37
|
const isRtl = useRtl();
|
|
39
|
-
const listView = props.listView;
|
|
40
38
|
const getCurrentPageRows = React.useCallback(() => {
|
|
41
39
|
return gridVisibleRowsWithPinnedRowsSelector(apiRef);
|
|
42
40
|
}, [apiRef]);
|
|
@@ -59,7 +57,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
59
57
|
colIndex = nextCellColSpanInfo.rightVisibleCellIndex;
|
|
60
58
|
}
|
|
61
59
|
}
|
|
62
|
-
const field =
|
|
60
|
+
const field = gridVisibleColumnFieldsSelector(apiRef)[colIndex];
|
|
63
61
|
const nonRowSpannedRowId = findNonRowSpannedCell(apiRef, rowId, field, rowSpanScanDirection);
|
|
64
62
|
// `scrollToIndexes` requires a rowIndex relative to all visible rows.
|
|
65
63
|
// Those rows do not include pinned rows, but pinned rows do not need scroll anyway.
|
|
@@ -70,7 +68,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
70
68
|
rowIndex: rowIndexRelativeToAllRows
|
|
71
69
|
});
|
|
72
70
|
apiRef.current.setCellFocus(nonRowSpannedRowId, field);
|
|
73
|
-
}, [apiRef, logger
|
|
71
|
+
}, [apiRef, logger]);
|
|
74
72
|
const goToHeader = React.useCallback((colIndex, event) => {
|
|
75
73
|
logger.debug(`Navigating to header col ${colIndex}`);
|
|
76
74
|
apiRef.current.scrollToIndexes({
|
|
@@ -395,14 +393,12 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
395
393
|
return;
|
|
396
394
|
}
|
|
397
395
|
const viewportPageSize = apiRef.current.getViewportPageSize();
|
|
398
|
-
const
|
|
399
|
-
const colIndexBefore = params.field ? getColumnIndexFn(params.field) : 0;
|
|
396
|
+
const colIndexBefore = params.field ? apiRef.current.getColumnIndex(params.field) : 0;
|
|
400
397
|
const rowIndexBefore = currentPageRows.findIndex(row => row.id === params.id);
|
|
401
398
|
const firstRowIndexInPage = 0;
|
|
402
399
|
const lastRowIndexInPage = currentPageRows.length - 1;
|
|
403
400
|
const firstColIndex = 0;
|
|
404
|
-
const
|
|
405
|
-
const lastColIndex = visibleColumns.length - 1;
|
|
401
|
+
const lastColIndex = gridVisibleColumnDefinitionsSelector(apiRef).length - 1;
|
|
406
402
|
let shouldPreventDefault = true;
|
|
407
403
|
switch (event.key) {
|
|
408
404
|
case 'ArrowDown':
|
|
@@ -519,7 +515,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
519
515
|
if (shouldPreventDefault) {
|
|
520
516
|
event.preventDefault();
|
|
521
517
|
}
|
|
522
|
-
}, [apiRef, getCurrentPageRows, isRtl, goToCell, getRowIdFromIndex, headerFilteringEnabled, goToHeaderFilter, goToHeader
|
|
518
|
+
}, [apiRef, getCurrentPageRows, isRtl, goToCell, getRowIdFromIndex, headerFilteringEnabled, goToHeaderFilter, goToHeader]);
|
|
523
519
|
const checkIfCanStartEditing = React.useCallback((initialValue, {
|
|
524
520
|
event
|
|
525
521
|
}) => {
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { GridStateCommunity } from "../../../models/gridStateCommunity.js";
|
|
2
|
+
import type { GridStateColDef } from "../../../models/colDef/gridColDef.js";
|
|
3
|
+
/**
|
|
4
|
+
* Get the list view state
|
|
5
|
+
* @category List View
|
|
6
|
+
* @ignore - Do not document
|
|
7
|
+
*/
|
|
8
|
+
export declare const gridListViewSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, unknown, boolean>;
|
|
2
9
|
/**
|
|
3
10
|
* Get the list column definition
|
|
4
11
|
* @category List View
|
|
5
12
|
* @ignore - Do not document
|
|
6
13
|
*/
|
|
7
|
-
export declare const gridListColumnSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, unknown,
|
|
14
|
+
export declare const gridListColumnSelector: import("@mui/x-data-grid").OutputSelector<GridStateCommunity, unknown, GridStateColDef>;
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { createRootSelector } from "../../../utils/createSelector.js";
|
|
2
|
+
/**
|
|
3
|
+
* Get the list view state
|
|
4
|
+
* @category List View
|
|
5
|
+
* @ignore - Do not document
|
|
6
|
+
*/
|
|
7
|
+
export const gridListViewSelector = createRootSelector(state => state.props.listView ?? false);
|
|
8
|
+
|
|
2
9
|
/**
|
|
3
10
|
* Get the list column definition
|
|
4
11
|
* @category List View
|
|
@@ -299,12 +299,13 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
299
299
|
}
|
|
300
300
|
const currentSelection = gridRowSelectionStateSelector(apiRef);
|
|
301
301
|
const rowsLookup = gridRowsLookupSelector(apiRef);
|
|
302
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
302
303
|
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
303
304
|
const isNonExistent = id => {
|
|
304
305
|
if (props.filterMode === 'server') {
|
|
305
306
|
return !rowsLookup[id];
|
|
306
307
|
}
|
|
307
|
-
return !
|
|
308
|
+
return !rowTree[id] || filteredRowsLookup[id] === false;
|
|
308
309
|
};
|
|
309
310
|
const newSelectionModel = {
|
|
310
311
|
type: currentSelection.type,
|
|
@@ -430,15 +431,15 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
430
431
|
const filterModel = gridFilterModelSelector(apiRef);
|
|
431
432
|
const quickFilterModel = gridQuickFilterValuesSelector(apiRef);
|
|
432
433
|
const hasFilters = filterModel.items.length > 0 || quickFilterModel?.some(val => val.length);
|
|
433
|
-
if (!props.isRowSelectable && !props.checkboxSelectionVisibleOnly &&
|
|
434
|
+
if (!props.isRowSelectable && !props.checkboxSelectionVisibleOnly && (!isNestedData || props.rowSelectionPropagation?.descendants) && !hasFilters) {
|
|
434
435
|
apiRef.current.setRowSelectionModel({
|
|
435
436
|
type: value ? 'exclude' : 'include',
|
|
436
437
|
ids: new Set()
|
|
437
|
-
});
|
|
438
|
+
}, 'multipleRowsSelection');
|
|
438
439
|
} else {
|
|
439
440
|
apiRef.current.selectRows(getRowsToBeSelected(), value);
|
|
440
441
|
}
|
|
441
|
-
}, [apiRef,
|
|
442
|
+
}, [apiRef, getRowsToBeSelected, props.checkboxSelectionVisibleOnly, props.isRowSelectable, props.rowSelectionPropagation?.descendants, isNestedData]);
|
|
442
443
|
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
|
|
443
444
|
toggleAllRows(params.value);
|
|
444
445
|
}, [toggleAllRows]);
|
|
@@ -42,7 +42,7 @@ export declare const getRowsStateFromCache: ({
|
|
|
42
42
|
}) => GridRowsState;
|
|
43
43
|
export declare const isAutogeneratedRow: (row: GridRowModel) => boolean;
|
|
44
44
|
export declare const isAutogeneratedRowNode: (rowNode: GridTreeNode) => rowNode is GridFooterNode | GridSkeletonRowNode | GridAutoGeneratedGroupNode | GridAutoGeneratedPinnedRowNode;
|
|
45
|
-
export declare const getTreeNodeDescendants: (tree: GridRowTreeConfig, parentId: GridRowId, skipAutoGeneratedRows: boolean) => GridRowId[];
|
|
45
|
+
export declare const getTreeNodeDescendants: (tree: GridRowTreeConfig, parentId: GridRowId, skipAutoGeneratedRows: boolean, directChildrenOnly?: boolean) => GridRowId[];
|
|
46
46
|
export declare const updateCacheWithNewRows: ({
|
|
47
47
|
previousCache,
|
|
48
48
|
getRowId,
|
|
@@ -127,7 +127,7 @@ export const getRowsStateFromCache = ({
|
|
|
127
127
|
};
|
|
128
128
|
export const isAutogeneratedRow = row => GRID_ID_AUTOGENERATED in row;
|
|
129
129
|
export const isAutogeneratedRowNode = rowNode => rowNode.type === 'skeletonRow' || rowNode.type === 'footer' || rowNode.type === 'group' && rowNode.isAutoGenerated || rowNode.type === 'pinnedRow' && rowNode.isAutoGenerated;
|
|
130
|
-
export const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows) => {
|
|
130
|
+
export const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows, directChildrenOnly) => {
|
|
131
131
|
const node = tree[parentId];
|
|
132
132
|
if (node.type !== 'group') {
|
|
133
133
|
return [];
|
|
@@ -138,7 +138,10 @@ export const getTreeNodeDescendants = (tree, parentId, skipAutoGeneratedRows) =>
|
|
|
138
138
|
if (!skipAutoGeneratedRows || !isAutogeneratedRowNode(tree[child])) {
|
|
139
139
|
validDescendants.push(child);
|
|
140
140
|
}
|
|
141
|
-
|
|
141
|
+
if (directChildrenOnly) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const childDescendants = getTreeNodeDescendants(tree, child, skipAutoGeneratedRows, directChildrenOnly);
|
|
142
145
|
for (let j = 0; j < childDescendants.length; j += 1) {
|
|
143
146
|
validDescendants.push(childDescendants[j]);
|
|
144
147
|
}
|
|
@@ -198,7 +198,8 @@ export const useGridRows = (apiRef, props) => {
|
|
|
198
198
|
skipAutoGeneratedRows = true,
|
|
199
199
|
groupId,
|
|
200
200
|
applySorting,
|
|
201
|
-
applyFiltering
|
|
201
|
+
applyFiltering,
|
|
202
|
+
directChildrenOnly = false
|
|
202
203
|
}) => {
|
|
203
204
|
const tree = gridRowTreeSelector(apiRef);
|
|
204
205
|
let children;
|
|
@@ -210,14 +211,14 @@ export const useGridRows = (apiRef, props) => {
|
|
|
210
211
|
const sortedRowIds = gridSortedRowIdsSelector(apiRef);
|
|
211
212
|
children = [];
|
|
212
213
|
const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1;
|
|
213
|
-
for (let index = startIndex; index < sortedRowIds.length && tree[sortedRowIds[index]].depth > groupNode.depth; index += 1) {
|
|
214
|
+
for (let index = startIndex; index < sortedRowIds.length && (directChildrenOnly ? tree[sortedRowIds[index]].depth === groupNode.depth + 1 : tree[sortedRowIds[index]].depth > groupNode.depth); index += 1) {
|
|
214
215
|
const id = sortedRowIds[index];
|
|
215
216
|
if (!skipAutoGeneratedRows || !isAutogeneratedRowNode(tree[id])) {
|
|
216
217
|
children.push(id);
|
|
217
218
|
}
|
|
218
219
|
}
|
|
219
220
|
} else {
|
|
220
|
-
children = getTreeNodeDescendants(tree, groupId, skipAutoGeneratedRows);
|
|
221
|
+
children = getTreeNodeDescendants(tree, groupId, skipAutoGeneratedRows, directChildrenOnly);
|
|
221
222
|
}
|
|
222
223
|
if (applyFiltering) {
|
|
223
224
|
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
@@ -9,4 +9,4 @@ import { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
|
|
|
9
9
|
* @requires useGridFilter (state)
|
|
10
10
|
* @requires useGridColumnSpanning (method)
|
|
11
11
|
*/
|
|
12
|
-
export declare const useGridScroll: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, "pagination"
|
|
12
|
+
export declare const useGridScroll: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, "pagination">) => void;
|
|
@@ -9,7 +9,6 @@ import { gridRowsMetaSelector } from "../rows/gridRowsMetaSelector.js";
|
|
|
9
9
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
|
|
10
10
|
import { gridExpandedSortedRowEntriesSelector } from "../filter/gridFilterSelector.js";
|
|
11
11
|
import { gridDimensionsSelector } from "../dimensions/index.js";
|
|
12
|
-
import { gridListColumnSelector } from "../listView/gridListViewSelectors.js";
|
|
13
12
|
|
|
14
13
|
// Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js
|
|
15
14
|
// Similar to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
|
|
@@ -52,7 +51,7 @@ export const useGridScroll = (apiRef, props) => {
|
|
|
52
51
|
const scrollToIndexes = React.useCallback(params => {
|
|
53
52
|
const dimensions = gridDimensionsSelector(apiRef);
|
|
54
53
|
const totalRowCount = gridRowCountSelector(apiRef);
|
|
55
|
-
const visibleColumns =
|
|
54
|
+
const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
|
|
56
55
|
const scrollToHeader = params.rowIndex == null;
|
|
57
56
|
if (!scrollToHeader && totalRowCount === 0 || visibleColumns.length === 0) {
|
|
58
57
|
return false;
|
|
@@ -99,7 +98,7 @@ export const useGridScroll = (apiRef, props) => {
|
|
|
99
98
|
return true;
|
|
100
99
|
}
|
|
101
100
|
return false;
|
|
102
|
-
}, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows
|
|
101
|
+
}, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows]);
|
|
103
102
|
const scroll = React.useCallback(params => {
|
|
104
103
|
if (virtualScrollerRef.current && params.left !== undefined && colRef.current) {
|
|
105
104
|
const direction = isRtl ? -1 : 1;
|