@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.
Files changed (84) hide show
  1. package/CHANGELOG.md +131 -24
  2. package/DataGrid/index.d.ts +0 -1
  3. package/DataGrid/useDataGridComponent.js +8 -0
  4. package/components/GridScrollArea.js +1 -1
  5. package/components/containers/GridRootStyles.js +39 -0
  6. package/constants/gridClasses.d.ts +12 -0
  7. package/constants/gridClasses.js +3 -1
  8. package/esm/DataGrid/index.d.ts +0 -1
  9. package/esm/DataGrid/useDataGridComponent.js +8 -0
  10. package/esm/components/GridScrollArea.js +1 -1
  11. package/esm/components/containers/GridRootStyles.js +39 -0
  12. package/esm/constants/gridClasses.d.ts +12 -0
  13. package/esm/constants/gridClasses.js +3 -1
  14. package/esm/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
  15. package/esm/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
  16. package/esm/hooks/core/useGridProps.d.ts +2 -2
  17. package/esm/hooks/core/useGridProps.js +3 -1
  18. package/esm/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
  19. package/esm/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
  20. package/esm/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
  21. package/esm/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
  22. package/esm/hooks/features/columns/gridColumnsSelector.js +6 -2
  23. package/esm/hooks/features/columns/gridColumnsUtils.js +6 -4
  24. package/esm/hooks/features/columns/useGridColumns.js +8 -10
  25. package/esm/hooks/features/export/utils.js +1 -1
  26. package/esm/hooks/features/filter/useGridFilter.js +3 -3
  27. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  28. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +5 -9
  29. package/esm/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
  30. package/esm/hooks/features/listView/gridListViewSelectors.js +7 -0
  31. package/esm/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  32. package/esm/hooks/features/rows/gridRowsUtils.d.ts +1 -1
  33. package/esm/hooks/features/rows/gridRowsUtils.js +5 -2
  34. package/esm/hooks/features/rows/useGridRows.js +4 -3
  35. package/esm/hooks/features/scroll/useGridScroll.d.ts +1 -1
  36. package/esm/hooks/features/scroll/useGridScroll.js +2 -3
  37. package/esm/hooks/features/virtualization/useGridVirtualScroller.js +3 -6
  38. package/esm/hooks/utils/index.d.ts +1 -0
  39. package/esm/hooks/utils/index.js +2 -1
  40. package/esm/hooks/utils/useGridInitializeState.d.ts +1 -1
  41. package/esm/hooks/utils/useGridInitializeState.js +6 -1
  42. package/esm/hooks/utils/useRunOncePerLoop.d.ts +1 -0
  43. package/esm/hooks/utils/useRunOncePerLoop.js +26 -0
  44. package/esm/index.js +1 -1
  45. package/esm/models/api/gridRowApi.d.ts +5 -0
  46. package/esm/models/events/gridEventLookup.d.ts +2 -1
  47. package/esm/models/gridApiCaches.d.ts +8 -2
  48. package/esm/models/gridStateCommunity.d.ts +2 -2
  49. package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
  50. package/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
  51. package/hooks/core/useGridProps.d.ts +2 -2
  52. package/hooks/core/useGridProps.js +3 -1
  53. package/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
  54. package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
  55. package/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
  56. package/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
  57. package/hooks/features/columns/gridColumnsSelector.js +6 -2
  58. package/hooks/features/columns/gridColumnsUtils.js +6 -4
  59. package/hooks/features/columns/useGridColumns.js +8 -10
  60. package/hooks/features/export/utils.js +1 -1
  61. package/hooks/features/filter/useGridFilter.js +3 -3
  62. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  63. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +5 -9
  64. package/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
  65. package/hooks/features/listView/gridListViewSelectors.js +8 -1
  66. package/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  67. package/hooks/features/rows/gridRowsUtils.d.ts +1 -1
  68. package/hooks/features/rows/gridRowsUtils.js +5 -2
  69. package/hooks/features/rows/useGridRows.js +4 -3
  70. package/hooks/features/scroll/useGridScroll.d.ts +1 -1
  71. package/hooks/features/scroll/useGridScroll.js +2 -3
  72. package/hooks/features/virtualization/useGridVirtualScroller.js +3 -6
  73. package/hooks/utils/index.d.ts +1 -0
  74. package/hooks/utils/index.js +12 -0
  75. package/hooks/utils/useGridInitializeState.d.ts +1 -1
  76. package/hooks/utils/useGridInitializeState.js +6 -1
  77. package/hooks/utils/useRunOncePerLoop.d.ts +1 -0
  78. package/hooks/utils/useRunOncePerLoop.js +33 -0
  79. package/index.js +1 -1
  80. package/models/api/gridRowApi.d.ts +5 -0
  81. package/models/events/gridEventLookup.d.ts +2 -1
  82. package/models/gridApiCaches.d.ts +8 -2
  83. package/models/gridStateCommunity.d.ts +2 -2
  84. package/package.json +1 -1
@@ -25,9 +25,7 @@ import { getFirstNonSpannedColumnToRender } from "../columns/gridColumnsUtils.js
25
25
  import { gridRenderContextSelector, gridVirtualizationRowEnabledSelector, gridVirtualizationColumnEnabledSelector } from "./gridVirtualizationSelectors.js";
26
26
  import { EMPTY_RENDER_CONTEXT } from "./useGridVirtualization.js";
27
27
  import { gridRowSpanningHiddenCellsOriginMapSelector } from "../rows/gridRowSpanningSelectors.js";
28
- import { gridListColumnSelector } from "../listView/gridListViewSelectors.js";
29
28
  import { minimalContentHeight } from "../rows/gridRowsUtils.js";
30
- import { EMPTY_PINNED_COLUMN_FIELDS } from "../columns/index.js";
31
29
  import { gridFocusedVirtualCellSelector } from "./gridFocusedVirtualCellSelector.js";
32
30
  import { roundToDecimalPlaces } from "../../../utils/roundToDecimalPlaces.js";
33
31
  import { isJSDOM } from "../../../utils/isJSDOM.js";
@@ -57,12 +55,11 @@ export const useGridVirtualScroller = () => {
57
55
  const {
58
56
  listView
59
57
  } = rootProps;
60
- const visibleColumns = useGridSelector(apiRef, () => listView ? [gridListColumnSelector(apiRef)] : gridVisibleColumnDefinitionsSelector(apiRef));
58
+ const visibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
61
59
  const enabledForRows = useGridSelector(apiRef, gridVirtualizationRowEnabledSelector) && !isJSDOM;
62
60
  const enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector) && !isJSDOM;
63
61
  const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector);
64
- const pinnedColumnDefinitions = gridVisiblePinnedColumnDefinitionsSelector(apiRef);
65
- const pinnedColumns = listView ? EMPTY_PINNED_COLUMN_FIELDS : pinnedColumnDefinitions;
62
+ const pinnedColumns = gridVisiblePinnedColumnDefinitionsSelector(apiRef);
66
63
  const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
67
64
  const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
68
65
  const isRtl = useRtl();
@@ -552,7 +549,7 @@ function needsHorizontalScrollbarSelector(apiRef) {
552
549
  function inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns) {
553
550
  const dimensions = gridDimensionsSelector(apiRef);
554
551
  const currentPage = getVisibleRows(apiRef, rootProps);
555
- const visibleColumns = rootProps.listView ? [gridListColumnSelector(apiRef)] : gridVisibleColumnDefinitionsSelector(apiRef);
552
+ const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
556
553
  const hiddenCellsOriginMap = gridRowSpanningHiddenCellsOriginMapSelector(apiRef);
557
554
  const lastRowId = apiRef.current.state.rows.dataRowIds.at(-1);
558
555
  const lastColumn = visibleColumns.at(-1);
@@ -6,4 +6,5 @@ export * from "./useGridNativeEventListener.js";
6
6
  export * from "./useFirstRender.js";
7
7
  export * from "./useOnMount.js";
8
8
  export * from "./useRunOnce.js";
9
+ export * from "./useRunOncePerLoop.js";
9
10
  export type { RenderProp } from '@mui/x-internals/useComponentRenderer';
@@ -5,4 +5,5 @@ export { useGridSelector } from "./useGridSelector.js";
5
5
  export * from "./useGridNativeEventListener.js";
6
6
  export * from "./useFirstRender.js";
7
7
  export * from "./useOnMount.js";
8
- export * from "./useRunOnce.js";
8
+ export * from "./useRunOnce.js";
9
+ export * from "./useRunOncePerLoop.js";
@@ -4,5 +4,5 @@ import { GridPrivateApiCommunity } from "../../models/api/gridApiCommunity.js";
4
4
  import { DataGridProcessedProps } from "../../models/props/DataGridProps.js";
5
5
  type DeepPartial<T> = { [P in keyof T]?: DeepPartial<T[P]> };
6
6
  export type GridStateInitializer<P extends Partial<DataGridProcessedProps> = DataGridProcessedProps, PrivateApi extends GridPrivateApiCommon = GridPrivateApiCommunity> = (state: DeepPartial<PrivateApi['state']>, props: P, privateApiRef: RefObject<PrivateApi>) => DeepPartial<PrivateApi['state']>;
7
- export declare const useGridInitializeState: <P extends Partial<DataGridProcessedProps>, PrivateApi extends GridPrivateApiCommon = GridPrivateApiCommunity>(initializer: GridStateInitializer<P, PrivateApi>, privateApiRef: RefObject<PrivateApi>, props: P) => void;
7
+ export declare const useGridInitializeState: <P extends Partial<DataGridProcessedProps>, PrivateApi extends GridPrivateApiCommon = GridPrivateApiCommunity>(initializer: GridStateInitializer<P, PrivateApi>, privateApiRef: RefObject<PrivateApi>, props: P, key?: string) => void;
8
8
  export {};
@@ -1,6 +1,11 @@
1
1
  import * as React from 'react';
2
- export const useGridInitializeState = (initializer, privateApiRef, props) => {
2
+ export const useGridInitializeState = (initializer, privateApiRef, props, key) => {
3
+ const previousKey = React.useRef(key);
3
4
  const isInitialized = React.useRef(false);
5
+ if (key !== previousKey.current) {
6
+ isInitialized.current = false;
7
+ previousKey.current = key;
8
+ }
4
9
  if (!isInitialized.current) {
5
10
  privateApiRef.current.state = initializer(privateApiRef.current.state, props, privateApiRef);
6
11
  isInitialized.current = true;
@@ -0,0 +1 @@
1
+ export declare function useRunOncePerLoop<T extends (...args: any[]) => void>(callback: T, nextFrame?: boolean): (...args: Parameters<T>) => void;
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ export function useRunOncePerLoop(callback, nextFrame = false) {
3
+ const scheduledRef = React.useRef(false);
4
+ const schedule = React.useCallback((...args) => {
5
+ if (scheduledRef.current) {
6
+ return;
7
+ }
8
+ scheduledRef.current = true;
9
+ const runner = () => {
10
+ scheduledRef.current = false;
11
+ callback(...args);
12
+ };
13
+ if (nextFrame) {
14
+ if (typeof requestAnimationFrame === 'function') {
15
+ requestAnimationFrame(runner);
16
+ }
17
+ return;
18
+ }
19
+ if (typeof queueMicrotask === 'function') {
20
+ queueMicrotask(runner);
21
+ } else {
22
+ Promise.resolve().then(runner);
23
+ }
24
+ }, [callback, nextFrame]);
25
+ return schedule;
26
+ }
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v8.8.0
2
+ * @mui/x-data-grid v8.9.1
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -19,6 +19,11 @@ export interface GridRowGroupChildrenGetterParams {
19
19
  * @default false
20
20
  */
21
21
  applySorting?: boolean;
22
+ /**
23
+ * If `true`, the method will only return the direct leaf children of the group
24
+ * @default false
25
+ */
26
+ directChildrenOnly?: boolean;
22
27
  }
23
28
  /**
24
29
  * The Row API interface that is available in the grid `apiRef`.
@@ -77,11 +77,12 @@ export interface GridRowEventLookup {
77
77
  };
78
78
  /**
79
79
  * Fired when the dragging of a row ends.
80
+ * It's mapped to the `dragend` DOM event.
80
81
  * @ignore - do not document.
81
82
  */
82
83
  rowDragEnd: {
83
84
  params: GridRowParams;
84
- event: React.DragEvent<HTMLElement>;
85
+ event: DragEvent;
85
86
  };
86
87
  }
87
88
  export interface GridColumnHeaderEventLookup {
@@ -1,6 +1,12 @@
1
- import { GridRowsInternalCache } from "../hooks/features/rows/gridRowsInterfaces.js";
2
- import { GridRowsMetaInternalCache } from "../hooks/features/rows/gridRowsMetaInterfaces.js";
1
+ import type { GridRowsInternalCache } from "../hooks/features/rows/gridRowsInterfaces.js";
2
+ import type { GridRowsMetaInternalCache } from "../hooks/features/rows/gridRowsMetaInterfaces.js";
3
+ import type { GridColumnGroupingInternalCache } from "../hooks/features/columnGrouping/gridColumnGroupsInterfaces.js";
4
+ import type { GridColDef } from "./colDef/index.js";
3
5
  export interface GridApiCaches {
6
+ columns: {
7
+ lastColumnsProp: readonly GridColDef[];
8
+ };
9
+ columnGrouping: GridColumnGroupingInternalCache;
4
10
  rows: GridRowsInternalCache;
5
11
  rowsMeta: GridRowsMetaInternalCache;
6
12
  }
@@ -1,5 +1,5 @@
1
1
  import type { GridColumnMenuState, GridColumnsInitialState, GridColumnsState, GridColumnsGroupingState, GridColumnPinningState, GridDensityState, GridDimensionsState, GridFilterInitialState, GridFilterState, GridFocusState, GridPaginationInitialState, GridPaginationState, GridPreferencePanelInitialState, GridPreferencePanelState, GridRowsState, GridSortingInitialState, GridSortingState, GridTabIndexState, GridVirtualizationState } from "../hooks/index.js";
2
- import type { DataGridProps } from "./props/DataGridProps.js";
2
+ import type { DataGridProcessedProps } from "./props/DataGridProps.js";
3
3
  import type { GridRowsMetaState } from "../hooks/features/rows/gridRowsMetaState.js";
4
4
  import type { GridEditingState } from "./gridEditRowModel.js";
5
5
  import { GridHeaderFilteringState } from "./gridHeaderFilteringModel.js";
@@ -12,7 +12,7 @@ import type { GridListViewState } from "../hooks/features/listView/useGridListVi
12
12
  * Some props are passed on the state to enable grid selectors to select
13
13
  * and react to them.
14
14
  */
15
- type GridStateProps = Pick<DataGridProps, 'getRowId'>;
15
+ type GridStateProps = Pick<DataGridProcessedProps, 'getRowId' | 'listView'>;
16
16
  /**
17
17
  * The state of Data Grid.
18
18
  */
@@ -138,5 +138,10 @@ export interface GridPipeProcessingPrivateApi {
138
138
  * @param {GridPipeProcessorGroup} group The group to apply.
139
139
  */
140
140
  requestPipeProcessorsApplication: (group: GridPipeProcessorGroup) => void;
141
+ /**
142
+ * Checks of there are any processors that have been updated and runs appliers for them.
143
+ * It is intended to be called in a useEffect in the top-level data grid hook (`useDataGridComponent`).
144
+ */
145
+ runAppliersForPendingProcessors: () => void;
141
146
  }
142
147
  export {};
@@ -57,7 +57,8 @@ const useGridPipeProcessing = apiRef => {
57
57
  cache.current[group] = {
58
58
  processors: new Map(),
59
59
  processorsAsArray: [],
60
- appliers: {}
60
+ appliers: {},
61
+ processorsUpdated: false
61
62
  };
62
63
  }
63
64
  const groupCache = cache.current[group];
@@ -65,19 +66,20 @@ const useGridPipeProcessing = apiRef => {
65
66
  if (oldProcessor !== processor) {
66
67
  groupCache.processors.set(id, processor);
67
68
  groupCache.processorsAsArray = Array.from(cache.current[group].processors.values()).filter(processorValue => processorValue !== null);
68
- runAppliers(groupCache);
69
+ groupCache.processorsUpdated = true;
69
70
  }
70
71
  return () => {
71
72
  cache.current[group].processors.set(id, null);
72
73
  cache.current[group].processorsAsArray = Array.from(cache.current[group].processors.values()).filter(processorValue => processorValue !== null);
73
74
  };
74
- }, [runAppliers]);
75
+ }, []);
75
76
  const registerPipeApplier = React.useCallback((group, id, applier) => {
76
77
  if (!cache.current[group]) {
77
78
  cache.current[group] = {
78
79
  processors: new Map(),
79
80
  processorsAsArray: [],
80
- appliers: {}
81
+ appliers: {},
82
+ processorsUpdated: false
81
83
  };
82
84
  }
83
85
  cache.current[group].appliers[id] = applier;
@@ -90,6 +92,18 @@ const useGridPipeProcessing = apiRef => {
90
92
  const requestPipeProcessorsApplication = React.useCallback(group => {
91
93
  runAppliers(cache.current[group]);
92
94
  }, [runAppliers]);
95
+ const runAppliersForPendingProcessors = React.useCallback(() => {
96
+ for (const group in cache.current) {
97
+ if (!Object.prototype.hasOwnProperty.call(cache.current, group)) {
98
+ continue;
99
+ }
100
+ const groupCache = cache.current[group];
101
+ if (groupCache.processorsUpdated) {
102
+ groupCache.processorsUpdated = false;
103
+ runAppliers(groupCache);
104
+ }
105
+ }
106
+ }, [runAppliers]);
93
107
  const applyPipeProcessors = React.useCallback((...args) => {
94
108
  const [group, value, context] = args;
95
109
  if (!cache.current[group]) {
@@ -105,7 +119,8 @@ const useGridPipeProcessing = apiRef => {
105
119
  const preProcessingPrivateApi = {
106
120
  registerPipeProcessor,
107
121
  registerPipeApplier,
108
- requestPipeProcessorsApplication
122
+ requestPipeProcessorsApplication,
123
+ runAppliersForPendingProcessors
109
124
  };
110
125
  const preProcessingPublicApi = {
111
126
  unstable_applyPipeProcessors: applyPipeProcessors
@@ -1,8 +1,8 @@
1
1
  import type { RefObject } from '@mui/x-internals/types';
2
- import type { DataGridProps } from "../../models/props/DataGridProps.js";
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<DataGridProps, 'getRowId'>;
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 {};
@@ -12,6 +12,7 @@ var React = _interopRequireWildcard(require("react"));
12
12
  const propsStateInitializer = (state, props) => {
13
13
  return (0, _extends2.default)({}, state, {
14
14
  props: {
15
+ listView: props.listView,
15
16
  getRowId: props.getRowId
16
17
  }
17
18
  });
@@ -21,9 +22,10 @@ const useGridProps = (apiRef, props) => {
21
22
  React.useEffect(() => {
22
23
  apiRef.current.setState(state => (0, _extends2.default)({}, state, {
23
24
  props: {
25
+ listView: props.listView,
24
26
  getRowId: props.getRowId
25
27
  }
26
28
  }));
27
- }, [apiRef, props.getRowId]);
29
+ }, [apiRef, props.listView, props.getRowId]);
28
30
  };
29
31
  exports.useGridProps = useGridProps;
@@ -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
  }
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.unwrapGroupingColumnModel = exports.getColumnGroupsHeaderStructure = void 0;
7
- var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
8
7
  var _gridColumnGrouping = require("../../../models/gridColumnGrouping");
9
8
  // This is the recurrence function that help writing `unwrapGroupingColumnModel()`
10
9
  const recurrentUnwrapGroupingColumnModel = (columnGroupNode, parents, unwrappedGroupingModelToComplete) => {
@@ -44,45 +43,49 @@ exports.unwrapGroupingColumnModel = unwrapGroupingColumnModel;
44
43
  const getColumnGroupsHeaderStructure = (orderedColumns, unwrappedGroupingModel, pinnedFields) => {
45
44
  const getParents = field => unwrappedGroupingModel[field] ?? [];
46
45
  const groupingHeaderStructure = [];
47
- const maxDepth = Math.max(...orderedColumns.map(field => getParents(field).length));
48
- const haveSameParents = (field1, field2, depth) => (0, _isDeepEqual.isDeepEqual)(getParents(field1).slice(0, depth + 1), getParents(field2).slice(0, depth + 1));
49
- const haveDifferentContainers = (field1, field2) => {
50
- if (pinnedFields?.left && pinnedFields.left.includes(field1) && !pinnedFields.left.includes(field2)) {
51
- return true;
52
- }
53
- if (pinnedFields?.right && !pinnedFields.right.includes(field1) && pinnedFields.right.includes(field2)) {
54
- return true;
46
+ const maxDepth = Math.max(0, ...orderedColumns.map(field => getParents(field).length));
47
+ const haveSameParents = (field1, field2, depth) => {
48
+ const a = getParents(field1);
49
+ const b = getParents(field2);
50
+ for (let i = 0; i <= depth; i += 1) {
51
+ if (a[i] !== b[i]) {
52
+ return false;
53
+ }
55
54
  }
56
- return false;
55
+ return true;
56
+ };
57
+ const haveDifferentContainers = (field1, field2) => {
58
+ const left = pinnedFields?.left;
59
+ const right = pinnedFields?.right;
60
+ const inLeft1 = !!left?.includes(field1);
61
+ const inLeft2 = !!left?.includes(field2);
62
+ const inRight1 = !!right?.includes(field1);
63
+ const inRight2 = !!right?.includes(field2);
64
+ return inLeft1 !== inLeft2 || inRight1 !== inRight2;
57
65
  };
58
66
  for (let depth = 0; depth < maxDepth; depth += 1) {
59
- const depthStructure = orderedColumns.reduce((structure, newField) => {
60
- const groupId = getParents(newField)[depth] ?? null;
61
- if (structure.length === 0) {
62
- return [{
63
- columnFields: [newField],
67
+ const depthStructure = [];
68
+ for (let i = 0; i < orderedColumns.length; i += 1) {
69
+ const field = orderedColumns[i];
70
+ const groupId = getParents(field)[depth] ?? null;
71
+ if (depthStructure.length === 0) {
72
+ depthStructure.push({
73
+ columnFields: [field],
64
74
  groupId
65
- }];
75
+ });
76
+ continue;
66
77
  }
67
- const lastGroup = structure[structure.length - 1];
78
+ const lastGroup = depthStructure[depthStructure.length - 1];
68
79
  const prevField = lastGroup.columnFields[lastGroup.columnFields.length - 1];
69
- const prevGroupId = lastGroup.groupId;
70
- if (prevGroupId !== groupId || !haveSameParents(prevField, newField, depth) ||
71
- // Fix for https://github.com/mui/mui-x/issues/7041
72
- haveDifferentContainers(prevField, newField)) {
73
- // It's a new group
74
- return [...structure, {
75
- columnFields: [newField],
80
+ if (lastGroup.groupId !== groupId || !haveSameParents(prevField, field, depth) || haveDifferentContainers(prevField, field)) {
81
+ depthStructure.push({
82
+ columnFields: [field],
76
83
  groupId
77
- }];
84
+ });
85
+ } else {
86
+ lastGroup.columnFields.push(field);
78
87
  }
79
-
80
- // It extends the previous group
81
- return [...structure.slice(0, structure.length - 1), {
82
- columnFields: [...lastGroup.columnFields, newField],
83
- groupId
84
- }];
85
- }, []);
88
+ }
86
89
  groupingHeaderStructure.push(depthStructure);
87
90
  }
88
91
  return groupingHeaderStructure;
@@ -18,10 +18,11 @@ var _useGridEvent = require("../../utils/useGridEvent");
18
18
  var _columns = require("../columns");
19
19
  const _excluded = ["groupId", "children"];
20
20
  const createGroupLookup = columnGroupingModel => {
21
- let groupLookup = {};
22
- columnGroupingModel.forEach(node => {
21
+ const groupLookup = {};
22
+ for (let i = 0; i < columnGroupingModel.length; i += 1) {
23
+ const node = columnGroupingModel[i];
23
24
  if ((0, _gridColumnGrouping.isLeaf)(node)) {
24
- return;
25
+ continue;
25
26
  }
26
27
  const {
27
28
  groupId,
@@ -31,10 +32,8 @@ const createGroupLookup = columnGroupingModel => {
31
32
  if (!groupId) {
32
33
  throw new Error('MUI X: An element of the columnGroupingModel does not have either `field` or `groupId`.');
33
34
  }
34
- if (process.env.NODE_ENV !== 'production') {
35
- if (!children) {
36
- console.warn(`MUI X: group groupId=${groupId} has no children.`);
37
- }
35
+ if (process.env.NODE_ENV !== 'production' && !children) {
36
+ console.warn(`MUI X: group groupId=${groupId} has no children.`);
38
37
  }
39
38
  const groupParam = (0, _extends2.default)({}, other, {
40
39
  groupId
@@ -43,13 +42,15 @@ const createGroupLookup = columnGroupingModel => {
43
42
  if (subTreeLookup[groupId] !== undefined || groupLookup[groupId] !== undefined) {
44
43
  throw new Error(`MUI X: The groupId ${groupId} is used multiple times in the columnGroupingModel.`);
45
44
  }
46
- groupLookup = (0, _extends2.default)({}, groupLookup, subTreeLookup, {
47
- [groupId]: groupParam
48
- });
49
- });
50
- return (0, _extends2.default)({}, groupLookup);
45
+ Object.assign(groupLookup, subTreeLookup);
46
+ groupLookup[groupId] = groupParam;
47
+ }
48
+ return groupLookup;
51
49
  };
52
50
  const columnGroupsStateInitializer = (state, props, apiRef) => {
51
+ apiRef.current.caches.columnGrouping = {
52
+ lastColumnGroupingModel: props.columnGroupingModel
53
+ };
53
54
  if (!props.columnGroupingModel) {
54
55
  return state;
55
56
  }
@@ -105,6 +106,7 @@ const useGridColumnGrouping = (apiRef, props) => {
105
106
  });
106
107
  }, [apiRef, props.columnGroupingModel]);
107
108
  const updateColumnGroupingState = React.useCallback(columnGroupingModel => {
109
+ apiRef.current.caches.columnGrouping.lastColumnGroupingModel = columnGroupingModel;
108
110
  // @ts-expect-error Move this logic to `Pro` package
109
111
  const pinnedColumns = apiRef.current.getPinnedColumns?.() ?? {};
110
112
  const columnFields = (0, _columns.gridColumnFieldsSelector)(apiRef);
@@ -136,7 +138,10 @@ const useGridColumnGrouping = (apiRef, props) => {
136
138
  * EFFECTS
137
139
  */
138
140
  React.useEffect(() => {
141
+ if (props.columnGroupingModel === apiRef.current.caches.columnGrouping.lastColumnGroupingModel) {
142
+ return;
143
+ }
139
144
  updateColumnGroupingState(props.columnGroupingModel);
140
- }, [updateColumnGroupingState, props.columnGroupingModel]);
145
+ }, [apiRef, updateColumnGroupingState, props.columnGroupingModel]);
141
146
  };
142
147
  exports.useGridColumnGrouping = useGridColumnGrouping;
@@ -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: string[];
25
- right: string[];
24
+ left: never[];
25
+ right: never[];
26
26
  };
27
27
  export interface GridPinnedColumns {
28
28
  left: GridStateColDef[];
@@ -7,6 +7,7 @@ exports.gridVisiblePinnedColumnDefinitionsSelector = exports.gridVisibleColumnFi
7
7
  var _createSelector = require("../../../utils/createSelector");
8
8
  var _gridColumnsInterfaces = require("./gridColumnsInterfaces");
9
9
  var _gridCoreSelector = require("../../core/gridCoreSelector");
10
+ var _listView = require("../listView");
10
11
  /**
11
12
  * Get the columns state
12
13
  * @category Columns
@@ -50,7 +51,7 @@ const gridInitialColumnVisibilityModelSelector = exports.gridInitialColumnVisibi
50
51
  * Get the visible columns as a lookup (an object containing the field for keys and the definition for values).
51
52
  * @category Visible Columns
52
53
  */
53
- const gridVisibleColumnDefinitionsSelector = exports.gridVisibleColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, (columns, columnVisibilityModel) => columns.filter(column => columnVisibilityModel[column.field] !== false));
54
+ const gridVisibleColumnDefinitionsSelector = exports.gridVisibleColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnDefinitionsSelector, gridColumnVisibilityModelSelector, _listView.gridListViewSelector, _listView.gridListColumnSelector, (columns, columnVisibilityModel, listView, listColumn) => listView && listColumn ? [listColumn] : columns.filter(column => columnVisibilityModel[column.field] !== false));
54
55
 
55
56
  /**
56
57
  * Get the field of each visible column.
@@ -75,7 +76,10 @@ const gridExistingPinnedColumnSelector = exports.gridExistingPinnedColumnSelecto
75
76
  * Get the visible pinned columns.
76
77
  * @category Visible Columns
77
78
  */
78
- const gridVisiblePinnedColumnDefinitionsSelector = exports.gridVisiblePinnedColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnsStateSelector, gridPinnedColumnsSelector, gridVisibleColumnFieldsSelector, _gridCoreSelector.gridIsRtlSelector, (columnsState, model, visibleColumnFields, isRtl) => {
79
+ const gridVisiblePinnedColumnDefinitionsSelector = exports.gridVisiblePinnedColumnDefinitionsSelector = (0, _createSelector.createSelectorMemoized)(gridColumnsStateSelector, gridPinnedColumnsSelector, gridVisibleColumnFieldsSelector, _gridCoreSelector.gridIsRtlSelector, _listView.gridListViewSelector, (columnsState, model, visibleColumnFields, isRtl, listView) => {
80
+ if (listView) {
81
+ return _gridColumnsInterfaces.EMPTY_PINNED_COLUMN_FIELDS;
82
+ }
79
83
  const visiblePinnedFields = filterMissingColumns(model, visibleColumnFields, isRtl);
80
84
  const visiblePinnedColumns = {
81
85
  left: visiblePinnedFields.left.map(field => columnsState.lookup[field]),
@@ -257,11 +257,13 @@ const createColumnsState = ({
257
257
  initialColumnVisibilityModel: updateInitialVisibilityModel ? columnVisibilityModel : currentState.initialColumnVisibilityModel
258
258
  };
259
259
  }
260
- let columnsToKeep = {};
260
+ const columnsToKeep = {};
261
261
  if (keepOnlyColumnsToUpsert && !isInsideStateInitializer) {
262
- columnsToKeep = Object.keys(columnsState.lookup).reduce((acc, key) => (0, _extends2.default)({}, acc, {
263
- [key]: false
264
- }), {});
262
+ for (const key in columnsState.lookup) {
263
+ if (Object.prototype.hasOwnProperty.call(columnsState.lookup, key)) {
264
+ columnsToKeep[key] = false;
265
+ }
266
+ }
265
267
  }
266
268
  const columnsToUpsertLookup = {};
267
269
  columnsToUpsert.forEach(newColumn => {
@@ -22,6 +22,9 @@ var _preferencesPanel = require("../preferencesPanel");
22
22
  var _pivoting = require("../pivoting");
23
23
  var _jsxRuntime = require("react/jsx-runtime");
24
24
  const columnsStateInitializer = (state, props, apiRef) => {
25
+ apiRef.current.caches.columns = {
26
+ lastColumnsProp: props.columns
27
+ };
25
28
  const columnsState = (0, _gridColumnsUtils.createColumnsState)({
26
29
  apiRef,
27
30
  columnsToUpsert: props.columns,
@@ -45,7 +48,6 @@ const columnsStateInitializer = (state, props, apiRef) => {
45
48
  exports.columnsStateInitializer = columnsStateInitializer;
46
49
  function useGridColumns(apiRef, props) {
47
50
  const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridColumns');
48
- const previousColumnsProp = React.useRef(props.columns);
49
51
  apiRef.current.registerControlState({
50
52
  stateId: 'visibleColumns',
51
53
  propModel: props.columnVisibilityModel,
@@ -308,27 +310,23 @@ function useGridColumns(apiRef, props) {
308
310
  */
309
311
  // The effect do not track any value defined synchronously during the 1st render by hooks called after `useGridColumns`
310
312
  // As a consequence, the state generated by the 1st run of this useEffect will always be equal to the initialization one
311
- const isFirstRender = React.useRef(true);
312
313
  React.useEffect(() => {
313
- if (isFirstRender.current) {
314
- isFirstRender.current = false;
314
+ if (apiRef.current.caches.columns.lastColumnsProp === props.columns) {
315
315
  return;
316
316
  }
317
+ apiRef.current.caches.columns.lastColumnsProp = props.columns;
317
318
  logger.info(`GridColumns have changed, new length ${props.columns.length}`);
318
- if (previousColumnsProp.current === props.columns) {
319
- return;
320
- }
321
319
  const columnsState = (0, _gridColumnsUtils.createColumnsState)({
322
320
  apiRef,
323
321
  initialState: undefined,
324
322
  // 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`
325
323
  columnsToUpsert: props.columns,
326
324
  keepOnlyColumnsToUpsert: true,
327
- updateInitialVisibilityModel: true
325
+ updateInitialVisibilityModel: true,
326
+ columnVisibilityModel: props.columnVisibilityModel
328
327
  });
329
- previousColumnsProp.current = props.columns;
330
328
  setGridColumnsState(columnsState);
331
- }, [logger, apiRef, setGridColumnsState, props.columns]);
329
+ }, [logger, apiRef, setGridColumnsState, props.columns, props.columnVisibilityModel]);
332
330
  React.useEffect(() => {
333
331
  if (props.columnVisibilityModel !== undefined) {
334
332
  apiRef.current.setColumnVisibilityModel(props.columnVisibilityModel);
@@ -23,7 +23,7 @@ const getColumnsToExport = ({
23
23
  }, []);
24
24
  }
25
25
  const validColumns = options.allColumns ? columns : (0, _columns.gridVisibleColumnDefinitionsSelector)(apiRef);
26
- return validColumns.filter(column => !column.disableExport);
26
+ return validColumns.filter(column => column.disableExport !== true);
27
27
  };
28
28
  exports.getColumnsToExport = getColumnsToExport;
29
29
  const defaultGetRowsToExport = ({
@@ -351,9 +351,9 @@ const useGridFilter = (apiRef, props) => {
351
351
  (0, _useGridEvent.useGridEvent)(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
352
352
  (0, _useGridEvent.useGridEvent)(apiRef, 'columnVisibilityModelChange', () => {
353
353
  const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
354
- if (filterModel.quickFilterValues && (0, _gridFilterUtils.shouldQuickFilterExcludeHiddenColumns)(filterModel)) {
354
+ if (filterModel.quickFilterValues?.length && (0, _gridFilterUtils.shouldQuickFilterExcludeHiddenColumns)(filterModel)) {
355
355
  // re-apply filters because the quick filter results may have changed
356
- apiRef.current.unstable_applyFilters();
356
+ updateFilteredRows();
357
357
  }
358
358
  });
359
359
 
@@ -361,7 +361,7 @@ const useGridFilter = (apiRef, props) => {
361
361
  * 1ST RENDER
362
362
  */
363
363
  (0, _useFirstRender.useFirstRender)(() => {
364
- apiRef.current.unstable_applyFilters();
364
+ updateFilteredRows();
365
365
  });
366
366
 
367
367
  /**
@@ -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" | "listView">) => void;
13
+ export declare const useGridKeyboardNavigation: (apiRef: RefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, "pagination" | "paginationMode" | "getRowId" | "signature" | "headerFilters">) => void;