@mui/x-data-grid 7.1.1 → 7.3.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 (145) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/DataGrid/DataGrid.js +19 -0
  3. package/components/GridPagination.d.ts +4 -1
  4. package/components/GridPagination.js +60 -9
  5. package/components/GridRow.js +4 -1
  6. package/components/GridScrollArea.js +1 -1
  7. package/components/cell/GridCell.d.ts +1 -0
  8. package/components/cell/GridCell.js +4 -2
  9. package/components/columnHeaders/GridColumnGroupHeader.d.ts +1 -0
  10. package/components/columnHeaders/GridColumnGroupHeader.js +3 -2
  11. package/components/columnHeaders/GridColumnHeaderItem.d.ts +2 -0
  12. package/components/columnHeaders/GridColumnHeaderItem.js +9 -4
  13. package/components/containers/GridRootStyles.js +8 -4
  14. package/components/index.d.ts +1 -1
  15. package/components/index.js +1 -1
  16. package/components/panel/GridPanel.js +3 -1
  17. package/components/panel/filterPanel/GridFilterInputDate.js +5 -1
  18. package/constants/gridClasses.d.ts +11 -2
  19. package/constants/gridClasses.js +1 -1
  20. package/hooks/core/useGridInitialization.js +1 -1
  21. package/hooks/core/useGridStateInitialization.d.ts +1 -2
  22. package/hooks/core/useGridStateInitialization.js +6 -10
  23. package/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -5
  24. package/hooks/features/columnResize/useGridColumnResize.js +75 -61
  25. package/hooks/features/columns/gridColumnsUtils.d.ts +2 -1
  26. package/hooks/features/columns/gridColumnsUtils.js +4 -3
  27. package/hooks/features/density/useGridDensity.d.ts +1 -1
  28. package/hooks/features/density/useGridDensity.js +30 -4
  29. package/hooks/features/dimensions/gridDimensionsApi.d.ts +5 -1
  30. package/hooks/features/dimensions/useGridDimensions.d.ts +1 -1
  31. package/hooks/features/dimensions/useGridDimensions.js +5 -2
  32. package/hooks/features/editing/useGridCellEditing.js +17 -2
  33. package/hooks/features/editing/useGridRowEditing.js +3 -1
  34. package/hooks/features/export/serializers/csvSerializer.js +6 -5
  35. package/hooks/features/export/useGridPrintExport.d.ts +1 -1
  36. package/hooks/features/export/useGridPrintExport.js +2 -2
  37. package/hooks/features/headerFiltering/useGridHeaderFiltering.d.ts +2 -2
  38. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +2 -2
  39. package/hooks/features/pagination/gridPaginationInterfaces.d.ts +14 -2
  40. package/hooks/features/pagination/gridPaginationSelector.d.ts +5 -0
  41. package/hooks/features/pagination/gridPaginationSelector.js +7 -1
  42. package/hooks/features/pagination/gridPaginationUtils.d.ts +1 -2
  43. package/hooks/features/pagination/gridPaginationUtils.js +5 -3
  44. package/hooks/features/pagination/useGridPagination.d.ts +1 -1
  45. package/hooks/features/pagination/useGridPagination.js +5 -1
  46. package/hooks/features/pagination/useGridPaginationMeta.d.ts +4 -0
  47. package/hooks/features/pagination/useGridPaginationMeta.js +77 -0
  48. package/hooks/features/pagination/useGridPaginationModel.js +2 -1
  49. package/hooks/features/pagination/useGridRowCount.d.ts +0 -4
  50. package/hooks/features/pagination/useGridRowCount.js +32 -18
  51. package/hooks/utils/useGridSelector.d.ts +1 -1
  52. package/index.js +1 -1
  53. package/internals/index.d.ts +1 -1
  54. package/internals/utils/propValidation.js +1 -1
  55. package/locales/daDK.js +3 -4
  56. package/locales/deDE.js +3 -4
  57. package/locales/frFR.js +5 -6
  58. package/locales/svSE.js +3 -4
  59. package/models/api/gridApiCommon.d.ts +1 -1
  60. package/models/api/gridCallbackDetails.d.ts +5 -0
  61. package/models/api/gridLocaleTextApi.d.ts +7 -3
  62. package/models/api/index.d.ts +1 -1
  63. package/models/api/index.js +0 -1
  64. package/models/events/gridEventLookup.d.ts +7 -1
  65. package/models/gridPaginationProps.d.ts +3 -0
  66. package/models/props/DataGridProps.d.ts +26 -8
  67. package/modern/DataGrid/DataGrid.js +19 -0
  68. package/modern/components/GridPagination.js +60 -9
  69. package/modern/components/GridRow.js +4 -1
  70. package/modern/components/GridScrollArea.js +1 -1
  71. package/modern/components/cell/GridCell.js +4 -2
  72. package/modern/components/columnHeaders/GridColumnGroupHeader.js +3 -2
  73. package/modern/components/columnHeaders/GridColumnHeaderItem.js +9 -4
  74. package/modern/components/containers/GridRootStyles.js +8 -4
  75. package/modern/components/index.js +1 -1
  76. package/modern/components/panel/GridPanel.js +3 -1
  77. package/modern/components/panel/filterPanel/GridFilterInputDate.js +5 -1
  78. package/modern/constants/gridClasses.js +1 -1
  79. package/modern/hooks/core/useGridInitialization.js +1 -1
  80. package/modern/hooks/core/useGridStateInitialization.js +6 -10
  81. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -5
  82. package/modern/hooks/features/columnResize/useGridColumnResize.js +75 -61
  83. package/modern/hooks/features/columns/gridColumnsUtils.js +4 -3
  84. package/modern/hooks/features/density/useGridDensity.js +30 -4
  85. package/modern/hooks/features/dimensions/useGridDimensions.js +5 -2
  86. package/modern/hooks/features/editing/useGridCellEditing.js +17 -2
  87. package/modern/hooks/features/editing/useGridRowEditing.js +3 -1
  88. package/modern/hooks/features/export/serializers/csvSerializer.js +6 -5
  89. package/modern/hooks/features/export/useGridPrintExport.js +2 -2
  90. package/modern/hooks/features/pagination/gridPaginationSelector.js +7 -1
  91. package/modern/hooks/features/pagination/gridPaginationUtils.js +5 -3
  92. package/modern/hooks/features/pagination/useGridPagination.js +5 -1
  93. package/modern/hooks/features/pagination/useGridPaginationMeta.js +77 -0
  94. package/modern/hooks/features/pagination/useGridPaginationModel.js +2 -1
  95. package/modern/hooks/features/pagination/useGridRowCount.js +32 -18
  96. package/modern/index.js +1 -1
  97. package/modern/internals/utils/propValidation.js +1 -1
  98. package/modern/locales/daDK.js +3 -4
  99. package/modern/locales/deDE.js +3 -4
  100. package/modern/locales/frFR.js +5 -6
  101. package/modern/locales/svSE.js +3 -4
  102. package/modern/models/api/index.js +0 -1
  103. package/modern/utils/cellBorderUtils.js +15 -2
  104. package/node/DataGrid/DataGrid.js +19 -0
  105. package/node/components/GridPagination.js +59 -8
  106. package/node/components/GridRow.js +4 -1
  107. package/node/components/GridScrollArea.js +1 -1
  108. package/node/components/cell/GridCell.js +4 -2
  109. package/node/components/columnHeaders/GridColumnGroupHeader.js +3 -2
  110. package/node/components/columnHeaders/GridColumnHeaderItem.js +8 -3
  111. package/node/components/containers/GridRootStyles.js +8 -4
  112. package/node/components/index.js +27 -10
  113. package/node/components/panel/GridPanel.js +3 -1
  114. package/node/components/panel/filterPanel/GridFilterInputDate.js +5 -1
  115. package/node/constants/gridClasses.js +1 -1
  116. package/node/hooks/core/useGridInitialization.js +1 -1
  117. package/node/hooks/core/useGridStateInitialization.js +6 -10
  118. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +9 -5
  119. package/node/hooks/features/columnResize/useGridColumnResize.js +76 -62
  120. package/node/hooks/features/columns/gridColumnsUtils.js +4 -3
  121. package/node/hooks/features/density/useGridDensity.js +30 -4
  122. package/node/hooks/features/dimensions/useGridDimensions.js +5 -2
  123. package/node/hooks/features/editing/useGridCellEditing.js +17 -2
  124. package/node/hooks/features/editing/useGridRowEditing.js +3 -1
  125. package/node/hooks/features/export/serializers/csvSerializer.js +6 -5
  126. package/node/hooks/features/export/useGridPrintExport.js +2 -2
  127. package/node/hooks/features/pagination/gridPaginationSelector.js +8 -2
  128. package/node/hooks/features/pagination/gridPaginationUtils.js +6 -4
  129. package/node/hooks/features/pagination/useGridPagination.js +5 -1
  130. package/node/hooks/features/pagination/useGridPaginationMeta.js +87 -0
  131. package/node/hooks/features/pagination/useGridPaginationModel.js +2 -1
  132. package/node/hooks/features/pagination/useGridRowCount.js +30 -15
  133. package/node/index.js +1 -1
  134. package/node/internals/utils/propValidation.js +1 -1
  135. package/node/locales/daDK.js +3 -4
  136. package/node/locales/deDE.js +3 -4
  137. package/node/locales/frFR.js +5 -6
  138. package/node/locales/svSE.js +3 -4
  139. package/node/models/api/index.js +0 -11
  140. package/node/utils/cellBorderUtils.js +15 -2
  141. package/package.json +1 -1
  142. package/themeAugmentation/overrides.d.ts +6 -0
  143. package/utils/cellBorderUtils.d.ts +1 -1
  144. package/utils/cellBorderUtils.js +15 -2
  145. package/utils/getGridLocalization.d.ts +1 -1
@@ -12,6 +12,9 @@ function convertFilterItemValueToInputValue(itemValue, inputType) {
12
12
  return '';
13
13
  }
14
14
  const dateCopy = new Date(itemValue);
15
+ if (Number.isNaN(dateCopy.getTime())) {
16
+ return '';
17
+ }
15
18
  // The date picker expects the date to be in the local timezone.
16
19
  // But .toISOString() converts it to UTC with zero offset.
17
20
  // So we need to subtract the timezone offset.
@@ -48,8 +51,9 @@ function GridFilterInputDate(props) {
48
51
  setFilterValueState(value);
49
52
  setIsApplying(true);
50
53
  filterTimeout.start(rootProps.filterDebounceMs, () => {
54
+ const date = new Date(value);
51
55
  applyValue(_extends({}, item, {
52
- value: new Date(value)
56
+ value: Number.isNaN(date.getTime()) ? undefined : date
53
57
  }));
54
58
  setIsApplying(false);
55
59
  });
@@ -112,6 +112,10 @@ export interface GridClasses {
112
112
  * Styles applied to the selection checkbox element.
113
113
  */
114
114
  checkboxInput: string;
115
+ /**
116
+ * Styles applied to the column header element.
117
+ */
118
+ columnHeader: string;
115
119
  /**
116
120
  * Styles applied to the column header if `headerAlign="center"`.
117
121
  */
@@ -151,9 +155,9 @@ export interface GridClasses {
151
155
  'columnHeader--pinnedLeft': string;
152
156
  'columnHeader--pinnedRight': string;
153
157
  /**
154
- * Styles applied to the column header element.
158
+ * Styles applied to the last column header element.
155
159
  */
156
- columnHeader: string;
160
+ 'columnHeader--last': string;
157
161
  /**
158
162
  * Styles applied to the header checkbox cell element.
159
163
  */
@@ -287,6 +291,11 @@ export interface GridClasses {
287
291
  * @ignore - do not document.
288
292
  */
289
293
  filler: string;
294
+ /**
295
+ * Styles applied to the filler row with top border.
296
+ * @ignore - do not document.
297
+ */
298
+ 'filler--borderTop': string;
290
299
  /**
291
300
  * Styles applied to the filler row pinned left section.
292
301
  * @ignore - do not document.
@@ -2,4 +2,4 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, unstable_gen
2
2
  export function getDataGridUtilityClass(slot) {
3
3
  return generateUtilityClass('MuiDataGrid', slot);
4
4
  }
5
- export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
5
+ export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderTop', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
@@ -15,7 +15,7 @@ export const useGridInitialization = (inputApiRef, props) => {
15
15
  useGridRefs(privateApiRef);
16
16
  useGridTheme(privateApiRef);
17
17
  useGridLoggerFactory(privateApiRef, props);
18
- useGridStateInitialization(privateApiRef, props);
18
+ useGridStateInitialization(privateApiRef);
19
19
  useGridPipeProcessing(privateApiRef);
20
20
  useGridStrategyProcessing(privateApiRef);
21
21
  useGridLocaleText(privateApiRef, props);
@@ -1,4 +1,3 @@
1
1
  import * as React from 'react';
2
- import { DataGridProcessedProps } from '../../models/props/DataGridProps';
3
2
  import type { GridPrivateApiCommon } from '../../models/api/gridApiCommon';
4
- export declare const useGridStateInitialization: <PrivateApi extends GridPrivateApiCommon>(apiRef: React.MutableRefObject<PrivateApi>, props: Pick<DataGridProcessedProps, 'signature'>) => void;
3
+ export declare const useGridStateInitialization: <PrivateApi extends GridPrivateApiCommon>(apiRef: React.MutableRefObject<PrivateApi>) => void;
@@ -1,9 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { GridSignature } from '../utils/useGridApiEventHandler';
4
3
  import { useGridApiMethod } from '../utils';
5
4
  import { isFunction } from '../../utils/utils';
6
- export const useGridStateInitialization = (apiRef, props) => {
5
+ export const useGridStateInitialization = apiRef => {
7
6
  const controlStateMapRef = React.useRef({});
8
7
  const [, rawForceUpdate] = React.useState();
9
8
  const registerControlState = React.useCallback(controlStateItem => {
@@ -62,13 +61,10 @@ export const useGridStateInitialization = (apiRef, props) => {
62
61
  const controlState = controlStateMapRef.current[stateId];
63
62
  const model = controlState.stateSelector(newState, apiRef.current.instanceId);
64
63
  if (controlState.propOnChange && hasPropChanged) {
65
- const details = props.signature === GridSignature.DataGridPro ? {
66
- api: apiRef.current,
67
- reason
68
- } : {
69
- reason
70
- };
71
- controlState.propOnChange(model, details);
64
+ controlState.propOnChange(model, {
65
+ reason,
66
+ api: apiRef.current
67
+ });
72
68
  }
73
69
  if (!ignoreSetState) {
74
70
  apiRef.current.publishEvent(controlState.changeEvent, model, {
@@ -77,7 +73,7 @@ export const useGridStateInitialization = (apiRef, props) => {
77
73
  }
78
74
  }
79
75
  return !ignoreSetState;
80
- }, [apiRef, props.signature]);
76
+ }, [apiRef]);
81
77
  const updateControlState = React.useCallback((key, state, reason) => {
82
78
  return apiRef.current.setState(previousState => {
83
79
  return _extends({}, previousState, {
@@ -1,5 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
+ import clsx from 'clsx';
3
4
  import { styled, useTheme } from '@mui/material/styles';
4
5
  import { useGridSelector } from '../../utils';
5
6
  import { useGridRootProps } from '../../utils/useGridRootProps';
@@ -22,8 +23,7 @@ export const GridColumnHeaderRow = styled('div', {
22
23
  slot: 'ColumnHeaderRow',
23
24
  overridesResolver: (_, styles) => styles.columnHeaderRow
24
25
  })({
25
- display: 'flex',
26
- height: 'var(--DataGrid-headerHeight)'
26
+ display: 'flex'
27
27
  });
28
28
  export const useGridColumnHeaders = props => {
29
29
  const {
@@ -51,6 +51,7 @@ export const useGridColumnHeaders = props => {
51
51
  const renderContext = useGridSelector(apiRef, gridRenderContextColumnsSelector);
52
52
  const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
53
53
  const offsetLeft = computeOffsetLeft(columnPositions, renderContext, theme.direction, pinnedColumns.left.length);
54
+ const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width;
54
55
  React.useEffect(() => {
55
56
  apiRef.current.columnHeadersContainerRef.current.scrollLeft = 0;
56
57
  }, [apiRef]);
@@ -104,7 +105,7 @@ export const useGridColumnHeaders = props => {
104
105
  }
105
106
  }), children, isNotPinned && /*#__PURE__*/_jsx("div", {
106
107
  role: "presentation",
107
- className: gridClasses.filler
108
+ className: clsx(gridClasses.filler, borderTop && gridClasses['filler--borderTop'])
108
109
  }), hasScrollbarFiller && /*#__PURE__*/_jsx(ScrollbarFiller, {
109
110
  header: true,
110
111
  borderTop: borderTop,
@@ -160,12 +161,14 @@ export const useGridColumnHeaders = props => {
160
161
  colDef: colDef,
161
162
  colIndex: columnIndex,
162
163
  isResizing: resizeCol === colDef.field,
164
+ isLast: columnIndex === columnPositions.length - 1,
163
165
  hasFocus: hasFocus,
164
166
  tabIndex: tabIndex,
165
167
  pinnedPosition: pinnedPosition,
166
168
  style: style,
167
169
  indexInSection: i,
168
- sectionLength: renderedColumns.length
170
+ sectionLength: renderedColumns.length,
171
+ gridHasFiller: gridHasFiller
169
172
  }, other), colDef.field));
170
173
  }
171
174
  return getFillers(params, columns, 0);
@@ -275,7 +278,8 @@ export const useGridColumnHeaders = props => {
275
278
  pinnedPosition: pinnedPosition,
276
279
  style: style,
277
280
  indexInSection: indexInSection,
278
- sectionLength: renderedColumns.length
281
+ sectionLength: renderedColumns.length,
282
+ gridHasFiller: gridHasFiller
279
283
  }, index);
280
284
  });
281
285
  return getFillers(params, children, leftOverflow);
@@ -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, unstable_useEventCallback as useEventCallback } from '@mui/utils';
4
+ import useLazyRef from '@mui/utils/useLazyRef';
4
5
  import { useTheme } from '@mui/material/styles';
5
6
  import { findGridCellElementsFromCol, findGridElement, findLeftPinnedCellsAfterCol, findRightPinnedCellsBeforeCol, getFieldFromHeaderElem, findHeaderElementFromField, findGroupHeaderElementsFromField, findGridHeader, findGridCells, findParentElementFromClassName, findLeftPinnedHeadersAfterCol, findRightPinnedHeadersBeforeCol } from '../../../utils/domUtils';
6
7
  import { DEFAULT_GRID_AUTOSIZE_OPTIONS } from './gridColumnResizeApi';
@@ -173,6 +174,25 @@ export const columnResizeStateInitializer = state => _extends({}, state, {
173
174
  resizingColumnField: ''
174
175
  }
175
176
  });
177
+ function createResizeRefs() {
178
+ return {
179
+ colDef: undefined,
180
+ initialColWidth: 0,
181
+ initialTotalWidth: 0,
182
+ previousMouseClickEvent: undefined,
183
+ columnHeaderElement: undefined,
184
+ headerFilterElement: undefined,
185
+ groupHeaderElements: [],
186
+ cellElements: [],
187
+ leftPinnedCellsAfter: [],
188
+ rightPinnedCellsBefore: [],
189
+ fillerLeft: undefined,
190
+ fillerRight: undefined,
191
+ leftPinnedHeadersAfter: [],
192
+ rightPinnedHeadersBefore: []
193
+ };
194
+ }
195
+
176
196
  /**
177
197
  * @requires useGridColumns (method, event)
178
198
  * TODO: improve experience for last column
@@ -180,18 +200,7 @@ export const columnResizeStateInitializer = state => _extends({}, state, {
180
200
  export const useGridColumnResize = (apiRef, props) => {
181
201
  const theme = useTheme();
182
202
  const logger = useGridLogger(apiRef, 'useGridColumnResize');
183
- const colDefRef = React.useRef();
184
- const previousMouseClickEvent = React.useRef();
185
- const columnHeaderElementRef = React.useRef();
186
- const headerFilterElementRef = React.useRef();
187
- const groupHeaderElementsRef = React.useRef([]);
188
- const cellElementsRef = React.useRef([]);
189
- const leftPinnedCellsAfterRef = React.useRef([]);
190
- const rightPinnedCellsBeforeRef = React.useRef([]);
191
- const fillerLeftRef = React.useRef();
192
- const fillerRightRef = React.useRef();
193
- const leftPinnedHeadersAfterRef = React.useRef([]);
194
- const rightPinnedHeadersBeforeRef = React.useRef([]);
203
+ const refs = useLazyRef(createResizeRefs).current;
195
204
 
196
205
  // To improve accessibility, the separator has padding on both sides.
197
206
  // Clicking inside the padding area should be treated as a click in the separator.
@@ -201,22 +210,25 @@ export const useGridColumnResize = (apiRef, props) => {
201
210
  const stopResizeEventTimeout = useTimeout();
202
211
  const touchId = React.useRef();
203
212
  const updateWidth = newWidth => {
204
- logger.debug(`Updating width to ${newWidth} for col ${colDefRef.current.field}`);
205
- const prevWidth = columnHeaderElementRef.current.offsetWidth;
213
+ logger.debug(`Updating width to ${newWidth} for col ${refs.colDef.field}`);
214
+ const prevWidth = refs.columnHeaderElement.offsetWidth;
206
215
  const widthDiff = newWidth - prevWidth;
207
- colDefRef.current.computedWidth = newWidth;
208
- colDefRef.current.width = newWidth;
209
- colDefRef.current.flex = 0;
210
- columnHeaderElementRef.current.style.width = `${newWidth}px`;
211
- columnHeaderElementRef.current.style.minWidth = `${newWidth}px`;
212
- columnHeaderElementRef.current.style.maxWidth = `${newWidth}px`;
213
- const headerFilterElement = headerFilterElementRef.current;
216
+ const columnWidthDiff = newWidth - refs.initialColWidth;
217
+ const newTotalWidth = refs.initialTotalWidth + columnWidthDiff;
218
+ apiRef.current.rootElementRef?.current?.style.setProperty('--DataGrid-rowWidth', `${newTotalWidth}px`);
219
+ refs.colDef.computedWidth = newWidth;
220
+ refs.colDef.width = newWidth;
221
+ refs.colDef.flex = 0;
222
+ refs.columnHeaderElement.style.width = `${newWidth}px`;
223
+ refs.columnHeaderElement.style.minWidth = `${newWidth}px`;
224
+ refs.columnHeaderElement.style.maxWidth = `${newWidth}px`;
225
+ const headerFilterElement = refs.headerFilterElement;
214
226
  if (headerFilterElement) {
215
227
  headerFilterElement.style.width = `${newWidth}px`;
216
228
  headerFilterElement.style.minWidth = `${newWidth}px`;
217
229
  headerFilterElement.style.maxWidth = `${newWidth}px`;
218
230
  }
219
- groupHeaderElementsRef.current.forEach(element => {
231
+ refs.groupHeaderElements.forEach(element => {
220
232
  const div = element;
221
233
  let finalWidth;
222
234
  if (div.getAttribute('aria-colspan') === '1') {
@@ -230,7 +242,7 @@ export const useGridColumnResize = (apiRef, props) => {
230
242
  div.style.minWidth = finalWidth;
231
243
  div.style.maxWidth = finalWidth;
232
244
  });
233
- cellElementsRef.current.forEach(element => {
245
+ refs.cellElements.forEach(element => {
234
246
  const div = element;
235
247
  let finalWidth;
236
248
  if (div.getAttribute('aria-colspan') === '1') {
@@ -242,22 +254,22 @@ export const useGridColumnResize = (apiRef, props) => {
242
254
  }
243
255
  div.style.setProperty('--width', finalWidth);
244
256
  });
245
- const pinnedPosition = apiRef.current.unstable_applyPipeProcessors('isColumnPinned', false, colDefRef.current.field);
257
+ const pinnedPosition = apiRef.current.unstable_applyPipeProcessors('isColumnPinned', false, refs.colDef.field);
246
258
  if (pinnedPosition === GridPinnedColumnPosition.LEFT) {
247
- updateProperty(fillerLeftRef.current, 'width', widthDiff);
248
- leftPinnedCellsAfterRef.current.forEach(cell => {
259
+ updateProperty(refs.fillerLeft, 'width', widthDiff);
260
+ refs.leftPinnedCellsAfter.forEach(cell => {
249
261
  updateProperty(cell, 'left', widthDiff);
250
262
  });
251
- leftPinnedHeadersAfterRef.current.forEach(header => {
263
+ refs.leftPinnedHeadersAfter.forEach(header => {
252
264
  updateProperty(header, 'left', widthDiff);
253
265
  });
254
266
  }
255
267
  if (pinnedPosition === GridPinnedColumnPosition.RIGHT) {
256
- updateProperty(fillerRightRef.current, 'width', widthDiff);
257
- rightPinnedCellsBeforeRef.current.forEach(cell => {
268
+ updateProperty(refs.fillerRight, 'width', widthDiff);
269
+ refs.rightPinnedCellsBefore.forEach(cell => {
258
270
  updateProperty(cell, 'right', widthDiff);
259
271
  });
260
- rightPinnedHeadersBeforeRef.current.forEach(header => {
272
+ refs.rightPinnedHeadersBefore.forEach(header => {
261
273
  updateProperty(header, 'right', widthDiff);
262
274
  });
263
275
  }
@@ -267,21 +279,21 @@ export const useGridColumnResize = (apiRef, props) => {
267
279
  stopListening();
268
280
 
269
281
  // Prevent double-clicks from being interpreted as two separate clicks
270
- if (previousMouseClickEvent.current) {
271
- const prevEvent = previousMouseClickEvent.current;
282
+ if (refs.previousMouseClickEvent) {
283
+ const prevEvent = refs.previousMouseClickEvent;
272
284
  const prevTimeStamp = prevEvent.timeStamp;
273
285
  const prevClientX = prevEvent.clientX;
274
286
  const prevClientY = prevEvent.clientY;
275
287
 
276
288
  // Check if the current event is part of a double-click
277
289
  if (nativeEvent.timeStamp - prevTimeStamp < 300 && nativeEvent.clientX === prevClientX && nativeEvent.clientY === prevClientY) {
278
- previousMouseClickEvent.current = undefined;
290
+ refs.previousMouseClickEvent = undefined;
279
291
  return;
280
292
  }
281
293
  }
282
- if (colDefRef.current) {
283
- apiRef.current.setColumnWidth(colDefRef.current.field, colDefRef.current.width);
284
- logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
294
+ if (refs.colDef) {
295
+ apiRef.current.setColumnWidth(refs.colDef.field, refs.colDef.width);
296
+ logger.debug(`Updating col ${refs.colDef.field} with new width: ${refs.colDef.width}`);
285
297
  }
286
298
  stopResizeEventTimeout.start(0, () => {
287
299
  apiRef.current.publishEvent('columnResizeStop', null, nativeEvent);
@@ -289,23 +301,25 @@ export const useGridColumnResize = (apiRef, props) => {
289
301
  };
290
302
  const storeReferences = (colDef, separator, xStart) => {
291
303
  const root = apiRef.current.rootElementRef.current;
292
- colDefRef.current = colDef;
293
- columnHeaderElementRef.current = findHeaderElementFromField(apiRef.current.columnHeadersContainerRef.current, colDef.field);
304
+ refs.initialColWidth = colDef.computedWidth;
305
+ refs.initialTotalWidth = apiRef.current.getRootDimensions().rowWidth;
306
+ refs.colDef = colDef;
307
+ refs.columnHeaderElement = findHeaderElementFromField(apiRef.current.columnHeadersContainerRef.current, colDef.field);
294
308
  const headerFilterElement = root.querySelector(`.${gridClasses.headerFilterRow} [data-field="${colDef.field}"]`);
295
309
  if (headerFilterElement) {
296
- headerFilterElementRef.current = headerFilterElement;
310
+ refs.headerFilterElement = headerFilterElement;
297
311
  }
298
- groupHeaderElementsRef.current = findGroupHeaderElementsFromField(apiRef.current.columnHeadersContainerRef?.current, colDef.field);
299
- cellElementsRef.current = findGridCellElementsFromCol(columnHeaderElementRef.current, apiRef.current);
300
- fillerLeftRef.current = findGridElement(apiRef.current, 'filler--pinnedLeft');
301
- fillerRightRef.current = findGridElement(apiRef.current, 'filler--pinnedRight');
302
- const pinnedPosition = apiRef.current.unstable_applyPipeProcessors('isColumnPinned', false, colDefRef.current.field);
303
- leftPinnedCellsAfterRef.current = pinnedPosition !== GridPinnedColumnPosition.LEFT ? [] : findLeftPinnedCellsAfterCol(apiRef.current, columnHeaderElementRef.current);
304
- rightPinnedCellsBeforeRef.current = pinnedPosition !== GridPinnedColumnPosition.RIGHT ? [] : findRightPinnedCellsBeforeCol(apiRef.current, columnHeaderElementRef.current);
305
- leftPinnedHeadersAfterRef.current = pinnedPosition !== GridPinnedColumnPosition.LEFT ? [] : findLeftPinnedHeadersAfterCol(apiRef.current, columnHeaderElementRef.current);
306
- rightPinnedHeadersBeforeRef.current = pinnedPosition !== GridPinnedColumnPosition.RIGHT ? [] : findRightPinnedHeadersBeforeCol(apiRef.current, columnHeaderElementRef.current);
312
+ refs.groupHeaderElements = findGroupHeaderElementsFromField(apiRef.current.columnHeadersContainerRef?.current, colDef.field);
313
+ refs.cellElements = findGridCellElementsFromCol(refs.columnHeaderElement, apiRef.current);
314
+ refs.fillerLeft = findGridElement(apiRef.current, 'filler--pinnedLeft');
315
+ refs.fillerRight = findGridElement(apiRef.current, 'filler--pinnedRight');
316
+ const pinnedPosition = apiRef.current.unstable_applyPipeProcessors('isColumnPinned', false, refs.colDef.field);
317
+ refs.leftPinnedCellsAfter = pinnedPosition !== GridPinnedColumnPosition.LEFT ? [] : findLeftPinnedCellsAfterCol(apiRef.current, refs.columnHeaderElement);
318
+ refs.rightPinnedCellsBefore = pinnedPosition !== GridPinnedColumnPosition.RIGHT ? [] : findRightPinnedCellsBeforeCol(apiRef.current, refs.columnHeaderElement);
319
+ refs.leftPinnedHeadersAfter = pinnedPosition !== GridPinnedColumnPosition.LEFT ? [] : findLeftPinnedHeadersAfterCol(apiRef.current, refs.columnHeaderElement);
320
+ refs.rightPinnedHeadersBefore = pinnedPosition !== GridPinnedColumnPosition.RIGHT ? [] : findRightPinnedHeadersBeforeCol(apiRef.current, refs.columnHeaderElement);
307
321
  resizeDirection.current = getResizeDirection(separator, theme.direction);
308
- initialOffsetToSeparator.current = computeOffsetToSeparator(xStart, columnHeaderElementRef.current.getBoundingClientRect(), resizeDirection.current);
322
+ initialOffsetToSeparator.current = computeOffsetToSeparator(xStart, refs.columnHeaderElement.getBoundingClientRect(), resizeDirection.current);
309
323
  };
310
324
  const handleResizeMouseUp = useEventCallback(finishResize);
311
325
  const handleResizeMouseMove = useEventCallback(nativeEvent => {
@@ -314,12 +328,12 @@ export const useGridColumnResize = (apiRef, props) => {
314
328
  handleResizeMouseUp(nativeEvent);
315
329
  return;
316
330
  }
317
- let newWidth = computeNewWidth(initialOffsetToSeparator.current, nativeEvent.clientX, columnHeaderElementRef.current.getBoundingClientRect(), resizeDirection.current);
318
- newWidth = clamp(newWidth, colDefRef.current.minWidth, colDefRef.current.maxWidth);
331
+ let newWidth = computeNewWidth(initialOffsetToSeparator.current, nativeEvent.clientX, refs.columnHeaderElement.getBoundingClientRect(), resizeDirection.current);
332
+ newWidth = clamp(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
319
333
  updateWidth(newWidth);
320
334
  const params = {
321
- element: columnHeaderElementRef.current,
322
- colDef: colDefRef.current,
335
+ element: refs.columnHeaderElement,
336
+ colDef: refs.colDef,
323
337
  width: newWidth
324
338
  };
325
339
  apiRef.current.publishEvent('columnResize', params, nativeEvent);
@@ -342,12 +356,12 @@ export const useGridColumnResize = (apiRef, props) => {
342
356
  handleTouchEnd(nativeEvent);
343
357
  return;
344
358
  }
345
- let newWidth = computeNewWidth(initialOffsetToSeparator.current, finger.x, columnHeaderElementRef.current.getBoundingClientRect(), resizeDirection.current);
346
- newWidth = clamp(newWidth, colDefRef.current.minWidth, colDefRef.current.maxWidth);
359
+ let newWidth = computeNewWidth(initialOffsetToSeparator.current, finger.x, refs.columnHeaderElement.getBoundingClientRect(), resizeDirection.current);
360
+ newWidth = clamp(newWidth, refs.colDef.minWidth, refs.colDef.maxWidth);
347
361
  updateWidth(newWidth);
348
362
  const params = {
349
- element: columnHeaderElementRef.current,
350
- colDef: colDefRef.current,
363
+ element: refs.columnHeaderElement,
364
+ colDef: refs.colDef,
351
365
  width: newWidth
352
366
  };
353
367
  apiRef.current.publishEvent('columnResize', params, nativeEvent);
@@ -391,10 +405,10 @@ export const useGridColumnResize = (apiRef, props) => {
391
405
  setTimeout(() => {
392
406
  doc.removeEventListener('click', preventClick, true);
393
407
  }, 100);
394
- if (columnHeaderElementRef.current) {
395
- columnHeaderElementRef.current.style.pointerEvents = 'unset';
408
+ if (refs.columnHeaderElement) {
409
+ refs.columnHeaderElement.style.pointerEvents = 'unset';
396
410
  }
397
- }, [apiRef, columnHeaderElementRef, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
411
+ }, [apiRef, refs, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
398
412
  const handleResizeStart = React.useCallback(({
399
413
  field
400
414
  }) => {
@@ -435,7 +449,7 @@ export const useGridColumnResize = (apiRef, props) => {
435
449
  storeReferences(colDef, event.currentTarget, event.clientX);
436
450
  const doc = ownerDocument(apiRef.current.rootElementRef.current);
437
451
  doc.body.style.cursor = 'col-resize';
438
- previousMouseClickEvent.current = event.nativeEvent;
452
+ refs.previousMouseClickEvent = event.nativeEvent;
439
453
  doc.addEventListener('mousemove', handleResizeMouseMove);
440
454
  doc.addEventListener('mouseup', handleResizeMouseUp);
441
455
 
@@ -1,5 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { GridColumnsState, GridColumnsRawState, GridColumnVisibilityModel, GridColumnsInitialState } from './gridColumnsInterfaces';
3
+ import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
3
4
  import { GridApiCommunity } from '../../../models/api/gridApiCommunity';
4
5
  import { GridColDef } from '../../../models/colDef/gridColDef';
5
6
  import { GridApiCommon } from '../../../models/api/gridApiCommon';
@@ -51,4 +52,4 @@ export declare function getFirstNonSpannedColumnToRender({ firstColumnToRender,
51
52
  lastRowToRender: number;
52
53
  visibleRows: GridRowEntry[];
53
54
  }): number;
54
- export declare function getTotalHeaderHeight(apiRef: React.MutableRefObject<GridApiCommunity>, headerHeight: number): number;
55
+ export declare function getTotalHeaderHeight(apiRef: React.MutableRefObject<GridApiCommunity>, props: Pick<DataGridProcessedProps, 'columnHeaderHeight' | 'headerFilterHeight'>): number;
@@ -304,10 +304,11 @@ export function getFirstNonSpannedColumnToRender({
304
304
  }
305
305
  return firstNonSpannedColumnToRender;
306
306
  }
307
- export function getTotalHeaderHeight(apiRef, headerHeight) {
307
+ export function getTotalHeaderHeight(apiRef, props) {
308
308
  const densityFactor = gridDensityFactorSelector(apiRef);
309
309
  const maxDepth = gridColumnGroupsHeaderMaxDepthSelector(apiRef);
310
310
  const isHeaderFilteringEnabled = gridHeaderFilteringEnabledSelector(apiRef);
311
- const multiplicationFactor = isHeaderFilteringEnabled ? 2 : 1;
312
- return Math.floor(headerHeight * densityFactor) * ((maxDepth ?? 0) + multiplicationFactor);
311
+ const columnHeadersHeight = Math.floor(props.columnHeaderHeight * densityFactor);
312
+ const filterHeadersHeight = isHeaderFilteringEnabled ? Math.floor((props.headerFilterHeight ?? props.columnHeaderHeight) * densityFactor) : 0;
313
+ return columnHeadersHeight * (1 + (maxDepth ?? 0)) + filterHeadersHeight;
313
314
  }
@@ -3,4 +3,4 @@ import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
3
3
  import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
4
4
  import { GridStateInitializer } from '../../utils/useGridInitializeState';
5
5
  export declare const densityStateInitializer: GridStateInitializer<Pick<DataGridProcessedProps, 'initialState' | 'density'>>;
6
- export declare const useGridDensity: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'density' | 'onDensityChange'>) => void;
6
+ export declare const useGridDensity: (apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: Pick<DataGridProcessedProps, 'density' | 'onDensityChange' | 'initialState'>) => void;
@@ -4,6 +4,7 @@ import useEventCallback from '@mui/utils/useEventCallback';
4
4
  import { useGridLogger } from '../../utils/useGridLogger';
5
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
6
6
  import { gridDensitySelector } from './densitySelector';
7
+ import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
7
8
  export const densityStateInitializer = (state, props) => _extends({}, state, {
8
9
  density: props.initialState?.density ?? props.density ?? 'standard'
9
10
  });
@@ -26,13 +27,38 @@ export const useGridDensity = (apiRef, props) => {
26
27
  density: newDensity
27
28
  }));
28
29
  });
30
+ const densityApi = {
31
+ setDensity
32
+ };
33
+ useGridApiMethod(apiRef, densityApi, 'public');
34
+ const stateExportPreProcessing = React.useCallback((prevState, context) => {
35
+ const exportedDensity = gridDensitySelector(apiRef.current.state);
36
+ const shouldExportRowCount =
37
+ // Always export if the `exportOnlyDirtyModels` property is not activated
38
+ !context.exportOnlyDirtyModels ||
39
+ // Always export if the `density` is controlled
40
+ props.density != null ||
41
+ // Always export if the `density` has been initialized
42
+ props.initialState?.density != null;
43
+ if (!shouldExportRowCount) {
44
+ return prevState;
45
+ }
46
+ return _extends({}, prevState, {
47
+ density: exportedDensity
48
+ });
49
+ }, [apiRef, props.density, props.initialState?.density]);
50
+ const stateRestorePreProcessing = React.useCallback((params, context) => {
51
+ const restoredDensity = context.stateToRestore?.density ? context.stateToRestore.density : gridDensitySelector(apiRef.current.state);
52
+ apiRef.current.setState(state => _extends({}, state, {
53
+ density: restoredDensity
54
+ }));
55
+ return params;
56
+ }, [apiRef]);
57
+ useGridRegisterPipeProcessor(apiRef, 'exportState', stateExportPreProcessing);
58
+ useGridRegisterPipeProcessor(apiRef, 'restoreState', stateRestorePreProcessing);
29
59
  React.useEffect(() => {
30
60
  if (props.density) {
31
61
  apiRef.current.setDensity(props.density);
32
62
  }
33
63
  }, [apiRef, props.density]);
34
- const densityApi = {
35
- setDensity
36
- };
37
- useGridApiMethod(apiRef, densityApi, 'public');
38
64
  };
@@ -58,9 +58,13 @@ export interface GridDimensions {
58
58
  */
59
59
  rightPinnedWidth: number;
60
60
  /**
61
- * Height of one headers.
61
+ * Height of one column header.
62
62
  */
63
63
  headerHeight: number;
64
+ /**
65
+ * Height of header filters.
66
+ */
67
+ headerFilterHeight: number;
64
68
  /**
65
69
  * Height of all the column headers.
66
70
  */
@@ -3,7 +3,7 @@ import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity';
3
3
  import { DataGridProcessedProps } from '../../../models/props/DataGridProps';
4
4
  import { GridDimensions } from './gridDimensionsApi';
5
5
  import { GridStateInitializer } from '../../utils/useGridInitializeState';
6
- type RootProps = Pick<DataGridProcessedProps, 'onResize' | 'scrollbarSize' | 'pagination' | 'paginationMode' | 'autoHeight' | 'getRowHeight' | 'rowHeight' | 'resizeThrottleMs' | 'columnHeaderHeight'>;
6
+ type RootProps = Pick<DataGridProcessedProps, 'onResize' | 'scrollbarSize' | 'pagination' | 'paginationMode' | 'autoHeight' | 'getRowHeight' | 'rowHeight' | 'resizeThrottleMs' | 'columnHeaderHeight' | 'headerFilterHeight'>;
7
7
  export type GridDimensionsState = GridDimensions;
8
8
  export declare const dimensionsStateInitializer: GridStateInitializer<RootProps>;
9
9
  export declare function useGridDimensions(apiRef: React.MutableRefObject<GridPrivateApiCommunity>, props: RootProps): void;
@@ -29,6 +29,7 @@ const EMPTY_DIMENSIONS = {
29
29
  hasScrollY: false,
30
30
  scrollbarSize: 0,
31
31
  headerHeight: 0,
32
+ headerFilterHeight: 0,
32
33
  rowWidth: 0,
33
34
  rowHeight: 0,
34
35
  columnsTotalWidth: 0,
@@ -53,8 +54,9 @@ export function useGridDimensions(apiRef, props) {
53
54
  const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector);
54
55
  const rowHeight = Math.floor(props.rowHeight * densityFactor);
55
56
  const headerHeight = Math.floor(props.columnHeaderHeight * densityFactor);
57
+ const headerFilterHeight = Math.floor((props.headerFilterHeight ?? props.columnHeaderHeight) * densityFactor);
56
58
  const columnsTotalWidth = roundToDecimalPlaces(gridColumnsTotalWidthSelector(apiRef), 6);
57
- const headersTotalHeight = getTotalHeaderHeight(apiRef, props.columnHeaderHeight);
59
+ const headersTotalHeight = getTotalHeaderHeight(apiRef, props);
58
60
  const leftPinnedWidth = pinnedColumns.left.reduce((w, col) => w + col.computedWidth, 0);
59
61
  const rightPinnedWidth = pinnedColumns.right.reduce((w, col) => w + col.computedWidth, 0);
60
62
  const [savedSize, setSavedSize] = React.useState();
@@ -176,6 +178,7 @@ export function useGridDimensions(apiRef, props) {
176
178
  hasScrollY,
177
179
  scrollbarSize,
178
180
  headerHeight,
181
+ headerFilterHeight,
179
182
  rowWidth,
180
183
  rowHeight,
181
184
  columnsTotalWidth,
@@ -191,7 +194,7 @@ export function useGridDimensions(apiRef, props) {
191
194
  apiRef.current.publishEvent('viewportInnerSizeChange', newDimensions.viewportInnerSize);
192
195
  }
193
196
  apiRef.current.updateRenderContext?.();
194
- }, [apiRef, setDimensions, props.scrollbarSize, props.autoHeight, rowsMeta.currentPageTotalHeight, rowHeight, headerHeight, columnsTotalWidth, headersTotalHeight, leftPinnedWidth, rightPinnedWidth]);
197
+ }, [apiRef, setDimensions, props.scrollbarSize, props.autoHeight, rowsMeta.currentPageTotalHeight, rowHeight, headerHeight, headerFilterHeight, columnsTotalWidth, headersTotalHeight, leftPinnedWidth, rightPinnedWidth]);
195
198
  const apiPublic = {
196
199
  resize,
197
200
  getRootDimensions
@@ -153,13 +153,26 @@ export const useGridCellEditing = (apiRef, props) => {
153
153
  cellToFocusAfter
154
154
  });
155
155
  }, [apiRef]);
156
+ const runIfNoFieldErrors = callback => async (...args) => {
157
+ if (callback) {
158
+ const {
159
+ id,
160
+ field
161
+ } = args[0];
162
+ const editRowsState = apiRef.current.state.editRows;
163
+ const hasFieldErrors = editRowsState[id][field]?.error;
164
+ if (!hasFieldErrors) {
165
+ callback(...args);
166
+ }
167
+ }
168
+ };
156
169
  useGridApiEventHandler(apiRef, 'cellDoubleClick', runIfEditModeIsCell(handleCellDoubleClick));
157
170
  useGridApiEventHandler(apiRef, 'cellFocusOut', runIfEditModeIsCell(handleCellFocusOut));
158
171
  useGridApiEventHandler(apiRef, 'cellKeyDown', runIfEditModeIsCell(handleCellKeyDown));
159
172
  useGridApiEventHandler(apiRef, 'cellEditStart', runIfEditModeIsCell(handleCellEditStart));
160
173
  useGridApiEventHandler(apiRef, 'cellEditStop', runIfEditModeIsCell(handleCellEditStop));
161
174
  useGridApiOptionHandler(apiRef, 'cellEditStart', props.onCellEditStart);
162
- useGridApiOptionHandler(apiRef, 'cellEditStop', props.onCellEditStop);
175
+ useGridApiOptionHandler(apiRef, 'cellEditStop', runIfNoFieldErrors(props.onCellEditStop));
163
176
  const getCellMode = React.useCallback((id, field) => {
164
177
  const editingState = gridEditRowsStateSelector(apiRef.current.state);
165
178
  const isEditing = editingState[id] && editingState[id][field];
@@ -168,7 +181,9 @@ export const useGridCellEditing = (apiRef, props) => {
168
181
  const updateCellModesModel = useEventCallback(newModel => {
169
182
  const isNewModelDifferentFromProp = newModel !== props.cellModesModel;
170
183
  if (onCellModesModelChange && isNewModelDifferentFromProp) {
171
- onCellModesModelChange(newModel, {});
184
+ onCellModesModelChange(newModel, {
185
+ api: apiRef.current
186
+ });
172
187
  }
173
188
  if (props.cellModesModel && isNewModelDifferentFromProp) {
174
189
  return; // The prop always win