@mui/x-data-grid 6.7.0 → 6.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +77 -15
  2. package/components/GridColumnHeaders.d.ts +2 -2
  3. package/components/GridColumnHeaders.js +3 -1
  4. package/components/GridRow.d.ts +2 -2
  5. package/components/GridRow.js +23 -69
  6. package/components/cell/GridCell.d.ts +24 -15
  7. package/components/cell/GridCell.js +422 -45
  8. package/components/cell/index.d.ts +2 -1
  9. package/components/cell/index.js +1 -1
  10. package/components/containers/GridRootStyles.js +30 -16
  11. package/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
  12. package/components/toolbar/GridToolbar.js +2 -2
  13. package/components/virtualization/GridVirtualScroller.js +4 -9
  14. package/components/virtualization/GridVirtualScrollerContent.js +11 -20
  15. package/constants/defaultGridSlotsComponents.js +6 -2
  16. package/hooks/core/useGridApiInitialization.js +4 -1
  17. package/hooks/core/useGridStateInitialization.js +2 -9
  18. package/hooks/features/clipboard/useGridClipboard.js +1 -4
  19. package/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -3
  20. package/hooks/features/editing/useGridCellEditing.js +5 -3
  21. package/hooks/features/editing/useGridRowEditing.js +14 -6
  22. package/hooks/features/filter/gridFilterUtils.d.ts +4 -1
  23. package/hooks/features/filter/gridFilterUtils.js +19 -13
  24. package/hooks/features/filter/useGridFilter.js +2 -1
  25. package/hooks/features/focus/useGridFocus.js +9 -4
  26. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -3
  27. package/hooks/features/rows/useGridParamsApi.d.ts +2 -0
  28. package/hooks/features/rows/useGridParamsApi.js +7 -15
  29. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +8 -816
  30. package/hooks/features/virtualization/useGridVirtualScroller.js +40 -38
  31. package/hooks/utils/index.d.ts +1 -1
  32. package/hooks/utils/index.js +1 -1
  33. package/hooks/utils/useGridSelector.d.ts +3 -1
  34. package/hooks/utils/useGridSelector.js +37 -6
  35. package/hooks/utils/useLazyRef.d.ts +2 -0
  36. package/hooks/utils/useLazyRef.js +9 -0
  37. package/hooks/utils/useOnMount.d.ts +2 -0
  38. package/hooks/utils/useOnMount.js +7 -0
  39. package/index.js +1 -1
  40. package/legacy/components/GridColumnHeaders.js +3 -1
  41. package/legacy/components/GridRow.js +25 -69
  42. package/legacy/components/cell/GridCell.js +425 -46
  43. package/legacy/components/cell/index.js +1 -1
  44. package/legacy/components/containers/GridRootStyles.js +20 -17
  45. package/legacy/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
  46. package/legacy/components/toolbar/GridToolbar.js +2 -2
  47. package/legacy/components/virtualization/GridVirtualScroller.js +4 -7
  48. package/legacy/components/virtualization/GridVirtualScrollerContent.js +10 -17
  49. package/legacy/constants/defaultGridSlotsComponents.js +6 -2
  50. package/legacy/hooks/core/useGridApiInitialization.js +4 -1
  51. package/legacy/hooks/core/useGridStateInitialization.js +2 -7
  52. package/legacy/hooks/features/clipboard/useGridClipboard.js +1 -4
  53. package/legacy/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -3
  54. package/legacy/hooks/features/editing/useGridCellEditing.js +5 -3
  55. package/legacy/hooks/features/editing/useGridRowEditing.js +15 -7
  56. package/legacy/hooks/features/filter/gridFilterUtils.js +23 -19
  57. package/legacy/hooks/features/filter/useGridFilter.js +2 -1
  58. package/legacy/hooks/features/focus/useGridFocus.js +9 -4
  59. package/legacy/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -3
  60. package/legacy/hooks/features/rows/useGridParamsApi.js +23 -15
  61. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +38 -34
  62. package/legacy/hooks/utils/index.js +1 -1
  63. package/legacy/hooks/utils/useGridSelector.js +43 -5
  64. package/legacy/hooks/utils/useLazyRef.js +9 -0
  65. package/legacy/hooks/utils/useOnMount.js +7 -0
  66. package/legacy/index.js +1 -1
  67. package/legacy/locales/elGR.js +70 -79
  68. package/legacy/utils/Store.js +34 -0
  69. package/legacy/utils/doesSupportPreventScroll.js +13 -0
  70. package/legacy/utils/fastMemo.js +5 -0
  71. package/legacy/utils/fastObjectShallowCompare.js +32 -0
  72. package/legacy/utils/keyboardUtils.js +4 -2
  73. package/locales/elGR.js +66 -79
  74. package/models/api/gridCoreApi.d.ts +6 -0
  75. package/models/colDef/gridColDef.d.ts +4 -3
  76. package/models/colDef/gridColType.d.ts +3 -1
  77. package/models/events/gridEventLookup.d.ts +3 -3
  78. package/modern/components/GridColumnHeaders.js +3 -1
  79. package/modern/components/GridRow.js +22 -69
  80. package/modern/components/cell/GridCell.js +421 -45
  81. package/modern/components/cell/index.js +1 -1
  82. package/modern/components/containers/GridRootStyles.js +30 -16
  83. package/modern/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
  84. package/modern/components/toolbar/GridToolbar.js +2 -2
  85. package/modern/components/virtualization/GridVirtualScroller.js +4 -9
  86. package/modern/components/virtualization/GridVirtualScrollerContent.js +10 -20
  87. package/modern/constants/defaultGridSlotsComponents.js +6 -2
  88. package/modern/hooks/core/useGridApiInitialization.js +4 -1
  89. package/modern/hooks/core/useGridStateInitialization.js +2 -9
  90. package/modern/hooks/features/clipboard/useGridClipboard.js +1 -4
  91. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -3
  92. package/modern/hooks/features/editing/useGridCellEditing.js +5 -3
  93. package/modern/hooks/features/editing/useGridRowEditing.js +14 -6
  94. package/modern/hooks/features/filter/gridFilterUtils.js +17 -12
  95. package/modern/hooks/features/filter/useGridFilter.js +2 -1
  96. package/modern/hooks/features/focus/useGridFocus.js +8 -4
  97. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -3
  98. package/modern/hooks/features/rows/useGridParamsApi.js +7 -15
  99. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +40 -38
  100. package/modern/hooks/utils/index.js +1 -1
  101. package/modern/hooks/utils/useGridSelector.js +37 -6
  102. package/modern/hooks/utils/useLazyRef.js +9 -0
  103. package/modern/hooks/utils/useOnMount.js +7 -0
  104. package/modern/index.js +1 -1
  105. package/modern/locales/elGR.js +66 -79
  106. package/modern/utils/Store.js +24 -0
  107. package/modern/utils/doesSupportPreventScroll.js +13 -0
  108. package/modern/utils/fastMemo.js +5 -0
  109. package/modern/utils/fastObjectShallowCompare.js +32 -0
  110. package/modern/utils/keyboardUtils.js +4 -2
  111. package/node/components/GridColumnHeaders.js +4 -2
  112. package/node/components/GridRow.js +22 -69
  113. package/node/components/cell/GridCell.js +424 -47
  114. package/node/components/cell/index.js +17 -10
  115. package/node/components/containers/GridRootStyles.js +30 -16
  116. package/node/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
  117. package/node/components/toolbar/GridToolbar.js +2 -2
  118. package/node/components/virtualization/GridVirtualScroller.js +4 -9
  119. package/node/components/virtualization/GridVirtualScrollerContent.js +10 -20
  120. package/node/constants/defaultGridSlotsComponents.js +4 -1
  121. package/node/hooks/core/useGridApiInitialization.js +4 -1
  122. package/node/hooks/core/useGridStateInitialization.js +2 -9
  123. package/node/hooks/features/clipboard/useGridClipboard.js +1 -4
  124. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +8 -2
  125. package/node/hooks/features/editing/useGridCellEditing.js +5 -3
  126. package/node/hooks/features/editing/useGridRowEditing.js +14 -6
  127. package/node/hooks/features/filter/gridFilterUtils.js +17 -12
  128. package/node/hooks/features/filter/useGridFilter.js +2 -1
  129. package/node/hooks/features/focus/useGridFocus.js +8 -4
  130. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -3
  131. package/node/hooks/features/rows/useGridParamsApi.js +9 -15
  132. package/node/hooks/features/virtualization/useGridVirtualScroller.js +40 -36
  133. package/node/hooks/utils/index.js +14 -10
  134. package/node/hooks/utils/useGridSelector.js +41 -7
  135. package/node/hooks/utils/useLazyRef.js +17 -0
  136. package/node/hooks/utils/useOnMount.js +15 -0
  137. package/node/index.js +1 -1
  138. package/node/locales/elGR.js +66 -79
  139. package/node/utils/Store.js +31 -0
  140. package/node/utils/doesSupportPreventScroll.js +19 -0
  141. package/node/utils/fastMemo.js +13 -0
  142. package/node/utils/fastObjectShallowCompare.js +38 -0
  143. package/node/utils/keyboardUtils.js +4 -2
  144. package/package.json +1 -1
  145. package/utils/Store.d.ts +11 -0
  146. package/utils/Store.js +24 -0
  147. package/utils/doesSupportPreventScroll.d.ts +1 -0
  148. package/utils/doesSupportPreventScroll.js +13 -0
  149. package/utils/fastMemo.d.ts +1 -0
  150. package/utils/fastMemo.js +5 -0
  151. package/utils/fastObjectShallowCompare.d.ts +1 -0
  152. package/utils/fastObjectShallowCompare.js +32 -0
  153. package/utils/keyboardUtils.js +4 -2
@@ -1,6 +1,4 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["className", "style"];
4
2
  import * as React from 'react';
5
3
  import clsx from 'clsx';
6
4
  import { styled } from '@mui/system';
@@ -8,11 +6,10 @@ import { unstable_composeClasses as composeClasses } from '@mui/utils';
8
6
  import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
9
7
  import { getDataGridUtilityClass } from '../../constants/gridClasses';
10
8
  import { jsx as _jsx } from "react/jsx-runtime";
11
- const useUtilityClasses = ownerState => {
9
+ const useUtilityClasses = (props, overflowedContent) => {
12
10
  const {
13
- classes,
14
- overflowedContent
15
- } = ownerState;
11
+ classes
12
+ } = props;
16
13
  const slots = {
17
14
  root: ['virtualScrollerContent', overflowedContent && 'virtualScrollerContent--overflowed']
18
15
  };
@@ -24,21 +21,14 @@ const VirtualScrollerContentRoot = styled('div', {
24
21
  overridesResolver: (props, styles) => styles.virtualScrollerContent
25
22
  })({});
26
23
  const GridVirtualScrollerContent = /*#__PURE__*/React.forwardRef(function GridVirtualScrollerContent(props, ref) {
27
- const {
28
- className,
29
- style
30
- } = props,
31
- other = _objectWithoutPropertiesLoose(props, _excluded);
32
24
  const rootProps = useGridRootProps();
33
- const ownerState = _extends({}, rootProps, {
34
- overflowedContent: !rootProps.autoHeight && style?.minHeight === 'auto'
35
- });
36
- const classes = useUtilityClasses(ownerState);
25
+ const overflowedContent = !rootProps.autoHeight && props.style?.minHeight === 'auto';
26
+ const classes = useUtilityClasses(rootProps, overflowedContent);
37
27
  return /*#__PURE__*/_jsx(VirtualScrollerContentRoot, _extends({
38
- ref: ref,
39
- className: clsx(classes.root, className),
40
- ownerState: ownerState,
41
- style: style
42
- }, other));
28
+ ref: ref
29
+ }, props, {
30
+ ownerState: rootProps,
31
+ className: clsx(classes.root, props.className)
32
+ }));
43
33
  });
44
34
  export { GridVirtualScrollerContent };
@@ -1,11 +1,15 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import { GridCell, GridSkeletonCell, GridColumnsPanel, GridFilterPanel, GridFooter, GridLoadingOverlay, GridNoRowsOverlay, GridPagination, GridPanel, GridPreferencesPanel, GridRow, GridColumnHeaderFilterIconButton } from '../components';
2
+ import { GridSkeletonCell, GridColumnsPanel, GridFilterPanel, GridFooter, GridLoadingOverlay, GridNoRowsOverlay, GridPagination, GridPanel, GridPreferencesPanel, GridRow, GridColumnHeaderFilterIconButton } from '../components';
3
+ import { GridCellV7 } from '../components/cell/GridCell';
3
4
  import { GridColumnHeaders } from '../components/GridColumnHeaders';
4
5
  import { GridColumnMenu } from '../components/menu/columnMenu/GridColumnMenu';
5
6
  import { GridNoResultsOverlay } from '../components/GridNoResultsOverlay';
6
7
  import materialSlots from '../material';
8
+
9
+ // TODO: camelCase these key. It's a private helper now.
10
+ // Remove then need to call `uncapitalizeObjectKeys`.
7
11
  export const DATA_GRID_DEFAULT_SLOTS_COMPONENTS = _extends({}, materialSlots, {
8
- Cell: GridCell,
12
+ Cell: GridCellV7,
9
13
  SkeletonCell: GridSkeletonCell,
10
14
  ColumnHeaderFilterIconButton: GridColumnHeaderFilterIconButton,
11
15
  ColumnMenu: GridColumnMenu,
@@ -1,4 +1,5 @@
1
1
  import * as React from 'react';
2
+ import { Store } from '../../utils/Store';
2
3
  import { useGridApiMethod } from '../utils/useGridApiMethod';
3
4
  import { GridSignature } from '../utils/useGridApiEventHandler';
4
5
  import { EventManager } from '../../utils/EventManager';
@@ -35,8 +36,10 @@ const wrapPublicApi = publicApi => {
35
36
  export function useGridApiInitialization(inputApiRef, props) {
36
37
  const publicApiRef = React.useRef();
37
38
  if (!publicApiRef.current) {
39
+ const state = {};
38
40
  publicApiRef.current = {
39
- state: {},
41
+ state,
42
+ store: Store.create(state),
40
43
  instanceId: {
41
44
  id: globalId
42
45
  }
@@ -1,6 +1,4 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["stateId"];
4
2
  import * as React from 'react';
5
3
  import { GridSignature } from '../utils/useGridApiEventHandler';
6
4
  import { useGridApiMethod } from '../utils';
@@ -9,13 +7,7 @@ export const useGridStateInitialization = (apiRef, props) => {
9
7
  const controlStateMapRef = React.useRef({});
10
8
  const [, rawForceUpdate] = React.useState();
11
9
  const registerControlState = React.useCallback(controlStateItem => {
12
- const {
13
- stateId
14
- } = controlStateItem,
15
- others = _objectWithoutPropertiesLoose(controlStateItem, _excluded);
16
- controlStateMapRef.current[stateId] = _extends({}, others, {
17
- stateId
18
- });
10
+ controlStateMapRef.current[controlStateItem.stateId] = controlStateItem;
19
11
  }, []);
20
12
  const setState = React.useCallback((state, reason) => {
21
13
  let newState;
@@ -60,6 +52,7 @@ export const useGridStateInitialization = (apiRef, props) => {
60
52
  if (apiRef.current.publishEvent) {
61
53
  apiRef.current.publishEvent('stateChange', newState);
62
54
  }
55
+ apiRef.current.store.update(newState);
63
56
  }
64
57
  if (updatedControlStateIds.length === 1) {
65
58
  const {
@@ -53,10 +53,7 @@ export const useGridClipboard = (apiRef, props) => {
53
53
  const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp?.clipboardExport : ignoreValueFormatterProp) || false;
54
54
  const clipboardCopyCellDelimiter = props.clipboardCopyCellDelimiter;
55
55
  const handleCopy = React.useCallback(event => {
56
- const isModifierKeyPressed = event.ctrlKey || event.metaKey;
57
- // event.code === 'KeyC' is not enough as event.code assume a QWERTY keyboard layout which would
58
- // be wrong with a Dvorak keyboard (as if pressing J).
59
- if (String.fromCharCode(event.keyCode) !== 'C' || !isModifierKeyPressed) {
56
+ if (!((event.ctrlKey || event.metaKey) && event.key === 'c')) {
60
57
  return;
61
58
  }
62
59
 
@@ -10,7 +10,7 @@ import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
10
10
  import { GridColumnHeaderItem } from '../../../components/columnHeaders/GridColumnHeaderItem';
11
11
  import { getFirstColumnIndexToRender, getTotalHeaderHeight } from '../columns/gridColumnsUtils';
12
12
  import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
13
- import { getRenderableIndexes } from '../virtualization/useGridVirtualScroller';
13
+ import { areRenderContextsEqual, getRenderableIndexes } from '../virtualization/useGridVirtualScroller';
14
14
  import { GridColumnGroupHeader } from '../../../components/columnHeaders/GridColumnGroupHeader';
15
15
  import { jsx as _jsx } from "react/jsx-runtime";
16
16
  const GridColumnHeaderRow = styled('div', {
@@ -49,12 +49,18 @@ export const useGridColumnHeaders = props => {
49
49
  const rootProps = useGridRootProps();
50
50
  const innerRef = React.useRef(null);
51
51
  const handleInnerRef = useForkRef(innerRefProp, innerRef);
52
- const [renderContext, setRenderContext] = React.useState(null);
52
+ const [renderContext, setRenderContextRaw] = React.useState(null);
53
53
  const prevRenderContext = React.useRef(renderContext);
54
54
  const prevScrollLeft = React.useRef(0);
55
55
  const currentPage = useGridVisibleRows(apiRef, rootProps);
56
56
  const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps.columnHeaderHeight);
57
57
  const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
58
+ const setRenderContext = React.useCallback(nextRenderContext => {
59
+ if (renderContext && nextRenderContext && areRenderContextsEqual(renderContext, nextRenderContext)) {
60
+ return;
61
+ }
62
+ setRenderContextRaw(nextRenderContext);
63
+ }, [renderContext]);
58
64
  React.useEffect(() => {
59
65
  apiRef.current.columnHeadersContainerElementRef.current.scrollLeft = 0;
60
66
  }, [apiRef]);
@@ -129,7 +135,7 @@ export const useGridColumnHeaders = props => {
129
135
  if (nextRenderContext && canUpdateInnerPosition) {
130
136
  updateInnerPosition(nextRenderContext);
131
137
  }
132
- }, [updateInnerPosition]);
138
+ }, [updateInnerPosition, setRenderContext]);
133
139
  const handleColumnResizeStart = React.useCallback(params => setResizeCol(params.field), []);
134
140
  const handleColumnResizeStop = React.useCallback(() => setResizeCol(''), []);
135
141
  const handleColumnReorderStart = React.useCallback(params => setDragCol(params.field), []);
@@ -14,7 +14,7 @@ import { buildWarning } from '../../../utils/warning';
14
14
  import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
15
15
  import { deepClone } from '../../../utils/utils';
16
16
  import { GridCellEditStartReasons, GridCellEditStopReasons } from '../../../models/params/gridEditCellParams';
17
- const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#persistence.'], 'error');
17
+ const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#server-side-persistence.'], 'error');
18
18
  export const useGridCellEditing = (apiRef, props) => {
19
19
  const [cellModesModel, setCellModesModel] = React.useState({});
20
20
  const cellModesModelRef = React.useRef(cellModesModel);
@@ -122,7 +122,8 @@ export const useGridCellEditing = (apiRef, props) => {
122
122
  id,
123
123
  field,
124
124
  reason,
125
- key
125
+ key,
126
+ colDef
126
127
  } = params;
127
128
  const startCellEditModeParams = {
128
129
  id,
@@ -134,7 +135,8 @@ export const useGridCellEditing = (apiRef, props) => {
134
135
  // The sequence of events makes the key pressed by the end-users update the textbox directly.
135
136
  startCellEditModeParams.deleteValue = true;
136
137
  } else {
137
- startCellEditModeParams.initialValue = key;
138
+ const initialValue = colDef.valueParser ? colDef.valueParser(key) : key;
139
+ startCellEditModeParams.initialValue = initialValue;
138
140
  }
139
141
  } else if (reason === GridCellEditStartReasons.deleteKeyDown) {
140
142
  startCellEditModeParams.deleteValue = true;
@@ -15,7 +15,8 @@ import { buildWarning } from '../../../utils/warning';
15
15
  import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
16
16
  import { deepClone } from '../../../utils/utils';
17
17
  import { GridRowEditStopReasons, GridRowEditStartReasons } from '../../../models/params/gridRowParams';
18
- const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#persistence.'], 'error');
18
+ import { GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
19
+ const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see http://mui.com/components/data-grid/editing/#server-side-persistence.'], 'error');
19
20
  export const useGridRowEditing = (apiRef, props) => {
20
21
  const [rowModesModel, setRowModesModel] = React.useState({});
21
22
  const rowModesModelRef = React.useRef(rowModesModel);
@@ -113,7 +114,13 @@ export const useGridRowEditing = (apiRef, props) => {
113
114
  } else if (event.key === 'Enter') {
114
115
  reason = GridRowEditStopReasons.enterKeyDown;
115
116
  } else if (event.key === 'Tab') {
116
- const columnFields = gridColumnFieldsSelector(apiRef).filter(field => apiRef.current.isCellEditable(apiRef.current.getCellParams(params.id, field)));
117
+ const columnFields = gridColumnFieldsSelector(apiRef).filter(field => {
118
+ const column = apiRef.current.getColumn(field);
119
+ if (column.type === GRID_ACTIONS_COLUMN_TYPE) {
120
+ return true;
121
+ }
122
+ return apiRef.current.isCellEditable(apiRef.current.getCellParams(params.id, field));
123
+ });
117
124
  if (event.shiftKey) {
118
125
  if (params.field === columnFields[0]) {
119
126
  // Exit if user pressed Shift+Tab on the first field
@@ -134,8 +141,7 @@ export const useGridRowEditing = (apiRef, props) => {
134
141
  }
135
142
  }
136
143
  if (reason) {
137
- const rowParams = apiRef.current.getRowParams(params.id);
138
- const newParams = _extends({}, rowParams, {
144
+ const newParams = _extends({}, apiRef.current.getRowParams(params.id), {
139
145
  reason,
140
146
  field: params.field
141
147
  });
@@ -177,7 +183,8 @@ export const useGridRowEditing = (apiRef, props) => {
177
183
  id,
178
184
  field,
179
185
  reason,
180
- key
186
+ key,
187
+ columns
181
188
  } = params;
182
189
  const startRowEditModeParams = {
183
190
  id,
@@ -189,7 +196,8 @@ export const useGridRowEditing = (apiRef, props) => {
189
196
  // The sequence of events makes the key pressed by the end-users update the textbox directly.
190
197
  startRowEditModeParams.deleteValue = !!field;
191
198
  } else {
192
- startRowEditModeParams.initialValue = key;
199
+ const colDef = columns.find(col => col.field === field);
200
+ startRowEditModeParams.initialValue = colDef.valueParser ? colDef.valueParser(key) : key;
193
201
  }
194
202
  } else if (reason === GridRowEditStartReasons.deleteKeyDown) {
195
203
  startRowEditModeParams.deleteValue = !!field;
@@ -181,21 +181,25 @@ export const buildAggregatedFilterApplier = (filterModel, apiRef) => {
181
181
  passingQuickFilterValues: isRowMatchingQuickFilter && isRowMatchingQuickFilter(rowId, shouldApplyFilter)
182
182
  });
183
183
  };
184
- export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel, apiRef) => {
185
- const cleanedFilterItems = filterModel.items.filter(item => getFilterCallbackFromItem(item, apiRef) !== null);
186
- const cleanedAllFilterItemResults = allFilterItemResults.filter(result => result != null);
187
- const cleanedAllQuickFilterResults = allQuickFilterResults.filter(result => result != null);
188
-
189
- // Defaultize operators
190
- const quickFilterLogicOperator = filterModel.quickFilterLogicOperator ?? getDefaultGridFilterModel().quickFilterLogicOperator;
191
- const logicOperator = filterModel.logicOperator ?? getDefaultGridFilterModel().logicOperator;
184
+ const isNotNull = result => result != null;
185
+ const filterModelItems = (cache, apiRef, items) => {
186
+ if (!cache.cleanedFilterItems) {
187
+ cache.cleanedFilterItems = items.filter(item => getFilterCallbackFromItem(item, apiRef) !== null);
188
+ }
189
+ return cache.cleanedFilterItems;
190
+ };
191
+ export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel, apiRef, cache) => {
192
+ const cleanedFilterItems = filterModelItems(cache, apiRef, filterModel.items);
193
+ const cleanedFilterItemResults = allFilterItemResults.filter(isNotNull);
194
+ const cleanedQuickFilterResults = allQuickFilterResults.filter(isNotNull);
192
195
 
193
196
  // get result for filter items model
194
- if (cleanedAllFilterItemResults.length > 0) {
197
+ if (cleanedFilterItemResults.length > 0) {
195
198
  // Return true if the item pass with one of the rows
196
199
  const filterItemPredicate = item => {
197
- return cleanedAllFilterItemResults.some(filterItemResult => filterItemResult[item.id]);
200
+ return cleanedFilterItemResults.some(filterItemResult => filterItemResult[item.id]);
198
201
  };
202
+ const logicOperator = filterModel.logicOperator ?? getDefaultGridFilterModel().logicOperator;
199
203
  if (logicOperator === GridLogicOperator.And) {
200
204
  const passesAllFilters = cleanedFilterItems.every(filterItemPredicate);
201
205
  if (!passesAllFilters) {
@@ -210,11 +214,12 @@ export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, fil
210
214
  }
211
215
 
212
216
  // get result for quick filter model
213
- if (cleanedAllQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
217
+ if (cleanedQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
214
218
  // Return true if the item pass with one of the rows
215
219
  const quickFilterValuePredicate = value => {
216
- return cleanedAllQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
220
+ return cleanedQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
217
221
  };
222
+ const quickFilterLogicOperator = filterModel.quickFilterLogicOperator ?? getDefaultGridFilterModel().quickFilterLogicOperator;
218
223
  if (quickFilterLogicOperator === GridLogicOperator.And) {
219
224
  const passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate);
220
225
  if (!passesAllQuickFilterValues) {
@@ -255,6 +255,7 @@ export const useGridFilter = (apiRef, props) => {
255
255
  const tree = gridRowTreeSelector(apiRef);
256
256
  const rowIds = tree[GRID_ROOT_GROUP_ID].children;
257
257
  const filteredRowsLookup = {};
258
+ const filterCache = {};
258
259
  for (let i = 0; i < rowIds.length; i += 1) {
259
260
  const rowId = rowIds[i];
260
261
  let isRowPassing;
@@ -265,7 +266,7 @@ export const useGridFilter = (apiRef, props) => {
265
266
  passingFilterItems,
266
267
  passingQuickFilterValues
267
268
  } = params.isRowMatchingFilters(rowId);
268
- isRowPassing = passFilterLogic([passingFilterItems], [passingQuickFilterValues], params.filterModel, apiRef);
269
+ isRowPassing = passFilterLogic([passingFilterItems], [passingQuickFilterValues], params.filterModel, apiRef, filterCache);
269
270
  }
270
271
  filteredRowsLookup[rowId] = isRowPassing;
271
272
  }
@@ -1,6 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { unstable_ownerDocument as ownerDocument } from '@mui/utils';
4
+ import { gridClasses } from '../../../constants/gridClasses';
4
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
5
6
  import { useGridLogger } from '../../utils/useGridLogger';
6
7
  import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
@@ -236,7 +237,6 @@ export const useGridFocus = (apiRef, props) => {
236
237
  }
237
238
  apiRef.current.setColumnHeaderFocus(field, event);
238
239
  }, [apiRef]);
239
- const focussedColumnGroup = unstable_gridFocusColumnGroupHeaderSelector(apiRef);
240
240
  const handleColumnGroupHeaderFocus = React.useCallback(({
241
241
  fields,
242
242
  depth
@@ -244,13 +244,17 @@ export const useGridFocus = (apiRef, props) => {
244
244
  if (event.target !== event.currentTarget) {
245
245
  return;
246
246
  }
247
- if (focussedColumnGroup !== null && focussedColumnGroup.depth === depth && fields.includes(focussedColumnGroup.field)) {
247
+ const focusedColumnGroup = unstable_gridFocusColumnGroupHeaderSelector(apiRef);
248
+ if (focusedColumnGroup !== null && focusedColumnGroup.depth === depth && fields.includes(focusedColumnGroup.field)) {
248
249
  // This group cell has already been focused
249
250
  return;
250
251
  }
251
252
  apiRef.current.setColumnGroupHeaderFocus(fields[0], depth, event);
252
- }, [apiRef, focussedColumnGroup]);
253
- const handleBlur = React.useCallback(() => {
253
+ }, [apiRef]);
254
+ const handleBlur = React.useCallback((_, event) => {
255
+ if (event.relatedTarget?.className.includes(gridClasses.columnHeader)) {
256
+ return;
257
+ }
254
258
  logger.debug(`Clearing focus`);
255
259
  apiRef.current.setState(state => _extends({}, state, {
256
260
  focus: {
@@ -13,7 +13,6 @@ import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from '../../../constants/gridDetailPan
13
13
  import { gridPinnedRowsSelector } from '../rows/gridRowsSelector';
14
14
  import { unstable_gridFocusColumnGroupHeaderSelector } from '../focus';
15
15
  import { gridColumnGroupsHeaderMaxDepthSelector } from '../columnGrouping/gridColumnGroupsSelector';
16
- import { useGridSelector } from '../../utils/useGridSelector';
17
16
  import { unstable_gridHeaderFilteringEditFieldSelector, unstable_gridHeaderFilteringMenuSelector } from '../headerFiltering/gridHeaderFilteringSelectors';
18
17
  import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
19
18
  function enrichPageRowsWithPinnedRows(apiRef, rows) {
@@ -322,12 +321,12 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
322
321
  event.preventDefault();
323
322
  }
324
323
  }, [apiRef, currentPageRows.length, goToHeaderFilter, theme.direction, goToHeader, goToCell, getRowIdFromIndex]);
325
- const focusedColumnGroup = useGridSelector(apiRef, unstable_gridFocusColumnGroupHeaderSelector);
326
324
  const handleColumnGroupHeaderKeyDown = React.useCallback((params, event) => {
327
325
  const dimensions = apiRef.current.getRootDimensions();
328
326
  if (!dimensions) {
329
327
  return;
330
328
  }
329
+ const focusedColumnGroup = unstable_gridFocusColumnGroupHeaderSelector(apiRef);
331
330
  if (focusedColumnGroup === null) {
332
331
  return;
333
332
  }
@@ -411,7 +410,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
411
410
  if (shouldPreventDefault) {
412
411
  event.preventDefault();
413
412
  }
414
- }, [apiRef, focusedColumnGroup, currentPageRows.length, goToHeader, goToGroupHeader, goToCell, getRowIdFromIndex]);
413
+ }, [apiRef, currentPageRows.length, goToHeader, goToGroupHeader, goToCell, getRowIdFromIndex]);
415
414
  const handleCellKeyDown = React.useCallback((params, event) => {
416
415
  // Ignore portal
417
416
  if (!event.currentTarget.contains(event.target)) {
@@ -2,11 +2,7 @@ import * as React from 'react';
2
2
  import { getGridCellElement, getGridColumnHeaderElement, getGridRowElement } from '../../../utils/domUtils';
3
3
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
4
4
  import { gridFocusCellSelector, gridTabIndexCellSelector } from '../focus/gridFocusStateSelector';
5
- let warnedOnceMissingColumn = false;
6
- function warnMissingColumn(field) {
7
- console.warn([`MUI: You are calling getValue('${field}') but the column \`${field}\` is not defined.`, `Instead, you can access the data from \`params.row.${field}\`.`].join('\n'));
8
- warnedOnceMissingColumn = true;
9
- }
5
+ export class MissingRowIdError extends Error {}
10
6
 
11
7
  /**
12
8
  * @requires useGridColumns (method)
@@ -24,7 +20,7 @@ export function useGridParamsApi(apiRef) {
24
20
  const getRowParams = React.useCallback(id => {
25
21
  const row = apiRef.current.getRow(id);
26
22
  if (!row) {
27
- throw new Error(`No row with id #${id} found`);
23
+ throw new MissingRowIdError(`No row with id #${id} found`);
28
24
  }
29
25
  const params = {
30
26
  id,
@@ -37,7 +33,7 @@ export function useGridParamsApi(apiRef) {
37
33
  const row = apiRef.current.getRow(id);
38
34
  const rowNode = apiRef.current.getRowNode(id);
39
35
  if (!row || !rowNode) {
40
- throw new Error(`No row with id #${id} found`);
36
+ throw new MissingRowIdError(`No row with id #${id} found`);
41
37
  }
42
38
  const cellFocus = gridFocusCellSelector(apiRef);
43
39
  const cellTabIndex = gridTabIndexCellSelector(apiRef);
@@ -61,7 +57,7 @@ export function useGridParamsApi(apiRef) {
61
57
  const row = apiRef.current.getRow(id);
62
58
  const rowNode = apiRef.current.getRowNode(id);
63
59
  if (!row || !rowNode) {
64
- throw new Error(`No row with id #${id} found`);
60
+ throw new MissingRowIdError(`No row with id #${id} found`);
65
61
  }
66
62
  const cellFocus = gridFocusCellSelector(apiRef);
67
63
  const cellTabIndex = gridTabIndexCellSelector(apiRef);
@@ -75,7 +71,8 @@ export function useGridParamsApi(apiRef) {
75
71
  hasFocus: cellFocus !== null && cellFocus.field === field && cellFocus.id === id,
76
72
  tabIndex: cellTabIndex && cellTabIndex.field === field && cellTabIndex.id === id ? 0 : -1,
77
73
  value,
78
- formattedValue: value
74
+ formattedValue: value,
75
+ isEditable: false
79
76
  };
80
77
  if (colDef && colDef.valueFormatter) {
81
78
  params.formattedValue = colDef.valueFormatter({
@@ -90,15 +87,10 @@ export function useGridParamsApi(apiRef) {
90
87
  }, [apiRef]);
91
88
  const getCellValue = React.useCallback((id, field) => {
92
89
  const colDef = apiRef.current.getColumn(field);
93
- if (process.env.NODE_ENV !== 'production') {
94
- if (!colDef && !warnedOnceMissingColumn) {
95
- warnMissingColumn(field);
96
- }
97
- }
98
90
  if (!colDef || !colDef.valueGetter) {
99
91
  const rowModel = apiRef.current.getRow(id);
100
92
  if (!rowModel) {
101
- throw new Error(`No row with id #${id} found`);
93
+ throw new MissingRowIdError(`No row with id #${id} found`);
102
94
  }
103
95
  return rowModel[field];
104
96
  }
@@ -1,11 +1,10 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
3
  const _excluded = ["style"],
4
- _excluded2 = ["style"],
5
- _excluded3 = ["style"];
4
+ _excluded2 = ["style"];
6
5
  import * as React from 'react';
7
6
  import * as ReactDOM from 'react-dom';
8
- import { unstable_useForkRef as useForkRef, unstable_useEnhancedEffect as useEnhancedEffect } from '@mui/utils';
7
+ import { unstable_useForkRef as useForkRef, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
9
8
  import { useTheme } from '@mui/material/styles';
10
9
  import { defaultMemoize } from 'reselect';
11
10
  import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
@@ -50,12 +49,17 @@ export const getRenderableIndexes = ({
50
49
  }) => {
51
50
  return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
52
51
  };
53
- const areRenderContextsEqual = (context1, context2) => {
52
+ export const areRenderContextsEqual = (context1, context2) => {
54
53
  if (context1 === context2) {
55
54
  return true;
56
55
  }
57
56
  return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
58
57
  };
58
+ // The `maxSize` is 3 so that reselect caches the `renderedColumns` values for the pinned left,
59
+ // unpinned, and pinned right sections.
60
+ const MEMOIZE_OPTIONS = {
61
+ maxSize: 3
62
+ };
59
63
  export const useGridVirtualScroller = props => {
60
64
  const apiRef = useGridPrivateApiContext();
61
65
  const rootProps = useGridRootProps();
@@ -95,7 +99,7 @@ export const useGridVirtualScroller = props => {
95
99
  const prevRootRowStyle = React.useRef();
96
100
  const getRenderedColumnsRef = React.useRef(defaultMemoize((columns, firstColumnToRender, lastColumnToRender) => {
97
101
  return columns.slice(firstColumnToRender, lastColumnToRender);
98
- }));
102
+ }, MEMOIZE_OPTIONS));
99
103
  const getNearestIndexToRender = React.useCallback(offset => {
100
104
  const lastMeasuredIndexRelativeToAllRows = apiRef.current.getLastMeasuredRowIndex();
101
105
  let allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
@@ -253,7 +257,7 @@ export const useGridVirtualScroller = props => {
253
257
  };
254
258
  apiRef.current.publishEvent('scrollPositionChange', params);
255
259
  }, [apiRef, computeRenderContext, containerDimensions.width, updateRenderContext]);
256
- const handleScroll = event => {
260
+ const handleScroll = useEventCallback(event => {
257
261
  const {
258
262
  scrollTop,
259
263
  scrollLeft
@@ -295,13 +299,13 @@ export const useGridVirtualScroller = props => {
295
299
  });
296
300
  prevTotalWidth.current = columnsTotalWidth;
297
301
  }
298
- };
299
- const handleWheel = event => {
302
+ });
303
+ const handleWheel = useEventCallback(event => {
300
304
  apiRef.current.publishEvent('virtualScrollerWheel', {}, event);
301
- };
302
- const handleTouchMove = event => {
305
+ });
306
+ const handleTouchMove = useEventCallback(event => {
303
307
  apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
304
- };
308
+ });
305
309
  const getRows = (params = {
306
310
  renderContext
307
311
  }) => {
@@ -446,22 +450,25 @@ export const useGridVirtualScroller = props => {
446
450
  height,
447
451
  minHeight: shouldExtendContent ? '100%' : 'auto'
448
452
  };
453
+ if (rootProps.autoHeight && currentPage.rows.length === 0) {
454
+ size.height = getMinimalContentHeight(apiRef, rootProps.rowHeight); // Give room to show the overlay when there no rows.
455
+ }
456
+
449
457
  return size;
450
- }, [rootRef, columnsTotalWidth, rowsMeta.currentPageTotalHeight, needsHorizontalScrollbar]);
458
+ }, [apiRef, rootRef, columnsTotalWidth, rowsMeta.currentPageTotalHeight, needsHorizontalScrollbar, rootProps.autoHeight, rootProps.rowHeight, currentPage.rows.length]);
451
459
  React.useEffect(() => {
452
460
  apiRef.current.publishEvent('virtualScrollerContentSizeChange');
453
461
  }, [apiRef, contentSize]);
454
- if (rootProps.autoHeight && currentPage.rows.length === 0) {
455
- contentSize.height = getMinimalContentHeight(apiRef, rootProps.rowHeight); // Give room to show the overlay when there no rows.
456
- }
457
-
458
- const rootStyle = {};
459
- if (!needsHorizontalScrollbar) {
460
- rootStyle.overflowX = 'hidden';
461
- }
462
- if (rootProps.autoHeight) {
463
- rootStyle.overflowY = 'hidden';
464
- }
462
+ const rootStyle = React.useMemo(() => {
463
+ const style = {};
464
+ if (!needsHorizontalScrollbar) {
465
+ style.overflowX = 'hidden';
466
+ }
467
+ if (rootProps.autoHeight) {
468
+ style.overflowY = 'hidden';
469
+ }
470
+ return style;
471
+ }, [needsHorizontalScrollbar, rootProps.autoHeight]);
465
472
  const getRenderContext = React.useCallback(() => {
466
473
  return prevRenderContext.current;
467
474
  }, []);
@@ -472,23 +479,18 @@ export const useGridVirtualScroller = props => {
472
479
  renderContext,
473
480
  updateRenderZonePosition,
474
481
  getRows,
475
- getRootProps: (_ref3 = {}) => {
476
- let {
477
- style = {}
478
- } = _ref3,
479
- other = _objectWithoutPropertiesLoose(_ref3, _excluded3);
480
- return _extends({
481
- ref: handleRef,
482
- onScroll: handleScroll,
483
- onWheel: handleWheel,
484
- onTouchMove: handleTouchMove,
485
- style: _extends({}, style, rootStyle)
486
- }, other);
487
- },
482
+ getRootProps: (inputProps = {}) => _extends({
483
+ ref: handleRef,
484
+ onScroll: handleScroll,
485
+ onWheel: handleWheel,
486
+ onTouchMove: handleTouchMove
487
+ }, inputProps, {
488
+ style: inputProps.style ? _extends({}, inputProps.style, rootStyle) : rootStyle
489
+ }),
488
490
  getContentProps: ({
489
- style = {}
491
+ style
490
492
  } = {}) => ({
491
- style: _extends({}, style, contentSize)
493
+ style: style ? _extends({}, style, contentSize) : contentSize
492
494
  }),
493
495
  getRenderZoneProps: () => ({
494
496
  ref: renderZoneRef
@@ -1,6 +1,6 @@
1
1
  export * from './useGridApiEventHandler';
2
2
  export * from './useGridApiMethod';
3
3
  export * from './useGridLogger';
4
- export * from './useGridSelector';
4
+ export { useGridSelector } from './useGridSelector';
5
5
  export * from './useGridNativeEventListener';
6
6
  export * from './useFirstRender';