@mui/x-data-grid 7.22.0 → 7.22.2

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 (73) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/colDef/gridBooleanOperators.js +4 -6
  3. package/components/GridRow.js +1 -1
  4. package/components/cell/GridBooleanCell.js +2 -1
  5. package/components/panel/filterPanel/GridFilterInputBoolean.d.ts +1 -0
  6. package/components/panel/filterPanel/GridFilterInputBoolean.js +14 -5
  7. package/components/virtualization/GridVirtualScrollbar.js +7 -1
  8. package/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -2
  9. package/hooks/features/editing/useGridCellEditing.js +23 -4
  10. package/hooks/features/editing/useGridRowEditing.js +23 -2
  11. package/hooks/features/focus/useGridFocus.js +1 -1
  12. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +3 -4
  13. package/hooks/features/listView/useGridListView.d.ts +1 -1
  14. package/hooks/features/listView/useGridListView.js +8 -2
  15. package/hooks/features/rowSelection/useGridRowSelection.d.ts +1 -1
  16. package/hooks/features/rowSelection/useGridRowSelection.js +31 -17
  17. package/hooks/features/rows/useGridRowSpanning.js +3 -1
  18. package/hooks/features/scroll/useGridScroll.js +3 -7
  19. package/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  20. package/index.js +1 -1
  21. package/internals/constants.d.ts +3 -0
  22. package/internals/constants.js +3 -0
  23. package/internals/index.d.ts +1 -0
  24. package/internals/index.js +2 -1
  25. package/internals/utils/gridRowGroupingUtils.d.ts +2 -0
  26. package/internals/utils/gridRowGroupingUtils.js +9 -0
  27. package/internals/utils/index.d.ts +1 -0
  28. package/internals/utils/index.js +2 -1
  29. package/modern/colDef/gridBooleanOperators.js +4 -6
  30. package/modern/components/GridRow.js +1 -1
  31. package/modern/components/cell/GridBooleanCell.js +2 -1
  32. package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +14 -5
  33. package/modern/components/virtualization/GridVirtualScrollbar.js +7 -1
  34. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -2
  35. package/modern/hooks/features/editing/useGridCellEditing.js +23 -4
  36. package/modern/hooks/features/editing/useGridRowEditing.js +23 -2
  37. package/modern/hooks/features/focus/useGridFocus.js +1 -1
  38. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +3 -4
  39. package/modern/hooks/features/listView/useGridListView.js +8 -2
  40. package/modern/hooks/features/rowSelection/useGridRowSelection.js +31 -17
  41. package/modern/hooks/features/rows/useGridRowSpanning.js +3 -1
  42. package/modern/hooks/features/scroll/useGridScroll.js +3 -7
  43. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  44. package/modern/index.js +1 -1
  45. package/modern/internals/constants.js +3 -0
  46. package/modern/internals/index.js +2 -1
  47. package/modern/internals/utils/gridRowGroupingUtils.js +9 -0
  48. package/modern/internals/utils/index.js +2 -1
  49. package/node/colDef/gridBooleanOperators.js +3 -5
  50. package/node/components/GridRow.js +2 -2
  51. package/node/components/cell/GridBooleanCell.js +2 -1
  52. package/node/components/panel/filterPanel/GridFilterInputBoolean.js +16 -5
  53. package/node/components/virtualization/GridVirtualScrollbar.js +7 -1
  54. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -2
  55. package/node/hooks/features/editing/useGridCellEditing.js +23 -4
  56. package/node/hooks/features/editing/useGridRowEditing.js +23 -2
  57. package/node/hooks/features/focus/useGridFocus.js +1 -1
  58. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +4 -5
  59. package/node/hooks/features/listView/useGridListView.js +8 -2
  60. package/node/hooks/features/rowSelection/useGridRowSelection.js +31 -17
  61. package/node/hooks/features/rows/useGridRowSpanning.js +3 -1
  62. package/node/hooks/features/scroll/useGridScroll.js +3 -7
  63. package/node/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  64. package/node/index.js +1 -1
  65. package/node/internals/constants.js +9 -0
  66. package/node/internals/index.js +12 -0
  67. package/node/internals/utils/gridRowGroupingUtils.js +17 -0
  68. package/node/internals/utils/index.js +11 -0
  69. package/package.json +1 -1
  70. package/constants/gridDetailPanelToggleField.d.ts +0 -1
  71. package/constants/gridDetailPanelToggleField.js +0 -2
  72. package/modern/constants/gridDetailPanelToggleField.js +0 -2
  73. package/node/constants/gridDetailPanelToggleField.js +0 -8
@@ -23,7 +23,7 @@ var _useGridVisibleRows = require("../hooks/utils/useGridVisibleRows");
23
23
  var _domUtils = require("../utils/domUtils");
24
24
  var _gridCheckboxSelectionColDef = require("../colDef/gridCheckboxSelectionColDef");
25
25
  var _gridActionsColDef = require("../colDef/gridActionsColDef");
26
- var _gridDetailPanelToggleField = require("../constants/gridDetailPanelToggleField");
26
+ var _constants = require("../internals/constants");
27
27
  var _gridSortingSelector = require("../hooks/features/sorting/gridSortingSelector");
28
28
  var _gridRowsSelector = require("../hooks/features/rows/gridRowsSelector");
29
29
  var _gridEditingSelectors = require("../hooks/features/editing/gridEditingSelectors");
@@ -145,7 +145,7 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
145
145
  }
146
146
 
147
147
  // User opened a detail panel
148
- if (field === _gridDetailPanelToggleField.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
148
+ if (field === _constants.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
149
149
  return;
150
150
  }
151
151
 
@@ -17,6 +17,7 @@ var _gridClasses = require("../../constants/gridClasses");
17
17
  var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
18
18
  var _useGridApiContext = require("../../hooks/utils/useGridApiContext");
19
19
  var _gridRowsUtils = require("../../hooks/features/rows/gridRowsUtils");
20
+ var _constants = require("../../internals/constants");
20
21
  var _jsxRuntime = require("react/jsx-runtime");
21
22
  const _excluded = ["id", "value", "formattedValue", "api", "field", "row", "rowNode", "colDef", "cellMode", "isEditable", "hasFocus", "tabIndex", "hideDescendantCount"];
22
23
  const useUtilityClasses = ownerState => {
@@ -123,7 +124,7 @@ process.env.NODE_ENV !== "production" ? GridBooleanCellRaw.propTypes = {
123
124
  } : void 0;
124
125
  const GridBooleanCell = exports.GridBooleanCell = /*#__PURE__*/React.memo(GridBooleanCellRaw);
125
126
  const renderBooleanCell = params => {
126
- if (params.field !== '__row_group_by_columns_group__' && (0, _gridRowsUtils.isAutogeneratedRowNode)(params.rowNode)) {
127
+ if (params.field !== _constants.GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD && (0, _gridRowsUtils.isAutogeneratedRowNode)(params.rowNode)) {
127
128
  return '';
128
129
  }
129
130
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridBooleanCell, (0, _extends2.default)({}, params));
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
8
  exports.GridFilterInputBoolean = GridFilterInputBoolean;
9
+ exports.sanitizeFilterItemValue = void 0;
9
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
11
  var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
11
12
  var React = _interopRequireWildcard(require("react"));
@@ -15,6 +16,16 @@ var _styles = require("@mui/material/styles");
15
16
  var _useGridRootProps = require("../../../hooks/utils/useGridRootProps");
16
17
  var _jsxRuntime = require("react/jsx-runtime");
17
18
  const _excluded = ["item", "applyValue", "apiRef", "focusElementRef", "isFilterActive", "clearButton", "tabIndex", "label", "variant", "InputLabelProps"];
19
+ const sanitizeFilterItemValue = value => {
20
+ if (String(value).toLowerCase() === 'true') {
21
+ return true;
22
+ }
23
+ if (String(value).toLowerCase() === 'false') {
24
+ return false;
25
+ }
26
+ return undefined;
27
+ };
28
+ exports.sanitizeFilterItemValue = sanitizeFilterItemValue;
18
29
  const BooleanOperatorContainer = (0, _styles.styled)('div')({
19
30
  display: 'flex',
20
31
  alignItems: 'center',
@@ -35,7 +46,7 @@ function GridFilterInputBoolean(props) {
35
46
  variant = 'standard'
36
47
  } = props,
37
48
  others = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
38
- const [filterValueState, setFilterValueState] = React.useState(item.value || '');
49
+ const [filterValueState, setFilterValueState] = React.useState(sanitizeFilterItemValue(item.value));
39
50
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
40
51
  const labelId = (0, _utils.unstable_useId)();
41
52
  const selectId = (0, _utils.unstable_useId)();
@@ -43,14 +54,14 @@ function GridFilterInputBoolean(props) {
43
54
  const isSelectNative = baseSelectProps.native ?? false;
44
55
  const baseSelectOptionProps = rootProps.slotProps?.baseSelectOption || {};
45
56
  const onFilterChange = React.useCallback(event => {
46
- const value = event.target.value;
57
+ const value = sanitizeFilterItemValue(event.target.value);
47
58
  setFilterValueState(value);
48
59
  applyValue((0, _extends2.default)({}, item, {
49
- value: Boolean(value)
60
+ value
50
61
  }));
51
62
  }, [applyValue, item]);
52
63
  React.useEffect(() => {
53
- setFilterValueState(item.value || '');
64
+ setFilterValueState(sanitizeFilterItemValue(item.value));
54
65
  }, [item.value]);
55
66
  const label = labelProp ?? apiRef.current.getLocaleText('filterPanelInputLabel');
56
67
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(BooleanOperatorContainer, {
@@ -65,7 +76,7 @@ function GridFilterInputBoolean(props) {
65
76
  labelId: labelId,
66
77
  id: selectId,
67
78
  label: label,
68
- value: filterValueState,
79
+ value: filterValueState === undefined ? '' : String(filterValueState),
69
80
  onChange: onFilterChange,
70
81
  variant: variant,
71
82
  notched: variant === 'outlined' ? true : undefined,
@@ -77,9 +77,13 @@ const GridVirtualScrollbar = exports.GridVirtualScrollbar = /*#__PURE__*/React.f
77
77
  const onScrollerScroll = (0, _utils.unstable_useEventCallback)(() => {
78
78
  const scroller = apiRef.current.virtualScrollerRef.current;
79
79
  const scrollbar = scrollbarRef.current;
80
+ if (!scrollbar) {
81
+ return;
82
+ }
80
83
  if (scroller[propertyScroll] === lastPosition.current) {
81
84
  return;
82
85
  }
86
+ lastPosition.current = scroller[propertyScroll];
83
87
  if (isLocked.current) {
84
88
  isLocked.current = false;
85
89
  return;
@@ -87,11 +91,13 @@ const GridVirtualScrollbar = exports.GridVirtualScrollbar = /*#__PURE__*/React.f
87
91
  isLocked.current = true;
88
92
  const value = scroller[propertyScroll] / contentSize;
89
93
  scrollbar[propertyScroll] = value * scrollbarInnerSize;
90
- lastPosition.current = scroller[propertyScroll];
91
94
  });
92
95
  const onScrollbarScroll = (0, _utils.unstable_useEventCallback)(() => {
93
96
  const scroller = apiRef.current.virtualScrollerRef.current;
94
97
  const scrollbar = scrollbarRef.current;
98
+ if (!scrollbar) {
99
+ return;
100
+ }
95
101
  if (isLocked.current) {
96
102
  isLocked.current = false;
97
103
  return;
@@ -231,7 +231,6 @@ const useGridColumnHeaders = props => {
231
231
  return null;
232
232
  }
233
233
  const {
234
- renderedColumns,
235
234
  firstColumnToRender,
236
235
  lastColumnToRender
237
236
  } = columnsToRender;
@@ -300,7 +299,7 @@ const useGridColumnHeaders = props => {
300
299
  pinnedPosition: pinnedPosition,
301
300
  style: style,
302
301
  indexInSection: indexInSection,
303
- sectionLength: renderedColumns.length,
302
+ sectionLength: rowStructure.length,
304
303
  gridHasFiller: gridHasFiller
305
304
  }, index);
306
305
  });
@@ -249,26 +249,45 @@ const useGridCellEditing = (apiRef, props) => {
249
249
  mode: _gridEditRowModel.GridCellModes.Edit
250
250
  }, other));
251
251
  }, [throwIfNotEditable, throwIfNotInMode, updateFieldInCellModesModel]);
252
- const updateStateToStartCellEditMode = (0, _utils.unstable_useEventCallback)(params => {
252
+ const updateStateToStartCellEditMode = (0, _utils.unstable_useEventCallback)(async params => {
253
253
  const {
254
254
  id,
255
255
  field,
256
256
  deleteValue,
257
257
  initialValue
258
258
  } = params;
259
- let newValue = apiRef.current.getCellValue(id, field);
259
+ const value = apiRef.current.getCellValue(id, field);
260
+ let newValue = value;
260
261
  if (deleteValue) {
261
262
  newValue = (0, _utils3.getDefaultCellValue)(apiRef.current.getColumn(field));
262
263
  } else if (initialValue) {
263
264
  newValue = initialValue;
264
265
  }
265
- const newProps = {
266
+ const column = apiRef.current.getColumn(field);
267
+ const shouldProcessEditCellProps = !!column.preProcessEditCellProps && deleteValue;
268
+ let newProps = {
266
269
  value: newValue,
267
270
  error: false,
268
- isProcessingProps: false
271
+ isProcessingProps: shouldProcessEditCellProps
269
272
  };
270
273
  updateOrDeleteFieldState(id, field, newProps);
271
274
  apiRef.current.setCellFocus(id, field);
275
+ if (shouldProcessEditCellProps) {
276
+ newProps = await Promise.resolve(column.preProcessEditCellProps({
277
+ id,
278
+ row: apiRef.current.getRow(id),
279
+ props: newProps,
280
+ hasChanged: newValue !== value
281
+ }));
282
+ // Check if still in edit mode before updating
283
+ if (apiRef.current.getCellMode(id, field) === _gridEditRowModel.GridCellModes.Edit) {
284
+ const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
285
+ updateOrDeleteFieldState(id, field, (0, _extends2.default)({}, newProps, {
286
+ value: editingState[id][field].value,
287
+ isProcessingProps: false
288
+ }));
289
+ }
290
+ }
272
291
  });
273
292
  const stopCellEditMode = React.useCallback(params => {
274
293
  const {
@@ -326,10 +326,11 @@ const useGridRowEditing = (apiRef, props) => {
326
326
  if (!cellParams.isEditable) {
327
327
  return acc;
328
328
  }
329
+ const column = apiRef.current.getColumn(field);
329
330
  let newValue = apiRef.current.getCellValue(id, field);
330
331
  if (fieldToFocus === field && (deleteValue || initialValue)) {
331
332
  if (deleteValue) {
332
- newValue = (0, _utils3.getDefaultCellValue)(apiRef.current.getColumn(field));
333
+ newValue = (0, _utils3.getDefaultCellValue)(column);
333
334
  } else if (initialValue) {
334
335
  newValue = initialValue;
335
336
  }
@@ -337,7 +338,7 @@ const useGridRowEditing = (apiRef, props) => {
337
338
  acc[field] = {
338
339
  value: newValue,
339
340
  error: false,
340
- isProcessingProps: false
341
+ isProcessingProps: !!column.preProcessEditCellProps && deleteValue
341
342
  };
342
343
  return acc;
343
344
  }, {});
@@ -345,6 +346,26 @@ const useGridRowEditing = (apiRef, props) => {
345
346
  if (fieldToFocus) {
346
347
  apiRef.current.setCellFocus(id, fieldToFocus);
347
348
  }
349
+ columnFields.filter(field => !!apiRef.current.getColumn(field).preProcessEditCellProps && deleteValue).forEach(field => {
350
+ const column = apiRef.current.getColumn(field);
351
+ const value = apiRef.current.getCellValue(id, field);
352
+ const newValue = deleteValue ? (0, _utils3.getDefaultCellValue)(column) : initialValue ?? value;
353
+ Promise.resolve(column.preProcessEditCellProps({
354
+ id,
355
+ row: apiRef.current.getRow(id),
356
+ props: newProps[field],
357
+ hasChanged: newValue !== value
358
+ })).then(processedProps => {
359
+ // Check if still in edit mode before updating
360
+ if (apiRef.current.getRowMode(id) === _gridEditRowModel.GridRowModes.Edit) {
361
+ const editingState = (0, _gridEditingSelectors.gridEditRowsStateSelector)(apiRef.current.state);
362
+ updateOrDeleteFieldState(id, field, (0, _extends2.default)({}, processedProps, {
363
+ value: editingState[id][field].value,
364
+ isProcessingProps: false
365
+ }));
366
+ }
367
+ });
368
+ });
348
369
  });
349
370
  const stopRowEditMode = React.useCallback(params => {
350
371
  const {
@@ -344,7 +344,7 @@ const useGridFocus = (apiRef, props) => {
344
344
  paginationMode: props.paginationMode
345
345
  });
346
346
  const nextRow = currentPage.rows[(0, _utils2.clamp)(lastFocusedRowIndex, 0, currentPage.rows.length - 1)];
347
- nextRowId = nextRow.id ?? null;
347
+ nextRowId = nextRow?.id ?? null;
348
348
  }
349
349
  apiRef.current.setState(state => (0, _extends2.default)({}, state, {
350
350
  focus: {
@@ -7,6 +7,8 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.useGridKeyboardNavigation = void 0;
8
8
  var React = _interopRequireWildcard(require("react"));
9
9
  var _RtlProvider = require("@mui/system/RtlProvider");
10
+ var _constants = require("../../../internals/constants");
11
+ var _gridRowGroupingUtils = require("../../../internals/utils/gridRowGroupingUtils");
10
12
  var _gridColumnsSelector = require("../columns/gridColumnsSelector");
11
13
  var _useGridLogger = require("../../utils/useGridLogger");
12
14
  var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
@@ -16,7 +18,6 @@ var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectio
16
18
  var _gridClasses = require("../../../constants/gridClasses");
17
19
  var _gridEditRowModel = require("../../../models/gridEditRowModel");
18
20
  var _keyboardUtils = require("../../../utils/keyboardUtils");
19
- var _gridDetailPanelToggleField = require("../../../constants/gridDetailPanelToggleField");
20
21
  var _focus = require("../focus");
21
22
  var _gridColumnGroupsSelector = require("../columnGrouping/gridColumnGroupsSelector");
22
23
  var _gridHeaderFilteringSelectors = require("../headerFiltering/gridHeaderFilteringSelectors");
@@ -460,13 +461,11 @@ const useGridKeyboardNavigation = (apiRef, props) => {
460
461
  case ' ':
461
462
  {
462
463
  const field = params.field;
463
- if (field === _gridDetailPanelToggleField.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
464
+ if (field === _constants.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
464
465
  break;
465
466
  }
466
467
  const colDef = params.colDef;
467
- if (colDef &&
468
- // `GRID_TREE_DATA_GROUPING_FIELD` from the Pro package
469
- colDef.field === '__tree_data_group__') {
468
+ if (colDef && (colDef.field === _constants.GRID_TREE_DATA_GROUPING_FIELD || (0, _gridRowGroupingUtils.isGroupingColumn)(colDef.field))) {
470
469
  break;
471
470
  }
472
471
  if (!event.shiftKey && rowIndexBefore < lastRowIndexInPage) {
@@ -9,12 +9,13 @@ exports.listViewStateInitializer = void 0;
9
9
  exports.useGridListView = useGridListView;
10
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
11
  var React = _interopRequireWildcard(require("react"));
12
+ var _warning = require("@mui/x-internals/warning");
12
13
  var _dimensions = require("../dimensions");
13
14
  var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler");
14
15
  const listViewStateInitializer = (state, props, apiRef) => (0, _extends2.default)({}, state, {
15
- listViewColumn: (0, _extends2.default)({}, props.unstable_listColumn, {
16
+ listViewColumn: props.unstable_listColumn ? (0, _extends2.default)({}, props.unstable_listColumn, {
16
17
  computedWidth: getListColumnWidth(apiRef)
17
- })
18
+ }) : undefined
18
19
  });
19
20
  exports.listViewStateInitializer = listViewStateInitializer;
20
21
  function useGridListView(apiRef, props) {
@@ -58,6 +59,11 @@ function useGridListView(apiRef, props) {
58
59
  });
59
60
  }
60
61
  }, [apiRef, props.unstable_listColumn]);
62
+ React.useEffect(() => {
63
+ if (props.unstable_listView && !props.unstable_listColumn) {
64
+ (0, _warning.warnOnce)(['MUI X: The `unstable_listColumn` prop must be set if `unstable_listView` is enabled.', 'To fix, pass a column definition to the `unstable_listColumn` prop, e.g. `{ field: "example", renderCell: (params) => <div>{params.row.id}</div> }`.', 'For more details, see https://mui.com/x/react-data-grid/list-view/']);
65
+ }
66
+ }, [props.unstable_listView, props.unstable_listColumn]);
61
67
  }
62
68
  function getListColumnWidth(apiRef) {
63
69
  return (0, _dimensions.gridDimensionsSelector)(apiRef.current.state).viewportInnerSize.width;
@@ -21,7 +21,7 @@ var _colDef = require("../../../colDef");
21
21
  var _gridEditRowModel = require("../../../models/gridEditRowModel");
22
22
  var _keyboardUtils = require("../../../utils/keyboardUtils");
23
23
  var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
24
- var _gridDetailPanelToggleField = require("../../../constants/gridDetailPanelToggleField");
24
+ var _constants = require("../../../internals/constants");
25
25
  var _gridClasses = require("../../../constants/gridClasses");
26
26
  var _domUtils = require("../../../utils/domUtils");
27
27
  var _utils = require("./utils");
@@ -180,30 +180,33 @@ const useGridRowSelection = (apiRef, props) => {
180
180
  let newSelection;
181
181
  if (resetSelection) {
182
182
  if (isSelected) {
183
- newSelection = selectableIds;
183
+ newSelection = new Set(selectableIds);
184
184
  if (applyAutoSelection) {
185
185
  const addRow = rowId => {
186
- newSelection.push(rowId);
186
+ newSelection.add(rowId);
187
187
  };
188
188
  selectableIds.forEach(id => {
189
189
  (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
190
190
  });
191
191
  }
192
192
  } else {
193
- newSelection = [];
193
+ newSelection = new Set();
194
+ }
195
+ const currentLookup = (0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef);
196
+ if (newSelection.size === Object.keys(currentLookup).length && Array.from(newSelection).every(id => currentLookup[id] === id)) {
197
+ return;
194
198
  }
195
199
  } else {
196
- // We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
197
- const selectionLookup = (0, _extends2.default)({}, (0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef));
200
+ newSelection = new Set(Object.values((0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef)));
198
201
  const addRow = rowId => {
199
- selectionLookup[rowId] = rowId;
202
+ newSelection.add(rowId);
200
203
  };
201
204
  const removeRow = rowId => {
202
- delete selectionLookup[rowId];
205
+ newSelection.delete(rowId);
203
206
  };
204
207
  selectableIds.forEach(id => {
205
208
  if (isSelected) {
206
- selectionLookup[id] = id;
209
+ newSelection.add(id);
207
210
  if (applyAutoSelection) {
208
211
  (0, _utils.findRowsToSelect)(apiRef, tree, id, props.rowSelectionPropagation?.descendants ?? false, props.rowSelectionPropagation?.parents ?? false, addRow);
209
212
  }
@@ -214,11 +217,10 @@ const useGridRowSelection = (apiRef, props) => {
214
217
  }
215
218
  }
216
219
  });
217
- newSelection = Object.values(selectionLookup);
218
220
  }
219
- const isSelectionValid = newSelection.length < 2 || canHaveMultipleSelection;
221
+ const isSelectionValid = newSelection.size < 2 || canHaveMultipleSelection;
220
222
  if (isSelectionValid) {
221
- apiRef.current.setRowSelectionModel(newSelection);
223
+ apiRef.current.setRowSelectionModel(Array.from(newSelection));
222
224
  }
223
225
  }, [logger, applyAutoSelection, canHaveMultipleSelection, apiRef, tree, props.rowSelectionPropagation?.descendants, props.rowSelectionPropagation?.parents]);
224
226
  const selectRowRange = React.useCallback(({
@@ -261,13 +263,20 @@ const useGridRowSelection = (apiRef, props) => {
261
263
  return;
262
264
  }
263
265
  const currentSelection = (0, _gridRowSelectionSelector.gridRowSelectionStateSelector)(apiRef.current.state);
266
+ const rowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
264
267
  const filteredRowsLookup = (0, _gridFilterSelector.gridFilteredRowsLookupSelector)(apiRef);
265
268
 
266
269
  // We clone the existing object to avoid mutating the same object returned by the selector to others part of the project
267
270
  const selectionLookup = (0, _extends2.default)({}, (0, _gridRowSelectionSelector.selectedIdsLookupSelector)(apiRef));
271
+ const isNonExistent = id => {
272
+ if (props.filterMode === 'server') {
273
+ return !rowsLookup[id];
274
+ }
275
+ return filteredRowsLookup[id] !== true;
276
+ };
268
277
  let hasChanged = false;
269
278
  currentSelection.forEach(id => {
270
- if (filteredRowsLookup[id] !== true) {
279
+ if (isNonExistent(id)) {
271
280
  if (props.keepNonExistentRowsSelected) {
272
281
  return;
273
282
  }
@@ -293,15 +302,20 @@ const useGridRowSelection = (apiRef, props) => {
293
302
  }
294
303
  }
295
304
  });
296
- if (hasChanged || isNestedData && !sortModelUpdated) {
305
+
306
+ // For nested data, on row tree updation (filtering, adding rows, etc.) when the selection is
307
+ // not empty, we need to re-run scanning of the tree to propagate the selection changes
308
+ // Example: A parent whose de-selected children are filtered out should now be selected
309
+ const shouldReapplyPropagation = isNestedData && props.rowSelectionPropagation?.parents && Object.keys(selectionLookup).length > 0;
310
+ if (hasChanged || shouldReapplyPropagation && !sortModelUpdated) {
297
311
  const newSelection = Object.values(selectionLookup);
298
- if (isNestedData) {
312
+ if (shouldReapplyPropagation) {
299
313
  apiRef.current.selectRows(newSelection, true, true);
300
314
  } else {
301
315
  apiRef.current.setRowSelectionModel(newSelection);
302
316
  }
303
317
  }
304
- }, [apiRef, isNestedData, props.rowSelectionPropagation?.parents, props.keepNonExistentRowsSelected, tree]);
318
+ }, [apiRef, isNestedData, props.rowSelectionPropagation?.parents, props.keepNonExistentRowsSelected, props.filterMode, tree]);
305
319
  const handleSingleRowSelection = React.useCallback((id, event) => {
306
320
  const hasCtrlKey = event.metaKey || event.ctrlKey;
307
321
 
@@ -328,7 +342,7 @@ const useGridRowSelection = (apiRef, props) => {
328
342
  // click on checkbox should not trigger row selection
329
343
  return;
330
344
  }
331
- if (field === _gridDetailPanelToggleField.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
345
+ if (field === _constants.GRID_DETAIL_PANEL_TOGGLE_FIELD) {
332
346
  // click to open the detail panel should not select the row
333
347
  return;
334
348
  }
@@ -9,11 +9,13 @@ exports.useGridRowSpanning = exports.rowSpanningStateInitializer = void 0;
9
9
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
10
10
  var React = _interopRequireWildcard(require("react"));
11
11
  var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
12
+ var _constants = require("../../../internals/constants");
12
13
  var _gridColumnsSelector = require("../columns/gridColumnsSelector");
13
14
  var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
14
15
  var _gridVirtualizationSelectors = require("../virtualization/gridVirtualizationSelectors");
15
16
  var _useGridSelector = require("../../utils/useGridSelector");
16
17
  var _gridRowSpanningUtils = require("./gridRowSpanningUtils");
18
+ var _gridCheckboxSelectionColDef = require("../../../colDef/gridCheckboxSelectionColDef");
17
19
  const EMPTY_STATE = {
18
20
  spannedCells: {},
19
21
  hiddenCells: {},
@@ -23,7 +25,7 @@ const EMPTY_RANGE = {
23
25
  firstRowIndex: 0,
24
26
  lastRowIndex: 0
25
27
  };
26
- const skippedFields = new Set(['__check__', '__reorder__', '__detail_panel_toggle__']);
28
+ const skippedFields = new Set([_gridCheckboxSelectionColDef.GRID_CHECKBOX_SELECTION_FIELD, '__reorder__', _constants.GRID_DETAIL_PANEL_TOGGLE_FIELD]);
27
29
  /**
28
30
  * Default number of rows to process during state initialization to avoid flickering.
29
31
  * Number `20` is arbitrarily chosen to be large enough to cover most of the cases without
@@ -54,8 +54,6 @@ const useGridScroll = (apiRef, props) => {
54
54
  const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useGridScroll');
55
55
  const colRef = apiRef.current.columnHeadersContainerRef;
56
56
  const virtualScrollerRef = apiRef.current.virtualScrollerRef;
57
- const virtualScrollbarHorizontalRef = apiRef.current.virtualScrollbarHorizontalRef;
58
- const virtualScrollbarVerticalRef = apiRef.current.virtualScrollbarVerticalRef;
59
57
  const visibleSortedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridFilterSelector.gridExpandedSortedRowEntriesSelector);
60
58
  const scrollToIndexes = React.useCallback(params => {
61
59
  const dimensions = (0, _dimensions.gridDimensionsSelector)(apiRef.current.state);
@@ -109,20 +107,18 @@ const useGridScroll = (apiRef, props) => {
109
107
  return false;
110
108
  }, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows, props.unstable_listView]);
111
109
  const scroll = React.useCallback(params => {
112
- if (virtualScrollerRef.current && virtualScrollbarHorizontalRef.current && params.left !== undefined && colRef.current) {
110
+ if (virtualScrollerRef.current && params.left !== undefined && colRef.current) {
113
111
  const direction = isRtl ? -1 : 1;
114
112
  colRef.current.scrollLeft = params.left;
115
113
  virtualScrollerRef.current.scrollLeft = direction * params.left;
116
- virtualScrollbarHorizontalRef.current.scrollLeft = direction * params.left;
117
114
  logger.debug(`Scrolling left: ${params.left}`);
118
115
  }
119
- if (virtualScrollerRef.current && virtualScrollbarVerticalRef.current && params.top !== undefined) {
116
+ if (virtualScrollerRef.current && params.top !== undefined) {
120
117
  virtualScrollerRef.current.scrollTop = params.top;
121
- virtualScrollbarVerticalRef.current.scrollTop = params.top;
122
118
  logger.debug(`Scrolling top: ${params.top}`);
123
119
  }
124
120
  logger.debug(`Scrolling, updating container, and viewport`);
125
- }, [virtualScrollerRef, virtualScrollbarHorizontalRef, virtualScrollbarVerticalRef, isRtl, colRef, logger]);
121
+ }, [virtualScrollerRef, isRtl, colRef, logger]);
126
122
  const getScrollPosition = React.useCallback(() => {
127
123
  if (!virtualScrollerRef?.current) {
128
124
  return {
@@ -393,7 +393,7 @@ const useGridVirtualScroller = () => {
393
393
  flexShrink: 0
394
394
  };
395
395
  if (rootProps.autoHeight && currentPage.rows.length === 0) {
396
- size.height = (0, _gridRowsUtils.getMinimalContentHeight)(apiRef); // Give room to show the overlay when there no rows.
396
+ size.flexBasis = (0, _gridRowsUtils.getMinimalContentHeight)(apiRef); // Give room to show the overlay when there no rows.
397
397
  }
398
398
  return size;
399
399
  }, [apiRef, columnsTotalWidth, contentHeight, needsHorizontalScrollbar, rootProps.autoHeight, currentPage.rows.length]);
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.22.0
2
+ * @mui/x-data-grid v7.22.2
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.GRID_TREE_DATA_GROUPING_FIELD = exports.GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD = exports.GRID_DETAIL_PANEL_TOGGLE_FIELD = void 0;
7
+ const GRID_TREE_DATA_GROUPING_FIELD = exports.GRID_TREE_DATA_GROUPING_FIELD = '__tree_data_group__';
8
+ const GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD = exports.GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD = '__row_group_by_columns_group__';
9
+ const GRID_DETAIL_PANEL_TOGGLE_FIELD = exports.GRID_DETAIL_PANEL_TOGGLE_FIELD = '__detail_panel_toggle__';
@@ -879,4 +879,16 @@ Object.keys(_utils5).forEach(function (key) {
879
879
  return _utils5[key];
880
880
  }
881
881
  });
882
+ });
883
+ var _constants = require("./constants");
884
+ Object.keys(_constants).forEach(function (key) {
885
+ if (key === "default" || key === "__esModule") return;
886
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
887
+ if (key in exports && exports[key] === _constants[key]) return;
888
+ Object.defineProperty(exports, key, {
889
+ enumerable: true,
890
+ get: function () {
891
+ return _constants[key];
892
+ }
893
+ });
882
894
  });
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.isGroupingColumn = exports.getRowGroupingCriteriaFromGroupingField = void 0;
7
+ var _constants = require("../constants");
8
+ const getRowGroupingCriteriaFromGroupingField = groupingColDefField => {
9
+ const match = groupingColDefField.match(/^__row_group_by_columns_group_(.*)__$/);
10
+ if (!match) {
11
+ return null;
12
+ }
13
+ return match[1];
14
+ };
15
+ exports.getRowGroupingCriteriaFromGroupingField = getRowGroupingCriteriaFromGroupingField;
16
+ const isGroupingColumn = field => field === _constants.GRID_ROW_GROUPING_SINGLE_GROUPING_FIELD || getRowGroupingCriteriaFromGroupingField(field) !== null;
17
+ exports.isGroupingColumn = isGroupingColumn;
@@ -35,4 +35,15 @@ Object.keys(_propValidation).forEach(function (key) {
35
35
  return _propValidation[key];
36
36
  }
37
37
  });
38
+ });
39
+ var _gridRowGroupingUtils = require("./gridRowGroupingUtils");
40
+ Object.keys(_gridRowGroupingUtils).forEach(function (key) {
41
+ if (key === "default" || key === "__esModule") return;
42
+ if (key in exports && exports[key] === _gridRowGroupingUtils[key]) return;
43
+ Object.defineProperty(exports, key, {
44
+ enumerable: true,
45
+ get: function () {
46
+ return _gridRowGroupingUtils[key];
47
+ }
48
+ });
38
49
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid",
3
- "version": "7.22.0",
3
+ "version": "7.22.2",
4
4
  "description": "The Community plan edition of the Data Grid components (MUI X).",
5
5
  "author": "MUI Team",
6
6
  "main": "./node/index.js",
@@ -1 +0,0 @@
1
- export declare const GRID_DETAIL_PANEL_TOGGLE_FIELD = "__detail_panel_toggle__";
@@ -1,2 +0,0 @@
1
- // Can't import from pro package - hence duplication
2
- export const GRID_DETAIL_PANEL_TOGGLE_FIELD = '__detail_panel_toggle__';
@@ -1,2 +0,0 @@
1
- // Can't import from pro package - hence duplication
2
- export const GRID_DETAIL_PANEL_TOGGLE_FIELD = '__detail_panel_toggle__';
@@ -1,8 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.GRID_DETAIL_PANEL_TOGGLE_FIELD = void 0;
7
- // Can't import from pro package - hence duplication
8
- const GRID_DETAIL_PANEL_TOGGLE_FIELD = exports.GRID_DETAIL_PANEL_TOGGLE_FIELD = '__detail_panel_toggle__';