@mui/x-data-grid 6.10.0 → 6.10.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 (64) hide show
  1. package/CHANGELOG.md +72 -3
  2. package/components/panel/GridPanel.js +2 -2
  3. package/components/panel/filterPanel/GridFilterForm.js +2 -2
  4. package/components/panel/filterPanel/GridFilterInputSingleSelect.js +2 -2
  5. package/hooks/features/columns/gridColumnsUtils.js +17 -7
  6. package/hooks/features/columns/useGridColumns.js +4 -4
  7. package/hooks/features/dimensions/useGridDimensions.js +1 -1
  8. package/hooks/features/editing/useGridCellEditing.js +4 -4
  9. package/hooks/features/export/serializers/csvSerializer.js +3 -5
  10. package/hooks/features/export/useGridPrintExport.js +10 -3
  11. package/hooks/features/export/utils.js +2 -2
  12. package/hooks/features/filter/gridFilterSelector.js +1 -1
  13. package/hooks/features/filter/gridFilterUtils.js +37 -10
  14. package/hooks/features/filter/useGridFilter.js +14 -9
  15. package/hooks/features/focus/useGridFocus.js +30 -1
  16. package/hooks/features/pagination/useGridPagination.js +6 -6
  17. package/hooks/features/rows/gridRowsSelector.js +3 -3
  18. package/hooks/features/rows/gridRowsUtils.js +2 -2
  19. package/hooks/features/rows/useGridRowsMeta.js +2 -2
  20. package/hooks/features/sorting/useGridSorting.js +6 -6
  21. package/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  22. package/index.js +1 -1
  23. package/joy/joySlots.js +2 -2
  24. package/legacy/components/panel/GridPanel.js +2 -2
  25. package/legacy/components/panel/filterPanel/GridFilterForm.js +2 -2
  26. package/legacy/components/panel/filterPanel/GridFilterInputSingleSelect.js +2 -2
  27. package/legacy/hooks/features/columns/gridColumnsUtils.js +17 -7
  28. package/legacy/hooks/features/columns/useGridColumns.js +4 -4
  29. package/legacy/hooks/features/dimensions/useGridDimensions.js +1 -1
  30. package/legacy/hooks/features/editing/useGridCellEditing.js +4 -4
  31. package/legacy/hooks/features/export/serializers/csvSerializer.js +4 -6
  32. package/legacy/hooks/features/export/useGridPrintExport.js +16 -4
  33. package/legacy/hooks/features/export/utils.js +2 -2
  34. package/legacy/hooks/features/filter/gridFilterSelector.js +1 -1
  35. package/legacy/hooks/features/filter/gridFilterUtils.js +30 -10
  36. package/legacy/hooks/features/filter/useGridFilter.js +14 -11
  37. package/legacy/hooks/features/focus/useGridFocus.js +32 -1
  38. package/legacy/hooks/features/pagination/useGridPagination.js +6 -6
  39. package/legacy/hooks/features/rows/gridRowsSelector.js +3 -3
  40. package/legacy/hooks/features/rows/gridRowsUtils.js +2 -2
  41. package/legacy/hooks/features/rows/useGridRowsMeta.js +2 -2
  42. package/legacy/hooks/features/sorting/useGridSorting.js +6 -6
  43. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +1 -1
  44. package/legacy/index.js +1 -1
  45. package/legacy/joy/joySlots.js +2 -2
  46. package/legacy/utils/getGridLocalization.js +2 -2
  47. package/modern/hooks/features/columns/gridColumnsUtils.js +15 -5
  48. package/modern/hooks/features/dimensions/useGridDimensions.js +1 -1
  49. package/modern/hooks/features/export/serializers/csvSerializer.js +3 -5
  50. package/modern/hooks/features/export/useGridPrintExport.js +8 -1
  51. package/modern/hooks/features/filter/gridFilterUtils.js +37 -10
  52. package/modern/hooks/features/filter/useGridFilter.js +8 -3
  53. package/modern/hooks/features/focus/useGridFocus.js +30 -1
  54. package/modern/index.js +1 -1
  55. package/node/hooks/features/columns/gridColumnsUtils.js +15 -5
  56. package/node/hooks/features/dimensions/useGridDimensions.js +1 -1
  57. package/node/hooks/features/export/serializers/csvSerializer.js +3 -5
  58. package/node/hooks/features/export/useGridPrintExport.js +8 -1
  59. package/node/hooks/features/filter/gridFilterUtils.js +37 -10
  60. package/node/hooks/features/filter/useGridFilter.js +8 -3
  61. package/node/hooks/features/focus/useGridFocus.js +29 -0
  62. package/node/index.js +1 -1
  63. package/package.json +3 -3
  64. package/utils/getGridLocalization.js +2 -2
package/CHANGELOG.md CHANGED
@@ -3,6 +3,75 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 6.10.1
7
+
8
+ _Jul 20, 2023_
9
+
10
+ We'd like to offer a big thanks to the 11 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🎁 Fix CSV export for values containing double quotes
13
+ - 🚀 Improve tree data performance
14
+ - 🐞 Bugfixes
15
+ - 📚 Documentation improvements
16
+
17
+ ### Data Grid
18
+
19
+ #### `@mui/x-data-grid@v6.10.1`
20
+
21
+ - [DataGrid] Filtering performance: compile filter applier with `eval` (#9635) @romgrk
22
+ - [DataGrid] Fix CSV export for values containing double quotes (#9667) @cherniavskii
23
+ - [DataGrid] Fix column type change not working correctly (#9594) @cherniavskii
24
+ - [DataGrid] Fix quick filter `undefined` row error (#9708) @romgrk
25
+ - [DataGrid] Prevent `viewportOuterSize.height` going negative (#9664) @gitstart
26
+ - [DataGrid] Update focused cell on page change via keyboard (#9203) @m4theushw
27
+ - [DataGrid] Wait for remote stylesheets to load before print (#9665) @cherniavskii
28
+
29
+ #### `@mui/x-data-grid-pro@v6.10.1` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link)
30
+
31
+ Same changes as in `@mui/x-data-grid@v6.10.1`, plus:
32
+
33
+ - [DataGridPro] Improve tree data performance (#9682) @cherniavskii
34
+ - [DataGridPro] Prevent affecting cells from child DataGrid when resizing a column (#9670) @m4theushw
35
+
36
+ #### `@mui/x-data-grid-premium@v6.10.1` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link)
37
+
38
+ Same changes as in `@mui/x-data-grid-pro@v6.10.1`.
39
+
40
+ ### Date Pickers
41
+
42
+ #### `@mui/x-date-pickers@v6.10.1`
43
+
44
+ - [fields] Fix `format` and `value` update order (#9715) @LukasTy
45
+ - [pickers] Remove `require` usage in comment (#9675) @LukasTy
46
+
47
+ #### `@mui/x-date-pickers-pro@v6.10.1` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link)
48
+
49
+ Same changes as in `@mui/x-date-pickers@v6.10.1`.
50
+
51
+ ### Charts / `@mui/x-charts@v6.0.0-alpha.4`
52
+
53
+ - [charts] Fix blinking in responsive charts and extremums computation for line charts (#9734) @alexfauquette
54
+ - [charts] Use ESM with imports (#9645) @alexfauquette
55
+
56
+ ### Docs
57
+
58
+ - [docs] Add additional note for license key installation on Next.js (#9575) @joserodolfofreitas
59
+ - [docs] Add paragraph about managing focus of custom edit components (#9658) @m4theushw
60
+ - [docs] Add unsorted icon slot to the custom sort icons demo (#9169) @d4rekanguok
61
+ - [docs] Disable ad for onboarding pages (#9700) @oliviertassinari
62
+ - [docs] Disabling ads without toolbar has no effect @oliviertassinari
63
+ - [docs] Fix Date Pickers usage to Title Case (#9680) @richbustos
64
+ - [docs] Fix sorting in `CustomSortIcons` demo (#9656) @MBilalShafi
65
+ - [docs] Improve the UI for pickers introduction (#9644) @alexfauquette
66
+ - [docs] Improve the demo design @oliviertassinari
67
+ - [docs] Localization progress, polish (#9672) @oliviertassinari
68
+ - [docs] Normalize the WIP items (#9671) @oliviertassinari
69
+
70
+ ### Core
71
+
72
+ - [core] Add `validate` command (#9714) @romgrk
73
+ - [CHANGELOG] Update generator to new format @oliviertassinari
74
+
6
75
  ## 6.10.0
7
76
 
8
77
  _Jul 13, 2023_
@@ -26,11 +95,11 @@ We'd like to offer a big thanks to the 10 contributors who made this release pos
26
95
  - [DataGrid] Make `rowExpansionChange` event public (#9611) @MBilalShafi
27
96
  - [l10n] Improve Polish (pl-PL) locale (#9625) @ch1llysense
28
97
 
29
- #### `@mui/x-data-grid-pro@6.10.0`
98
+ #### `@mui/x-data-grid-pro@6.10.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link)
30
99
 
31
100
  Same changes as in `@mui/x-data-grid@6.10.0`.
32
101
 
33
- #### `@mui/x-data-grid-premium@6.10.0`
102
+ #### `@mui/x-data-grid-premium@6.10.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link)
34
103
 
35
104
  Same changes as in `@mui/x-data-grid-pro@6.10.0`.
36
105
 
@@ -41,7 +110,7 @@ Same changes as in `@mui/x-data-grid-pro@6.10.0`.
41
110
  - [pickers] Fix date calendar issues (#9652) @LukasTy
42
111
  - [l10n] Improve Norwegian (nb-NO) locale (#9608) @JosteinBrevik
43
112
 
44
- #### `@mui/x-date-pickers-pro@6.10.0`
113
+ #### `@mui/x-date-pickers-pro@6.10.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link)
45
114
 
46
115
  Same changes as in `@mui/x-date-pickers@6.10.0`.
47
116
 
@@ -70,8 +70,8 @@ const GridPanel = /*#__PURE__*/React.forwardRef((props, ref) => {
70
70
  }], []);
71
71
  const [anchorEl, setAnchorEl] = React.useState(null);
72
72
  React.useEffect(() => {
73
- var _apiRef$current$rootE, _apiRef$current$rootE2;
74
- const columnHeadersElement = (_apiRef$current$rootE = apiRef.current.rootElementRef) == null ? void 0 : (_apiRef$current$rootE2 = _apiRef$current$rootE.current) == null ? void 0 : _apiRef$current$rootE2.querySelector(`.${gridClasses.columnHeaders}`);
73
+ var _apiRef$current$rootE;
74
+ const columnHeadersElement = (_apiRef$current$rootE = apiRef.current.rootElementRef) == null || (_apiRef$current$rootE = _apiRef$current$rootE.current) == null ? void 0 : _apiRef$current$rootE.querySelector(`.${gridClasses.columnHeaders}`);
75
75
  if (columnHeadersElement) {
76
76
  setAnchorEl(columnHeadersElement);
77
77
  }
@@ -217,7 +217,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
217
217
  focus: () => {
218
218
  if (currentOperator != null && currentOperator.InputComponent) {
219
219
  var _valueRef$current;
220
- valueRef == null ? void 0 : (_valueRef$current = valueRef.current) == null ? void 0 : _valueRef$current.focus();
220
+ valueRef == null || (_valueRef$current = valueRef.current) == null ? void 0 : _valueRef$current.focus();
221
221
  } else {
222
222
  filterSelectorRef.current.focus();
223
223
  }
@@ -313,7 +313,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
313
313
  native: isBaseSelectNative,
314
314
  inputRef: filterSelectorRef
315
315
  }, (_rootProps$slotProps8 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps8.baseSelect, {
316
- children: currentColumn == null ? void 0 : (_currentColumn$filter2 = currentColumn.filterOperators) == null ? void 0 : _currentColumn$filter2.map(operator => /*#__PURE__*/_createElement(rootProps.slots.baseSelectOption, _extends({}, baseSelectOptionProps, {
316
+ children: currentColumn == null || (_currentColumn$filter2 = currentColumn.filterOperators) == null ? void 0 : _currentColumn$filter2.map(operator => /*#__PURE__*/_createElement(rootProps.slots.baseSelectOption, _extends({}, baseSelectOptionProps, {
317
317
  native: isBaseSelectNative,
318
318
  key: operator.value,
319
319
  value: operator.value
@@ -43,7 +43,7 @@ const SingleSelectOperatorContainer = styled('div')({
43
43
  }
44
44
  });
45
45
  function GridFilterInputSingleSelect(props) {
46
- var _item$value, _rootProps$slotProps$, _rootProps$slotProps, _rootProps$slotProps$2, _resolvedColumn, _resolvedColumn2, _rootProps$slotProps2, _rootProps$slotProps3, _rootProps$slotProps4;
46
+ var _item$value, _rootProps$slotProps$, _rootProps$slotProps, _resolvedColumn, _resolvedColumn2, _rootProps$slotProps2, _rootProps$slotProps3, _rootProps$slotProps4;
47
47
  const {
48
48
  item,
49
49
  applyValue,
@@ -62,7 +62,7 @@ function GridFilterInputSingleSelect(props) {
62
62
  const id = useId();
63
63
  const labelId = useId();
64
64
  const rootProps = useGridRootProps();
65
- const isSelectNative = (_rootProps$slotProps$ = (_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : (_rootProps$slotProps$2 = _rootProps$slotProps.baseSelect) == null ? void 0 : _rootProps$slotProps$2.native) != null ? _rootProps$slotProps$ : true;
65
+ const isSelectNative = (_rootProps$slotProps$ = (_rootProps$slotProps = rootProps.slotProps) == null || (_rootProps$slotProps = _rootProps$slotProps.baseSelect) == null ? void 0 : _rootProps$slotProps.native) != null ? _rootProps$slotProps$ : true;
66
66
  let resolvedColumn = null;
67
67
  if (item.field) {
68
68
  const column = apiRef.current.getColumn(item.field);
@@ -197,6 +197,13 @@ export const applyInitialState = (columnsState, initialState) => {
197
197
  });
198
198
  return newColumnsState;
199
199
  };
200
+ function getDefaultColTypeDef(columnTypes, type) {
201
+ let colDef = columnTypes[DEFAULT_GRID_COL_TYPE_KEY];
202
+ if (type && columnTypes[type]) {
203
+ colDef = columnTypes[type];
204
+ }
205
+ return colDef;
206
+ }
200
207
  export const createColumnsState = ({
201
208
  apiRef,
202
209
  columnsToUpsert,
@@ -205,7 +212,7 @@ export const createColumnsState = ({
205
212
  columnVisibilityModel = gridColumnVisibilityModelSelector(apiRef),
206
213
  keepOnlyColumnsToUpsert = false
207
214
  }) => {
208
- var _apiRef$current$getRo, _apiRef$current$getRo2, _apiRef$current, _apiRef$current$getRo3;
215
+ var _apiRef$current$getRo, _apiRef$current$getRo2, _apiRef$current;
209
216
  const isInsideStateInitializer = !apiRef.current.state.columns;
210
217
  let columnsState;
211
218
  if (isInsideStateInitializer) {
@@ -238,11 +245,7 @@ export const createColumnsState = ({
238
245
  columnsToKeep[field] = true;
239
246
  let existingState = columnsState.lookup[field];
240
247
  if (existingState == null) {
241
- let colDef = columnTypes[DEFAULT_GRID_COL_TYPE_KEY];
242
- if (newColumn.type && columnTypes[newColumn.type]) {
243
- colDef = columnTypes[newColumn.type];
244
- }
245
- existingState = _extends({}, colDef, {
248
+ existingState = _extends({}, getDefaultColTypeDef(columnTypes, newColumn.type), {
246
249
  field,
247
250
  hasBeenResized: false
248
251
  });
@@ -250,6 +253,13 @@ export const createColumnsState = ({
250
253
  } else if (keepOnlyColumnsToUpsert) {
251
254
  columnsState.orderedFields.push(field);
252
255
  }
256
+
257
+ // If the column type has changed - merge the existing state with the default column type definition
258
+ if (existingState && existingState.type !== newColumn.type) {
259
+ existingState = _extends({}, existingState, getDefaultColTypeDef(columnTypes, newColumn.type), {
260
+ field
261
+ });
262
+ }
253
263
  let hasBeenResized = existingState.hasBeenResized;
254
264
  COLUMNS_DIMENSION_PROPERTIES.forEach(key => {
255
265
  if (newColumn[key] !== undefined) {
@@ -272,7 +282,7 @@ export const createColumnsState = ({
272
282
  }
273
283
  const columnsStateWithPreProcessing = apiRef.current.unstable_applyPipeProcessors('hydrateColumns', columnsState);
274
284
  const columnsStateWithPortableColumns = applyInitialState(columnsStateWithPreProcessing, initialState);
275
- return hydrateColumnsWidth(columnsStateWithPortableColumns, (_apiRef$current$getRo = (_apiRef$current$getRo2 = (_apiRef$current = apiRef.current).getRootDimensions) == null ? void 0 : (_apiRef$current$getRo3 = _apiRef$current$getRo2.call(_apiRef$current)) == null ? void 0 : _apiRef$current$getRo3.viewportInnerSize.width) != null ? _apiRef$current$getRo : 0);
285
+ return hydrateColumnsWidth(columnsStateWithPortableColumns, (_apiRef$current$getRo = (_apiRef$current$getRo2 = (_apiRef$current = apiRef.current).getRootDimensions) == null || (_apiRef$current$getRo2 = _apiRef$current$getRo2.call(_apiRef$current)) == null ? void 0 : _apiRef$current$getRo2.viewportInnerSize.width) != null ? _apiRef$current$getRo : 0);
276
286
  };
277
287
  export const mergeColumnsState = columnsState => state => _extends({}, state, {
278
288
  columns: columnsState
@@ -11,13 +11,13 @@ import { getGridDefaultColumnTypes } from '../../../colDef';
11
11
  import { jsx as _jsx } from "react/jsx-runtime";
12
12
  const defaultColumnTypes = getGridDefaultColumnTypes();
13
13
  export const columnsStateInitializer = (state, props, apiRef) => {
14
- var _props$initialState, _ref, _props$columnVisibili, _props$initialState2, _props$initialState2$;
14
+ var _props$initialState, _ref, _props$columnVisibili, _props$initialState2;
15
15
  const columnsState = createColumnsState({
16
16
  apiRef,
17
17
  columnTypes: defaultColumnTypes,
18
18
  columnsToUpsert: props.columns,
19
19
  initialState: (_props$initialState = props.initialState) == null ? void 0 : _props$initialState.columns,
20
- columnVisibilityModel: (_ref = (_props$columnVisibili = props.columnVisibilityModel) != null ? _props$columnVisibili : (_props$initialState2 = props.initialState) == null ? void 0 : (_props$initialState2$ = _props$initialState2.columns) == null ? void 0 : _props$initialState2$.columnVisibilityModel) != null ? _ref : {},
20
+ columnVisibilityModel: (_ref = (_props$columnVisibili = props.columnVisibilityModel) != null ? _props$columnVisibili : (_props$initialState2 = props.initialState) == null || (_props$initialState2 = _props$initialState2.columns) == null ? void 0 : _props$initialState2.columnVisibilityModel) != null ? _ref : {},
21
21
  keepOnlyColumnsToUpsert: true
22
22
  });
23
23
  return _extends({}, state, {
@@ -160,7 +160,7 @@ export function useGridColumns(apiRef, props) {
160
160
  * PRE-PROCESSING
161
161
  */
162
162
  const stateExportPreProcessing = React.useCallback((prevState, context) => {
163
- var _props$initialState$c, _props$initialState3, _props$initialState3$;
163
+ var _props$initialState$c, _props$initialState3;
164
164
  const columnsStateToExport = {};
165
165
  const columnVisibilityModelToExport = gridColumnVisibilityModelSelector(apiRef);
166
166
  const shouldExportColumnVisibilityModel =
@@ -170,7 +170,7 @@ export function useGridColumns(apiRef, props) {
170
170
  props.columnVisibilityModel != null ||
171
171
  // Always export if the model has been initialized
172
172
  // TODO v6 Do a nullish check instead to export even if the initial model equals "{}"
173
- Object.keys((_props$initialState$c = (_props$initialState3 = props.initialState) == null ? void 0 : (_props$initialState3$ = _props$initialState3.columns) == null ? void 0 : _props$initialState3$.columnVisibilityModel) != null ? _props$initialState$c : {}).length > 0 ||
173
+ Object.keys((_props$initialState$c = (_props$initialState3 = props.initialState) == null || (_props$initialState3 = _props$initialState3.columns) == null ? void 0 : _props$initialState3.columnVisibilityModel) != null ? _props$initialState$c : {}).length > 0 ||
174
174
  // Always export if the model is not empty
175
175
  Object.keys(columnVisibilityModelToExport).length > 0;
176
176
  if (shouldExportColumnVisibilityModel) {
@@ -81,7 +81,7 @@ export function useGridDimensions(apiRef, props) {
81
81
  } else {
82
82
  viewportOuterSize = {
83
83
  width: rootDimensionsRef.current.width,
84
- height: rootDimensionsRef.current.height - totalHeaderHeight
84
+ height: Math.max(rootDimensionsRef.current.height - totalHeaderHeight, 0)
85
85
  };
86
86
  const scrollInformation = hasScroll({
87
87
  content: {
@@ -338,7 +338,7 @@ export const useGridCellEditing = (apiRef, props) => {
338
338
  }
339
339
  });
340
340
  const setCellEditingEditCellValue = React.useCallback(async params => {
341
- var _editingState$id, _editingState$id$fiel;
341
+ var _editingState$id;
342
342
  const {
343
343
  id,
344
344
  field,
@@ -388,7 +388,7 @@ export const useGridCellEditing = (apiRef, props) => {
388
388
  newProps.value = column.preProcessEditCellProps ? editingState[id][field].value : parsedValue;
389
389
  updateOrDeleteFieldState(id, field, newProps);
390
390
  editingState = gridEditRowsStateSelector(apiRef.current.state);
391
- return !((_editingState$id = editingState[id]) != null && (_editingState$id$fiel = _editingState$id[field]) != null && _editingState$id$fiel.error);
391
+ return !((_editingState$id = editingState[id]) != null && (_editingState$id = _editingState$id[field]) != null && _editingState$id.error);
392
392
  }, [apiRef, throwIfNotEditable, throwIfNotInMode, updateOrDeleteFieldState]);
393
393
  const getRowWithUpdatedValuesFromCellEditing = React.useCallback((id, field) => {
394
394
  const column = apiRef.current.getColumn(field);
@@ -432,8 +432,8 @@ export const useGridCellEditing = (apiRef, props) => {
432
432
 
433
433
  Object.entries(cellModesModel).forEach(([id, fields]) => {
434
434
  Object.entries(fields).forEach(([field, params]) => {
435
- var _copyOfPrevCellModes$, _copyOfPrevCellModes$2, _idToIdLookup$id;
436
- const prevMode = ((_copyOfPrevCellModes$ = copyOfPrevCellModes[id]) == null ? void 0 : (_copyOfPrevCellModes$2 = _copyOfPrevCellModes$[field]) == null ? void 0 : _copyOfPrevCellModes$2.mode) || GridCellModes.View;
435
+ var _copyOfPrevCellModes$, _idToIdLookup$id;
436
+ const prevMode = ((_copyOfPrevCellModes$ = copyOfPrevCellModes[id]) == null || (_copyOfPrevCellModes$ = _copyOfPrevCellModes$[field]) == null ? void 0 : _copyOfPrevCellModes$.mode) || GridCellModes.View;
437
437
  const originalId = (_idToIdLookup$id = idToIdLookup[id]) != null ? _idToIdLookup$id : id;
438
438
  if (params.mode === GridCellModes.Edit && prevMode === GridCellModes.View) {
439
439
  updateStateToStartCellEditMode(_extends({
@@ -2,13 +2,11 @@ import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
2
2
  import { buildWarning } from '../../../../utils/warning';
3
3
  function sanitizeCellValue(value, delimiterCharacter) {
4
4
  if (typeof value === 'string') {
5
- const formattedValue = value.replace(/"/g, '""');
6
-
7
5
  // Make sure value containing delimiter or line break won't be split into multiple rows
8
- if ([delimiterCharacter, '\n', '\r'].some(delimiter => formattedValue.includes(delimiter))) {
9
- return `"${formattedValue}"`;
6
+ if ([delimiterCharacter, '\n', '\r', '"'].some(delimiter => value.includes(delimiter))) {
7
+ return `"${value.replace(/"/g, '""')}"`;
10
8
  }
11
- return formattedValue;
9
+ return value;
12
10
  }
13
11
  return value;
14
12
  }
@@ -123,6 +123,7 @@ export const useGridPrintExport = (apiRef, props) => {
123
123
  if (normalizeOptions.bodyClassName) {
124
124
  printDoc.body.classList.add(...normalizeOptions.bodyClassName.split(' '));
125
125
  }
126
+ const stylesheetLoadPromises = [];
126
127
  if (normalizeOptions.copyStyles) {
127
128
  const rootCandidate = gridRootElement.getRootNode();
128
129
  const root = rootCandidate.constructor.name === 'ShadowRoot' ? rootCandidate : doc.current;
@@ -153,6 +154,9 @@ export const useGridPrintExport = (apiRef, props) => {
153
154
  newHeadStyleElements.setAttribute(attr.nodeName, attr.nodeValue || '');
154
155
  }
155
156
  }
157
+ stylesheetLoadPromises.push(new Promise(resolve => {
158
+ newHeadStyleElements.addEventListener('load', () => resolve());
159
+ }));
156
160
  printDoc.head.appendChild(newHeadStyleElements);
157
161
  }
158
162
  }
@@ -160,17 +164,20 @@ export const useGridPrintExport = (apiRef, props) => {
160
164
 
161
165
  // Trigger print
162
166
  if (process.env.NODE_ENV !== 'test') {
163
- printWindow.contentWindow.print();
167
+ // wait for remote stylesheets to load
168
+ Promise.all(stylesheetLoadPromises).then(() => {
169
+ printWindow.contentWindow.print();
170
+ });
164
171
  }
165
172
  }, [apiRef, doc, props.columnHeaderHeight]);
166
173
  const handlePrintWindowAfterPrint = React.useCallback(printWindow => {
167
- var _previousGridState$cu, _previousGridState$cu2;
174
+ var _previousGridState$cu;
168
175
  // Remove the print iframe
169
176
  doc.current.body.removeChild(printWindow);
170
177
 
171
178
  // Revert grid to previous state
172
179
  apiRef.current.restoreState(previousGridState.current || {});
173
- if (!((_previousGridState$cu = previousGridState.current) != null && (_previousGridState$cu2 = _previousGridState$cu.columns) != null && _previousGridState$cu2.columnVisibilityModel)) {
180
+ if (!((_previousGridState$cu = previousGridState.current) != null && (_previousGridState$cu = _previousGridState$cu.columns) != null && _previousGridState$cu.columnVisibilityModel)) {
174
181
  // if the apiRef.current.exportState(); did not exported the column visibility, we update it
175
182
  apiRef.current.setColumnVisibilityModel(previousColumnVisibility.current);
176
183
  }
@@ -21,8 +21,8 @@ export const defaultGetRowsToExport = ({
21
21
  const selectedRows = apiRef.current.getSelectedRows();
22
22
  const bodyRows = filteredSortedRowIds.filter(id => rowTree[id].type !== 'footer');
23
23
  const pinnedRows = gridPinnedRowsSelector(apiRef);
24
- const topPinnedRowsIds = (pinnedRows == null ? void 0 : (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.map(row => row.id)) || [];
25
- const bottomPinnedRowsIds = (pinnedRows == null ? void 0 : (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.map(row => row.id)) || [];
24
+ const topPinnedRowsIds = (pinnedRows == null || (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.map(row => row.id)) || [];
25
+ const bottomPinnedRowsIds = (pinnedRows == null || (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.map(row => row.id)) || [];
26
26
  bodyRows.unshift(...topPinnedRowsIds);
27
27
  bodyRows.push(...bottomPinnedRowsIds);
28
28
  if (selectedRows.size > 0) {
@@ -104,7 +104,7 @@ export const gridFilterActiveItemsSelector = createSelectorMemoized(gridFilterMo
104
104
  return false;
105
105
  }
106
106
  const column = columnLookup[item.field];
107
- if (!(column != null && column.filterOperators) || (column == null ? void 0 : (_column$filterOperato = column.filterOperators) == null ? void 0 : _column$filterOperato.length) === 0) {
107
+ if (!(column != null && column.filterOperators) || (column == null || (_column$filterOperato = column.filterOperators) == null ? void 0 : _column$filterOperato.length) === 0) {
108
108
  return false;
109
109
  }
110
110
  const filterOperator = column.filterOperators.find(operator => operator.value === item.operator);
@@ -118,6 +118,7 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
118
118
  }
119
119
  };
120
120
  };
121
+ let filterItemsApplierId = 1;
121
122
 
122
123
  /**
123
124
  * Generates a method to easily check if a row is matching the current filter model.
@@ -134,16 +135,42 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef)
134
135
  if (appliers.length === 0) {
135
136
  return null;
136
137
  }
137
- return (row, shouldApplyFilter) => {
138
- const resultPerItemId = {};
139
- for (let i = 0; i < appliers.length; i += 1) {
140
- const applier = appliers[i];
141
- if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
142
- resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(getRowId ? getRowId(row) : row.id);
143
- }
144
- }
145
- return resultPerItemId;
146
- };
138
+
139
+ // Original logic:
140
+ // return (row, shouldApplyFilter) => {
141
+ // const resultPerItemId: GridFilterItemResult = {};
142
+ //
143
+ // for (let i = 0; i < appliers.length; i += 1) {
144
+ // const applier = appliers[i];
145
+ // if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
146
+ // resultPerItemId[applier.item.id!] = applier.v7
147
+ // ? applier.fn(row)
148
+ // : applier.fn(getRowId ? getRowId(row) : row.id);
149
+ // }
150
+ // }
151
+ //
152
+ // return resultPerItemId;
153
+ // };
154
+
155
+ // We generate a new function with `eval()` to avoid expensive patterns for JS engines
156
+ // such as a dynamic object assignment, e.g. `{ [dynamicKey]: value }`.
157
+ const filterItemTemplate = `(function filterItem$$(row, shouldApplyFilter) {
158
+ ${appliers.map((applier, i) => `const shouldApply${i} = !shouldApplyFilter || shouldApplyFilter(${JSON.stringify(applier.item.field)});`).join('\n')}
159
+
160
+ const result$$ = {
161
+ ${appliers.map((applier, i) => `${JSON.stringify(String(applier.item.id))}:
162
+ !shouldApply${i} ?
163
+ false :
164
+ ${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(${getRowId ? 'getRowId(row)' : 'row.id'})`},
165
+ `).join('\n')}};
166
+
167
+ return result$$;
168
+ })`;
169
+
170
+ // eslint-disable-next-line no-eval
171
+ const filterItem = eval(filterItemTemplate.replaceAll('$$', String(filterItemsApplierId)));
172
+ filterItemsApplierId += 1;
173
+ return filterItem;
147
174
  };
148
175
 
149
176
  /**
@@ -1,6 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
+ import { defaultMemoize } from 'reselect';
3
4
  import { unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
5
+ import { useLazyRef } from '../../utils/useLazyRef';
4
6
  import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
5
7
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
6
8
  import { useGridLogger } from '../../utils/useGridLogger';
@@ -16,8 +18,8 @@ import { buildAggregatedFilterApplier, sanitizeFilterModel, mergeStateWithFilter
16
18
  import { isDeepEqual } from '../../../utils/utils';
17
19
  import { jsx as _jsx } from "react/jsx-runtime";
18
20
  export const filterStateInitializer = (state, props, apiRef) => {
19
- var _ref, _props$filterModel, _props$initialState, _props$initialState$f;
20
- const filterModel = (_ref = (_props$filterModel = props.filterModel) != null ? _props$filterModel : (_props$initialState = props.initialState) == null ? void 0 : (_props$initialState$f = _props$initialState.filter) == null ? void 0 : _props$initialState$f.filterModel) != null ? _ref : getDefaultGridFilterModel();
21
+ var _ref, _props$filterModel, _props$initialState;
22
+ const filterModel = (_ref = (_props$filterModel = props.filterModel) != null ? _props$filterModel : (_props$initialState = props.initialState) == null || (_props$initialState = _props$initialState.filter) == null ? void 0 : _props$initialState.filterModel) != null ? _ref : getDefaultGridFilterModel();
21
23
  return _extends({}, state, {
22
24
  filter: {
23
25
  filterModel: sanitizeFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef),
@@ -37,6 +39,9 @@ function getVisibleRowsLookupState(apiRef, state) {
37
39
  filteredRowsLookup: state.filter.filteredRowsLookup
38
40
  });
39
41
  }
42
+ function createMemoizedValues() {
43
+ return defaultMemoize(Object.values);
44
+ }
40
45
 
41
46
  /**
42
47
  * @requires useGridColumns (method, event)
@@ -44,7 +49,7 @@ function getVisibleRowsLookupState(apiRef, state) {
44
49
  * @requires useGridRows (event)
45
50
  */
46
51
  export const useGridFilter = (apiRef, props) => {
47
- var _props$initialState3, _props$initialState3$, _props$slotProps2;
52
+ var _props$initialState3, _props$slotProps2;
48
53
  const logger = useGridLogger(apiRef, 'useGridFilter');
49
54
  apiRef.current.registerControlState({
50
55
  stateId: 'filter',
@@ -218,7 +223,7 @@ export const useGridFilter = (apiRef, props) => {
218
223
  * PRE-PROCESSING
219
224
  */
220
225
  const stateExportPreProcessing = React.useCallback((prevState, context) => {
221
- var _props$initialState2, _props$initialState2$;
226
+ var _props$initialState2;
222
227
  const filterModelToExport = gridFilterModelSelector(apiRef);
223
228
  const shouldExportFilterModel =
224
229
  // Always export if the `exportOnlyDirtyModels` property is not activated
@@ -226,7 +231,7 @@ export const useGridFilter = (apiRef, props) => {
226
231
  // Always export if the model is controlled
227
232
  props.filterModel != null ||
228
233
  // Always export if the model has been initialized
229
- ((_props$initialState2 = props.initialState) == null ? void 0 : (_props$initialState2$ = _props$initialState2.filter) == null ? void 0 : _props$initialState2$.filterModel) != null ||
234
+ ((_props$initialState2 = props.initialState) == null || (_props$initialState2 = _props$initialState2.filter) == null ? void 0 : _props$initialState2.filterModel) != null ||
230
235
  // Export if the model is not equal to the default value
231
236
  !isDeepEqual(filterModelToExport, getDefaultGridFilterModel());
232
237
  if (!shouldExportFilterModel) {
@@ -237,7 +242,7 @@ export const useGridFilter = (apiRef, props) => {
237
242
  filterModel: filterModelToExport
238
243
  }
239
244
  });
240
- }, [apiRef, props.filterModel, (_props$initialState3 = props.initialState) == null ? void 0 : (_props$initialState3$ = _props$initialState3.filter) == null ? void 0 : _props$initialState3$.filterModel]);
245
+ }, [apiRef, props.filterModel, (_props$initialState3 = props.initialState) == null || (_props$initialState3 = _props$initialState3.filter) == null ? void 0 : _props$initialState3.filterModel]);
241
246
  const stateRestorePreProcessing = React.useCallback((params, context) => {
242
247
  var _context$stateToResto;
243
248
  const filterModel = (_context$stateToResto = context.stateToRestore.filter) == null ? void 0 : _context$stateToResto.filterModel;
@@ -257,11 +262,10 @@ export const useGridFilter = (apiRef, props) => {
257
262
  }
258
263
  return initialValue;
259
264
  }, [props.slots.filterPanel, (_props$slotProps2 = props.slotProps) == null ? void 0 : _props$slotProps2.filterPanel]);
260
- const dataRowIdToIdLookup = apiRef.current.state.rows.dataRowIdToModelLookup;
261
- const rows = React.useMemo(() => Object.values(dataRowIdToIdLookup), [dataRowIdToIdLookup]);
262
265
  const {
263
266
  getRowId
264
267
  } = props;
268
+ const getRowsRef = useLazyRef(createMemoizedValues);
265
269
  const flatFilteringMethod = React.useCallback(params => {
266
270
  if (props.filterMode !== 'client' || !params.isRowMatchingFilters) {
267
271
  return {
@@ -279,6 +283,7 @@ export const useGridFilter = (apiRef, props) => {
279
283
  passingFilterItems: null,
280
284
  passingQuickFilterValues: null
281
285
  };
286
+ const rows = getRowsRef.current(apiRef.current.state.rows.dataRowIdToModelLookup);
282
287
  for (let i = 0; i < rows.length; i += 1) {
283
288
  const row = rows[i];
284
289
  const id = getRowId ? getRowId(row) : row.id;
@@ -295,7 +300,7 @@ export const useGridFilter = (apiRef, props) => {
295
300
  filteredRowsLookup,
296
301
  filteredDescendantCountLookup: {}
297
302
  };
298
- }, [apiRef, rows, props.filterMode, getRowId]);
303
+ }, [apiRef, props.filterMode, getRowId, getRowsRef]);
299
304
  useGridRegisterPipeProcessor(apiRef, 'columnMenu', addColumnMenuItem);
300
305
  useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
301
306
  useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { unstable_ownerDocument as ownerDocument } from '@mui/utils';
3
+ import { unstable_ownerDocument as ownerDocument, unstable_useEventCallback as useEventcallback } from '@mui/utils';
4
4
  import { gridClasses } from '../../../constants/gridClasses';
5
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
6
6
  import { useGridLogger } from '../../utils/useGridLogger';
@@ -335,6 +335,34 @@ export const useGridFocus = (apiRef, props) => {
335
335
  }));
336
336
  }
337
337
  }, [apiRef]);
338
+ const handlePaginationModelChange = useEventcallback(() => {
339
+ const currentFocusedCell = gridFocusCellSelector(apiRef);
340
+ if (!currentFocusedCell) {
341
+ return;
342
+ }
343
+ const currentPage = getVisibleRows(apiRef, {
344
+ pagination: props.pagination,
345
+ paginationMode: props.paginationMode
346
+ });
347
+ const rowIsInCurrentPage = currentPage.rows.find(row => row.id === currentFocusedCell.id);
348
+ if (rowIsInCurrentPage) {
349
+ return;
350
+ }
351
+ const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
352
+ apiRef.current.setState(state => {
353
+ return _extends({}, state, {
354
+ tabIndex: {
355
+ cell: {
356
+ id: currentPage.rows[0].id,
357
+ field: visibleColumns[0].field
358
+ },
359
+ columnGroupHeader: null,
360
+ columnHeader: null,
361
+ columnHeaderFilter: null
362
+ }
363
+ });
364
+ });
365
+ });
338
366
  const focusApi = {
339
367
  setCellFocus,
340
368
  setColumnHeaderFocus,
@@ -363,4 +391,5 @@ export const useGridFocus = (apiRef, props) => {
363
391
  useGridApiEventHandler(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus);
364
392
  useGridApiEventHandler(apiRef, 'columnGroupHeaderFocus', handleColumnGroupHeaderFocus);
365
393
  useGridApiEventHandler(apiRef, 'rowsSet', handleRowSet);
394
+ useGridApiEventHandler(apiRef, 'paginationModelChange', handlePaginationModelChange);
366
395
  };
@@ -8,8 +8,8 @@ import { gridPaginationModelSelector } from './gridPaginationSelector';
8
8
  import { calculatePinnedRowsHeight } from '../rows/gridRowsUtils';
9
9
  import { getPageCount, noRowCountInServerMode, defaultPageSize, throwIfPageSizeExceedsTheLimit, getDefaultGridPaginationModel, getValidPage } from './gridPaginationUtils';
10
10
  export const paginationStateInitializer = (state, props) => {
11
- var _props$paginationMode, _props$initialState, _props$initialState$p;
12
- const paginationModel = _extends({}, getDefaultGridPaginationModel(props.autoPageSize), (_props$paginationMode = props.paginationModel) != null ? _props$paginationMode : (_props$initialState = props.initialState) == null ? void 0 : (_props$initialState$p = _props$initialState.pagination) == null ? void 0 : _props$initialState$p.paginationModel);
11
+ var _props$paginationMode, _props$initialState;
12
+ const paginationModel = _extends({}, getDefaultGridPaginationModel(props.autoPageSize), (_props$paginationMode = props.paginationModel) != null ? _props$paginationMode : (_props$initialState = props.initialState) == null || (_props$initialState = _props$initialState.pagination) == null ? void 0 : _props$initialState.paginationModel);
13
13
  throwIfPageSizeExceedsTheLimit(paginationModel.pageSize, props.signature);
14
14
  return _extends({}, state, {
15
15
  pagination: {
@@ -42,7 +42,7 @@ const mergeStateWithPaginationModel = (rowCount, signature, paginationModelProp)
42
42
  * @requires useGridDimensions (event) - can be after
43
43
  */
44
44
  export const useGridPagination = (apiRef, props) => {
45
- var _props$initialState3, _props$initialState3$;
45
+ var _props$initialState3;
46
46
  const logger = useGridLogger(apiRef, 'useGridPagination');
47
47
  const visibleTopLevelRowCount = useGridSelector(apiRef, gridFilteredTopLevelRowCountSelector);
48
48
  const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector);
@@ -101,7 +101,7 @@ export const useGridPagination = (apiRef, props) => {
101
101
  * PRE-PROCESSING
102
102
  */
103
103
  const stateExportPreProcessing = React.useCallback((prevState, context) => {
104
- var _props$initialState2, _props$initialState2$;
104
+ var _props$initialState2;
105
105
  const paginationModel = gridPaginationModelSelector(apiRef);
106
106
  const shouldExportPaginationModel =
107
107
  // Always export if the `exportOnlyDirtyModels` property is not activated
@@ -109,7 +109,7 @@ export const useGridPagination = (apiRef, props) => {
109
109
  // Always export if the `paginationModel` is controlled
110
110
  props.paginationModel != null ||
111
111
  // Always export if the `paginationModel` has been initialized
112
- ((_props$initialState2 = props.initialState) == null ? void 0 : (_props$initialState2$ = _props$initialState2.pagination) == null ? void 0 : _props$initialState2$.paginationModel) != null ||
112
+ ((_props$initialState2 = props.initialState) == null || (_props$initialState2 = _props$initialState2.pagination) == null ? void 0 : _props$initialState2.paginationModel) != null ||
113
113
  // Export if `page` or `pageSize` is not equal to the default value
114
114
  paginationModel.page !== 0 && paginationModel.pageSize !== defaultPageSize(props.autoPageSize);
115
115
  if (!shouldExportPaginationModel) {
@@ -120,7 +120,7 @@ export const useGridPagination = (apiRef, props) => {
120
120
  paginationModel
121
121
  })
122
122
  });
123
- }, [apiRef, props.paginationModel, (_props$initialState3 = props.initialState) == null ? void 0 : (_props$initialState3$ = _props$initialState3.pagination) == null ? void 0 : _props$initialState3$.paginationModel, props.autoPageSize]);
123
+ }, [apiRef, props.paginationModel, (_props$initialState3 = props.initialState) == null || (_props$initialState3 = _props$initialState3.pagination) == null ? void 0 : _props$initialState3.paginationModel, props.autoPageSize]);
124
124
  const stateRestorePreProcessing = React.useCallback((params, context) => {
125
125
  var _context$stateToResto, _context$stateToResto2, _props$rowCount2;
126
126
  const paginationModel = (_context$stateToResto = context.stateToRestore.pagination) != null && _context$stateToResto.paginationModel ? _extends({}, getDefaultGridPaginationModel(props.autoPageSize), (_context$stateToResto2 = context.stateToRestore.pagination) == null ? void 0 : _context$stateToResto2.paginationModel) : gridPaginationModelSelector(apiRef);
@@ -31,14 +31,14 @@ export const gridPinnedRowsSelector = createSelectorMemoized(gridAdditionalRowGr
31
31
  var _rawPinnedRows$bottom, _rawPinnedRows$top;
32
32
  const rawPinnedRows = additionalRowGroups == null ? void 0 : additionalRowGroups.pinnedRows;
33
33
  return {
34
- bottom: rawPinnedRows == null ? void 0 : (_rawPinnedRows$bottom = rawPinnedRows.bottom) == null ? void 0 : _rawPinnedRows$bottom.map(rowEntry => {
34
+ bottom: rawPinnedRows == null || (_rawPinnedRows$bottom = rawPinnedRows.bottom) == null ? void 0 : _rawPinnedRows$bottom.map(rowEntry => {
35
35
  var _rowEntry$model;
36
36
  return {
37
37
  id: rowEntry.id,
38
38
  model: (_rowEntry$model = rowEntry.model) != null ? _rowEntry$model : {}
39
39
  };
40
40
  }),
41
- top: rawPinnedRows == null ? void 0 : (_rawPinnedRows$top = rawPinnedRows.top) == null ? void 0 : _rawPinnedRows$top.map(rowEntry => {
41
+ top: rawPinnedRows == null || (_rawPinnedRows$top = rawPinnedRows.top) == null ? void 0 : _rawPinnedRows$top.map(rowEntry => {
42
42
  var _rowEntry$model2;
43
43
  return {
44
44
  id: rowEntry.id,
@@ -53,5 +53,5 @@ export const gridPinnedRowsSelector = createSelectorMemoized(gridAdditionalRowGr
53
53
  */
54
54
  export const gridPinnedRowsCountSelector = createSelector(gridPinnedRowsSelector, pinnedRows => {
55
55
  var _pinnedRows$top, _pinnedRows$bottom;
56
- return ((pinnedRows == null ? void 0 : (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.length) || 0) + ((pinnedRows == null ? void 0 : (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.length) || 0);
56
+ return ((pinnedRows == null || (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.length) || 0) + ((pinnedRows == null || (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.length) || 0);
57
57
  });