@mui/x-data-grid 7.22.3 → 7.23.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 (75) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/DataGrid/DataGrid.js +9 -1
  3. package/README.md +3 -3
  4. package/components/cell/GridCell.js +10 -10
  5. package/components/toolbar/GridToolbarColumnsButton.js +3 -4
  6. package/components/toolbar/GridToolbarDensitySelector.js +3 -4
  7. package/components/toolbar/GridToolbarExportContainer.js +3 -4
  8. package/components/toolbar/GridToolbarFilterButton.d.ts +2 -0
  9. package/components/toolbar/GridToolbarFilterButton.js +7 -6
  10. package/components/toolbar/GridToolbarQuickFilter.js +1 -0
  11. package/constants/dataGridPropsDefaultValues.js +2 -1
  12. package/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  13. package/hooks/features/dimensions/useGridDimensions.js +2 -1
  14. package/hooks/features/index.d.ts +1 -0
  15. package/hooks/features/index.js +1 -0
  16. package/hooks/features/listView/gridListViewSelectors.d.ts +3 -1
  17. package/hooks/features/listView/gridListViewSelectors.js +3 -1
  18. package/hooks/features/listView/index.d.ts +1 -0
  19. package/hooks/features/listView/index.js +1 -0
  20. package/hooks/features/rowSelection/useGridRowSelection.js +0 -9
  21. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
  22. package/hooks/features/virtualization/useGridVirtualScroller.js +55 -15
  23. package/index.js +1 -1
  24. package/joy/joySlots.js +7 -2
  25. package/locales/esES.js +1 -2
  26. package/locales/ptBR.js +1 -2
  27. package/locales/ptPT.js +1 -2
  28. package/locales/zhCN.js +1 -2
  29. package/models/api/gridCoreApi.d.ts +1 -1
  30. package/models/colDef/gridColDef.d.ts +24 -24
  31. package/models/gridDataSource.d.ts +12 -12
  32. package/models/props/DataGridProps.d.ts +8 -0
  33. package/modern/DataGrid/DataGrid.js +9 -1
  34. package/modern/components/cell/GridCell.js +10 -10
  35. package/modern/components/toolbar/GridToolbarColumnsButton.js +3 -4
  36. package/modern/components/toolbar/GridToolbarDensitySelector.js +3 -4
  37. package/modern/components/toolbar/GridToolbarExportContainer.js +3 -4
  38. package/modern/components/toolbar/GridToolbarFilterButton.js +7 -6
  39. package/modern/components/toolbar/GridToolbarQuickFilter.js +1 -0
  40. package/modern/constants/dataGridPropsDefaultValues.js +2 -1
  41. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  42. package/modern/hooks/features/dimensions/useGridDimensions.js +2 -1
  43. package/modern/hooks/features/index.js +1 -0
  44. package/modern/hooks/features/listView/gridListViewSelectors.js +3 -1
  45. package/modern/hooks/features/listView/index.js +1 -0
  46. package/modern/hooks/features/rowSelection/useGridRowSelection.js +0 -9
  47. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +55 -15
  48. package/modern/index.js +1 -1
  49. package/modern/joy/joySlots.js +7 -2
  50. package/modern/locales/esES.js +1 -2
  51. package/modern/locales/ptBR.js +1 -2
  52. package/modern/locales/ptPT.js +1 -2
  53. package/modern/locales/zhCN.js +1 -2
  54. package/node/DataGrid/DataGrid.js +9 -1
  55. package/node/components/cell/GridCell.js +10 -10
  56. package/node/components/toolbar/GridToolbarColumnsButton.js +3 -4
  57. package/node/components/toolbar/GridToolbarDensitySelector.js +3 -4
  58. package/node/components/toolbar/GridToolbarExportContainer.js +3 -4
  59. package/node/components/toolbar/GridToolbarFilterButton.js +7 -6
  60. package/node/components/toolbar/GridToolbarQuickFilter.js +1 -0
  61. package/node/constants/dataGridPropsDefaultValues.js +2 -1
  62. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +1 -1
  63. package/node/hooks/features/dimensions/useGridDimensions.js +2 -1
  64. package/node/hooks/features/index.js +11 -0
  65. package/node/hooks/features/listView/gridListViewSelectors.js +3 -1
  66. package/node/hooks/features/listView/index.js +16 -0
  67. package/node/hooks/features/rowSelection/useGridRowSelection.js +0 -9
  68. package/node/hooks/features/virtualization/useGridVirtualScroller.js +55 -15
  69. package/node/index.js +1 -1
  70. package/node/joy/joySlots.js +7 -2
  71. package/node/locales/esES.js +1 -2
  72. package/node/locales/ptBR.js +1 -2
  73. package/node/locales/ptPT.js +1 -2
  74. package/node/locales/zhCN.js +1 -2
  75. package/package.json +4 -4
@@ -36,43 +36,43 @@ export type GridColSpanFn<R extends GridValidRowModel = GridValidRowModel, V = a
36
36
  */
37
37
  export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel, V = any, F = V> {
38
38
  /**
39
- * The column identifier. It's used to map with [[GridRowModel]] values.
39
+ * The unique identifier of the column. Used to map with [[GridRowModel]] values.
40
40
  */
41
41
  field: string;
42
42
  /**
43
- * The title of the column rendered in the column header cell.
43
+ * The title displayed in the column header cell.
44
44
  */
45
45
  headerName?: string;
46
46
  /**
47
- * The description of the column rendered as tooltip if the column header name is not fully displayed.
47
+ * The tooltip text shown when the column header name is truncated.
48
48
  */
49
49
  description?: string;
50
50
  /**
51
- * Set the width of the column.
51
+ * The width of the column in pixels.
52
52
  * @default 100
53
53
  */
54
54
  width?: number;
55
55
  /**
56
- * If set, it indicates that a column has fluid width. Range [0, ∞).
56
+ * The flex grow factor of the column. Must be a positive number.
57
57
  */
58
58
  flex?: number;
59
59
  /**
60
- * Sets the minimum width of a column.
60
+ * The minimum width of the column in pixels.
61
61
  * @default 50
62
62
  */
63
63
  minWidth?: number;
64
64
  /**
65
- * Sets the maximum width of a column.
65
+ * The maximum width of the column in pixels.
66
66
  * @default Infinity
67
67
  */
68
68
  maxWidth?: number;
69
69
  /**
70
- * If `false`, removes the buttons for hiding this column.
70
+ * If `false`, removes the option to hide this column.
71
71
  * @default true
72
72
  */
73
73
  hideable?: boolean;
74
74
  /**
75
- * If `true`, the column is sortable.
75
+ * If `false`, disables sorting for this column.
76
76
  * @default true
77
77
  */
78
78
  sortable?: boolean;
@@ -81,7 +81,7 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
81
81
  */
82
82
  sortingOrder?: readonly GridSortDirection[];
83
83
  /**
84
- * If `true`, the column is resizable.
84
+ * If `false`, disables resizing for this column.
85
85
  * @default true
86
86
  */
87
87
  resizable?: boolean;
@@ -109,7 +109,7 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
109
109
  */
110
110
  sortComparator?: GridComparatorFn<V>;
111
111
  /**
112
- * Allows to use a different comparator function depending on the sort direction.
112
+ * Provide an alternative comparator function for sorting.
113
113
  * Takes precedence over `sortComparator`.
114
114
  * @param {GridSortDirection} sortDirection The direction of the sort.
115
115
  * @returns {GridComparatorFn<V>} The comparator function to use.
@@ -122,25 +122,25 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
122
122
  */
123
123
  type?: GridColType;
124
124
  /**
125
- * Allows to align the column values in cells.
125
+ * Align cell content.
126
126
  */
127
127
  align?: GridAlignment;
128
128
  /**
129
- * Function that allows to get a specific data instead of field to render in the cell.
129
+ * Function that returns specific data to render in the cell instead of using the field value.
130
130
  */
131
131
  valueGetter?: GridValueGetter<R, V, F>;
132
132
  /**
133
- * Function that allows to provide a specific value to be used in row spanning.
133
+ * Function that returns a specific value to be used in row spanning.
134
134
  */
135
135
  rowSpanValueGetter?: GridValueGetter<R, V, F>;
136
136
  /**
137
- * Function that allows to customize how the entered value is stored in the row.
138
- * It only works with cell/row editing.
137
+ * Function that customizes how the entered value is stored in the row.
138
+ * Only works with cell/row editing.
139
139
  * @returns {R} The row with the updated field.
140
140
  */
141
141
  valueSetter?: GridValueSetter<R, V, F>;
142
142
  /**
143
- * Function that allows to apply a formatter before rendering its value.
143
+ * Formats the cell value before rendering.
144
144
  */
145
145
  valueFormatter?: GridValueFormatter<R, V, F>;
146
146
  /**
@@ -149,7 +149,7 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
149
149
  */
150
150
  valueParser?: GridValueParser<R, V, F>;
151
151
  /**
152
- * Class name that will be added in cells for that column.
152
+ * Class name added to cells in this column.
153
153
  */
154
154
  cellClassName?: GridCellClassNamePropType<R, V>;
155
155
  /**
@@ -159,38 +159,38 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
159
159
  */
160
160
  display?: 'text' | 'flex';
161
161
  /**
162
- * Allows to override the component rendered as cell for this column.
162
+ * Override the component rendered as cell for this column.
163
163
  * @template R, V, F
164
164
  * @param {GridRenderCellParams<R, V, F>} params Object containing parameters for the renderer.
165
165
  * @returns {React.ReactNode} The element to be rendered.
166
166
  */
167
167
  renderCell?: (params: GridRenderCellParams<R, V, F>) => React.ReactNode;
168
168
  /**
169
- * Allows to override the component rendered in edit cell mode for this column.
169
+ * Override the component rendered in edit cell mode for this column.
170
170
  * @param {GridRenderEditCellParams} params Object containing parameters for the renderer.
171
171
  * @returns {React.ReactNode} The element to be rendered.
172
172
  */
173
173
  renderEditCell?: (params: GridRenderEditCellParams<R, V, F>) => React.ReactNode;
174
174
  /**
175
175
  * Callback fired when the edit props of the cell changes.
176
- * It allows to process the props that saved into the state.
176
+ * Processes the props before being saved into the state.
177
177
  * @param {GridPreProcessEditCellProps} params Object containing parameters of the cell being edited.
178
178
  * @returns {GridEditCellProps | Promise<GridEditCellProps>} The new edit cell props.
179
179
  */
180
180
  preProcessEditCellProps?: (params: GridPreProcessEditCellProps) => GridEditCellProps | Promise<GridEditCellProps>;
181
181
  /**
182
- * Class name that will be added in the column header cell.
182
+ * Class name added to the column header cell.
183
183
  */
184
184
  headerClassName?: GridColumnHeaderClassNamePropType;
185
185
  /**
186
- * Allows to render a component in the column header cell.
186
+ * Override the component rendered in the column header cell.
187
187
  * @template R, V, F
188
188
  * @param {GridColumnHeaderParams<R, V, F>} params Object containing parameters for the renderer.
189
189
  * @returns {React.ReactNode} The element to be rendered.
190
190
  */
191
191
  renderHeader?: (params: GridColumnHeaderParams<R, V, F>) => React.ReactNode;
192
192
  /**
193
- * Header cell element alignment.
193
+ * Align column header content.
194
194
  */
195
195
  headerAlign?: GridAlignment;
196
196
  /**
@@ -34,7 +34,7 @@ export interface GridGetRowsResponse {
34
34
  rowCount?: number;
35
35
  /**
36
36
  * Additional `pageInfo` for advanced use-cases.
37
- * `hasNextPage`: When row count is unknown/estimated, `hasNextPage` will be used to check if more records are available on server
37
+ * `hasNextPage`: When row count is unknown/estimated, `hasNextPage` will be used to check if more records are available on server.
38
38
  */
39
39
  pageInfo?: {
40
40
  hasNextPage?: boolean;
@@ -44,25 +44,25 @@ export interface GridGetRowsResponse {
44
44
  export interface GridDataSource {
45
45
  /**
46
46
  * This method will be called when the grid needs to fetch some rows.
47
- * @param {GridGetRowsParams} params The parameters required to fetch the rows
48
- * @returns {Promise<GridGetRowsResponse>} A promise that resolves to the data of type [GridGetRowsResponse]
47
+ * @param {GridGetRowsParams} params The parameters required to fetch the rows.
48
+ * @returns {Promise<GridGetRowsResponse>} A promise that resolves to the data of type [GridGetRowsResponse].
49
49
  */
50
50
  getRows(params: GridGetRowsParams): Promise<GridGetRowsResponse>;
51
51
  /**
52
52
  * This method will be called when the user updates a row [Not yet implemented].
53
- * @param {GridRowModel} updatedRow The updated row
54
- * @returns {Promise<any>} If resolved (synced on the backend), the grid will update the row and mutate the cache
53
+ * @param {GridRowModel} updatedRow The updated row.
54
+ * @returns {Promise<any>} If resolved (synced on the backend), the grid will update the row and mutate the cache.
55
55
  */
56
56
  updateRow?(updatedRow: GridRowModel): Promise<any>;
57
57
  /**
58
58
  * Used to group rows by their parent group. Replaces `getTreeDataPath` used in client side tree-data.
59
- * @param {GridRowModel} row The row to get the group key of
60
- * @returns {string} The group key for the row
59
+ * @param {GridRowModel} row The row to get the group key of.
60
+ * @returns {string} The group key for the row.
61
61
  */
62
62
  getGroupKey?: (row: GridRowModel) => string;
63
63
  /**
64
64
  * Used to determine the number of children a row has on server.
65
- * @param {GridRowModel} row The row to check the number of children
65
+ * @param {GridRowModel} row The row to check the number of children.
66
66
  * @returns {number} The number of children the row has.
67
67
  * If the children count is not available for some reason, but there are some children, `getChildrenCount` should return `-1`.
68
68
  */
@@ -71,14 +71,14 @@ export interface GridDataSource {
71
71
  export interface GridDataSourceCache {
72
72
  /**
73
73
  * Set the cache entry for the given key.
74
- * @param {GridGetRowsParams} key The key of type `GridGetRowsParams`
75
- * @param {GridGetRowsResponse} value The value to be stored in the cache
74
+ * @param {GridGetRowsParams} key The key of type `GridGetRowsParams`.
75
+ * @param {GridGetRowsResponse} value The value to be stored in the cache.
76
76
  */
77
77
  set: (key: GridGetRowsParams, value: GridGetRowsResponse) => void;
78
78
  /**
79
79
  * Get the cache entry for the given key.
80
- * @param {GridGetRowsParams} key The key of type `GridGetRowsParams`
81
- * @returns {GridGetRowsResponse} The value stored in the cache
80
+ * @param {GridGetRowsParams} key The key of type `GridGetRowsParams`.
81
+ * @returns {GridGetRowsResponse} The value stored in the cache.
82
82
  */
83
83
  get: (key: GridGetRowsParams) => GridGetRowsResponse | undefined;
84
84
  /**
@@ -369,6 +369,14 @@ export interface DataGridPropsWithDefaultValues<R extends GridValidRowModel = an
369
369
  * @default false
370
370
  */
371
371
  unstable_rowSpanning: boolean;
372
+ /**
373
+ * If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
374
+ * By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
375
+ * For datasets with a large number of columns, this can cause performance issues.
376
+ * The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
377
+ * @default false
378
+ */
379
+ virtualizeColumnsWithAutoRowHeight: boolean;
372
380
  }
373
381
  /**
374
382
  * The Data Grid props with no default value.
@@ -766,5 +766,13 @@ DataGridRaw.propTypes = {
766
766
  * If `true`, the Data Grid will auto span the cells over the rows having the same value.
767
767
  * @default false
768
768
  */
769
- unstable_rowSpanning: PropTypes.bool
769
+ unstable_rowSpanning: PropTypes.bool,
770
+ /**
771
+ * If `true`, the Data Grid enables column virtualization when `getRowHeight` is set to `() => 'auto'`.
772
+ * By default, column virtualization is disabled when dynamic row height is enabled to measure the row height correctly.
773
+ * For datasets with a large number of columns, this can cause performance issues.
774
+ * The downside of enabling this prop is that the row height will be estimated based the cells that are currently rendered, which can cause row height change when scrolling horizontally.
775
+ * @default false
776
+ */
777
+ virtualizeColumnsWithAutoRowHeight: PropTypes.bool
770
778
  };
@@ -15,7 +15,6 @@ import { useGridSelector, objectShallowCompare } from "../../hooks/utils/useGrid
15
15
  import { useGridApiContext } from "../../hooks/utils/useGridApiContext.js";
16
16
  import { useGridRootProps } from "../../hooks/utils/useGridRootProps.js";
17
17
  import { gridFocusCellSelector } from "../../hooks/features/focus/gridFocusStateSelector.js";
18
- import { MissingRowIdError } from "../../hooks/features/rows/useGridParamsApi.js";
19
18
  import { shouldCellShowLeftBorder, shouldCellShowRightBorder } from "../../utils/cellBorderUtils.js";
20
19
  import { GridPinnedColumnPosition } from "../../hooks/features/columns/gridColumnsInterfaces.js";
21
20
  import { gridRowSpanningHiddenCellsSelector, gridRowSpanningSpannedCellsSelector } from "../../hooks/features/rows/gridRowSpanningSelectors.js";
@@ -114,16 +113,13 @@ const GridCell = /*#__PURE__*/React.forwardRef(function GridCell(props, ref) {
114
113
  // This is required because `.getCellParams` tries to get the `state.rows.tree` entry
115
114
  // associated with `rowId`/`fieldId`, but this selector runs after the state has been
116
115
  // updated, while `rowId`/`fieldId` reference an entry in the old state.
117
- try {
118
- const result = apiRef.current.getCellParams(rowId, field);
119
- result.api = apiRef.current;
120
- return result;
121
- } catch (error) {
122
- if (error instanceof MissingRowIdError) {
123
- return EMPTY_CELL_PARAMS;
124
- }
125
- throw error;
116
+ const row = apiRef.current.getRow(rowId);
117
+ if (!row) {
118
+ return EMPTY_CELL_PARAMS;
126
119
  }
120
+ const result = apiRef.current.getCellParams(rowId, field);
121
+ result.api = apiRef.current;
122
+ return result;
127
123
  }, objectShallowCompare);
128
124
  const isSelected = useGridSelector(apiRef, () => apiRef.current.unstable_applyPipeProcessors('isCellSelected', false, {
129
125
  id: rowId,
@@ -211,6 +207,7 @@ const GridCell = /*#__PURE__*/React.forwardRef(function GridCell(props, ref) {
211
207
  padding: 0,
212
208
  opacity: 0,
213
209
  width: 0,
210
+ height: 0,
214
211
  border: 0
215
212
  };
216
213
  }
@@ -229,6 +226,9 @@ const GridCell = /*#__PURE__*/React.forwardRef(function GridCell(props, ref) {
229
226
  if (rowSpan > 1) {
230
227
  cellStyle.height = `calc(var(--height) * ${rowSpan})`;
231
228
  cellStyle.zIndex = 5;
229
+ if (isLeftPinned || isRightPinned) {
230
+ cellStyle.zIndex = 6;
231
+ }
232
232
  }
233
233
  return cellStyle;
234
234
  }, [width, isNotVisible, styleProp, pinnedOffset, pinnedPosition, isRtl, rowSpan]);
@@ -36,7 +36,7 @@ const GridToolbarColumnsButton = /*#__PURE__*/React.forwardRef(function GridTool
36
36
  return /*#__PURE__*/_jsx(rootProps.slots.baseTooltip, _extends({
37
37
  title: apiRef.current.getLocaleText('toolbarColumnsLabel'),
38
38
  enterDelay: 1000
39
- }, tooltipProps, rootProps.slotProps?.baseTooltip, {
39
+ }, rootProps.slotProps?.baseTooltip, tooltipProps, {
40
40
  children: /*#__PURE__*/_jsx(rootProps.slots.baseButton, _extends({
41
41
  ref: ref,
42
42
  id: columnButtonId,
@@ -45,10 +45,9 @@ const GridToolbarColumnsButton = /*#__PURE__*/React.forwardRef(function GridTool
45
45
  "aria-haspopup": "menu",
46
46
  "aria-expanded": isOpen,
47
47
  "aria-controls": isOpen ? columnPanelId : undefined,
48
- startIcon: /*#__PURE__*/_jsx(rootProps.slots.columnSelectorIcon, {})
49
- }, buttonProps, {
48
+ startIcon: /*#__PURE__*/_jsx(rootProps.slots.columnSelectorIcon, {}),
50
49
  onClick: showColumns
51
- }, rootProps.slotProps?.baseButton, {
50
+ }, rootProps.slotProps?.baseButton, buttonProps, {
52
51
  children: apiRef.current.getLocaleText('toolbarColumns')
53
52
  }))
54
53
  }));
@@ -85,7 +85,7 @@ const GridToolbarDensitySelector = /*#__PURE__*/React.forwardRef(function GridTo
85
85
  children: [/*#__PURE__*/_jsx(rootProps.slots.baseTooltip, _extends({
86
86
  title: apiRef.current.getLocaleText('toolbarDensityLabel'),
87
87
  enterDelay: 1000
88
- }, tooltipProps, rootProps.slotProps?.baseTooltip, {
88
+ }, rootProps.slotProps?.baseTooltip, tooltipProps, {
89
89
  children: /*#__PURE__*/_jsx(rootProps.slots.baseButton, _extends({
90
90
  ref: handleRef,
91
91
  size: "small",
@@ -94,10 +94,9 @@ const GridToolbarDensitySelector = /*#__PURE__*/React.forwardRef(function GridTo
94
94
  "aria-haspopup": "menu",
95
95
  "aria-expanded": open,
96
96
  "aria-controls": open ? densityMenuId : undefined,
97
- id: densityButtonId
98
- }, buttonProps, {
97
+ id: densityButtonId,
99
98
  onClick: handleDensitySelectorOpen
100
- }, rootProps.slotProps?.baseButton, {
99
+ }, rootProps.slotProps?.baseButton, buttonProps, {
101
100
  children: apiRef.current.getLocaleText('toolbarDensity')
102
101
  }))
103
102
  })), /*#__PURE__*/_jsx(GridMenu, {
@@ -43,7 +43,7 @@ const GridToolbarExportContainer = /*#__PURE__*/React.forwardRef(function GridTo
43
43
  children: [/*#__PURE__*/_jsx(rootProps.slots.baseTooltip, _extends({
44
44
  title: apiRef.current.getLocaleText('toolbarExportLabel'),
45
45
  enterDelay: 1000
46
- }, tooltipProps, rootProps.slotProps?.baseTooltip, {
46
+ }, rootProps.slotProps?.baseTooltip, tooltipProps, {
47
47
  children: /*#__PURE__*/_jsx(rootProps.slots.baseButton, _extends({
48
48
  ref: handleRef,
49
49
  size: "small",
@@ -52,10 +52,9 @@ const GridToolbarExportContainer = /*#__PURE__*/React.forwardRef(function GridTo
52
52
  "aria-label": apiRef.current.getLocaleText('toolbarExportLabel'),
53
53
  "aria-haspopup": "menu",
54
54
  "aria-controls": open ? exportMenuId : undefined,
55
- id: exportButtonId
56
- }, buttonProps, {
55
+ id: exportButtonId,
57
56
  onClick: handleMenuOpen
58
- }, rootProps.slotProps?.baseButton, {
57
+ }, rootProps.slotProps?.baseButton, buttonProps, {
59
58
  children: apiRef.current.getLocaleText('toolbarExport')
60
59
  }))
61
60
  })), /*#__PURE__*/_jsx(GridMenu, {
@@ -37,6 +37,7 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
37
37
  } = props;
38
38
  const buttonProps = slotProps.button || {};
39
39
  const tooltipProps = slotProps.tooltip || {};
40
+ const badgeProps = slotProps.badge || {};
40
41
  const apiRef = useGridApiContext();
41
42
  const rootProps = useGridRootProps();
42
43
  const activeFilters = useGridSelector(apiRef, gridFilterActiveItemsSelector);
@@ -94,7 +95,7 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
94
95
  return /*#__PURE__*/_jsx(rootProps.slots.baseTooltip, _extends({
95
96
  title: tooltipContentNode,
96
97
  enterDelay: 1000
97
- }, tooltipProps, rootProps.slotProps?.baseTooltip, {
98
+ }, rootProps.slotProps?.baseTooltip, tooltipProps, {
98
99
  children: /*#__PURE__*/_jsx(rootProps.slots.baseButton, _extends({
99
100
  ref: ref,
100
101
  id: filterButtonId,
@@ -103,14 +104,14 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
103
104
  "aria-controls": isOpen ? filterPanelId : undefined,
104
105
  "aria-expanded": isOpen,
105
106
  "aria-haspopup": true,
106
- startIcon: /*#__PURE__*/_jsx(rootProps.slots.baseBadge, {
107
+ startIcon: /*#__PURE__*/_jsx(rootProps.slots.baseBadge, _extends({
107
108
  badgeContent: activeFilters.length,
108
- color: "primary",
109
+ color: "primary"
110
+ }, rootProps.slotProps?.baseBadge, badgeProps, {
109
111
  children: /*#__PURE__*/_jsx(rootProps.slots.openFilterButtonIcon, {})
110
- })
111
- }, buttonProps, {
112
+ })),
112
113
  onClick: toggleFilter
113
- }, rootProps.slotProps?.baseButton, {
114
+ }, rootProps.slotProps?.baseButton, buttonProps, {
114
115
  children: apiRef.current.getLocaleText('toolbarFilters')
115
116
  }))
116
117
  }));
@@ -78,6 +78,7 @@ function GridToolbarQuickFilter(props) {
78
78
  apiRef.current.setQuickFilterValues(newQuickFilterValues);
79
79
  }, [apiRef, quickFilterParser]);
80
80
  const debouncedUpdateSearchValue = React.useMemo(() => debounce(updateSearchValue, debounceMs), [updateSearchValue, debounceMs]);
81
+ React.useEffect(() => debouncedUpdateSearchValue.clear, [debouncedUpdateSearchValue]);
81
82
  const handleSearchValueChange = React.useCallback(event => {
82
83
  const newSearchValue = event.target.value;
83
84
  setSearchValue(newSearchValue);
@@ -56,5 +56,6 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES = {
56
56
  sortingMode: 'client',
57
57
  sortingOrder: ['asc', 'desc', null],
58
58
  throttleRowsMs: 0,
59
- unstable_rowSpanning: false
59
+ unstable_rowSpanning: false,
60
+ virtualizeColumnsWithAutoRowHeight: false
60
61
  };
@@ -283,7 +283,7 @@ export const useGridColumnHeaders = props => {
283
283
  fields: headerInfo.fields,
284
284
  colIndex: headerInfo.colIndex,
285
285
  depth: depth,
286
- isLastColumn: headerInfo.colIndex === visibleColumns.length - headerInfo.fields.length,
286
+ isLastColumn: index === visibleColumnGroupHeader.length - 1,
287
287
  maxDepth: headerGroupingMaxDepth,
288
288
  height: dimensions.groupHeaderHeight,
289
289
  hasFocus: hasFocus,
@@ -66,6 +66,7 @@ export function useGridDimensions(apiRef, props) {
66
66
  const rightPinnedWidth = pinnedColumns.right.reduce((w, col) => w + col.computedWidth, 0);
67
67
  const [savedSize, setSavedSize] = React.useState();
68
68
  const debouncedSetSavedSize = React.useMemo(() => throttle(setSavedSize, props.resizeThrottleMs), [props.resizeThrottleMs]);
69
+ React.useEffect(() => debouncedSetSavedSize.clear, [debouncedSetSavedSize]);
69
70
  const previousSize = React.useRef();
70
71
  const getRootDimensions = () => apiRef.current.state.dimensions;
71
72
  const setDimensions = useEventCallback(dimensions => {
@@ -238,7 +239,7 @@ export function useGridDimensions(apiRef, props) {
238
239
  rootDimensionsRef.current = size;
239
240
 
240
241
  // jsdom has no layout capabilities
241
- const isJSDOM = /jsdom/.test(window.navigator.userAgent);
242
+ const isJSDOM = /jsdom|HappyDOM/.test(window.navigator.userAgent);
242
243
  if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
243
244
  logger.error(['The parent DOM element of the Data Grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
244
245
  errorShown.current = true;
@@ -7,6 +7,7 @@ export * from "./density/index.js";
7
7
  export * from "./editing/index.js";
8
8
  export * from "./filter/index.js";
9
9
  export * from "./focus/index.js";
10
+ export * from "./listView/index.js";
10
11
  export * from "./pagination/index.js";
11
12
  export * from "./preferencesPanel/index.js";
12
13
  export * from "./rows/index.js";
@@ -1,4 +1,6 @@
1
1
  /**
2
- * Get a list column definition
2
+ * Get the list column definition
3
+ * @category List View
4
+ * @ignore - Do not document
3
5
  */
4
6
  export const gridListColumnSelector = state => state.listViewColumn;
@@ -0,0 +1 @@
1
+ export * from "./gridListViewSelectors.js";
@@ -248,11 +248,7 @@ export const useGridRowSelection = (apiRef, props) => {
248
248
  /*
249
249
  * EVENTS
250
250
  */
251
- const isFirstRender = React.useRef(true);
252
251
  const removeOutdatedSelection = React.useCallback((sortModelUpdated = false) => {
253
- if (isFirstRender.current) {
254
- return;
255
- }
256
252
  const currentSelection = gridRowSelectionStateSelector(apiRef.current.state);
257
253
  const rowsLookup = gridRowsLookupSelector(apiRef);
258
254
  const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
@@ -480,9 +476,4 @@ export const useGridRowSelection = (apiRef, props) => {
480
476
  React.useEffect(() => {
481
477
  runIfRowSelectionIsEnabled(removeOutdatedSelection);
482
478
  }, [removeOutdatedSelection, runIfRowSelectionIsEnabled]);
483
- React.useEffect(() => {
484
- if (isFirstRender.current) {
485
- isFirstRender.current = false;
486
- }
487
- }, []);
488
479
  };
@@ -4,8 +4,8 @@ import * as ReactDOM from 'react-dom';
4
4
  import { unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
5
5
  import useLazyRef from '@mui/utils/useLazyRef';
6
6
  import useTimeout from '@mui/utils/useTimeout';
7
- import { useResizeObserver } from '@mui/x-internals/useResizeObserver';
8
7
  import { useRtl } from '@mui/system/RtlProvider';
8
+ import reactMajor from '@mui/x-internals/reactMajor';
9
9
  import { useGridPrivateApiContext } from "../../utils/useGridPrivateApiContext.js";
10
10
  import { useGridRootProps } from "../../utils/useGridRootProps.js";
11
11
  import { useGridSelector } from "../../utils/useGridSelector.js";
@@ -48,7 +48,7 @@ const createScrollCache = (isRtl, rowBufferPx, columnBufferPx, verticalBuffer, h
48
48
  let isJSDOM = false;
49
49
  try {
50
50
  if (typeof window !== 'undefined') {
51
- isJSDOM = /jsdom/.test(window.navigator.userAgent);
51
+ isJSDOM = /jsdom|HappyDOM/.test(window.navigator.userAgent);
52
52
  }
53
53
  } catch (_) {
54
54
  /* ignore */
@@ -86,7 +86,44 @@ export const useGridVirtualScroller = () => {
86
86
  const contentHeight = dimensions.contentSize.height;
87
87
  const columnsTotalWidth = dimensions.columnsTotalWidth;
88
88
  const hasColSpan = useGridSelector(apiRef, gridHasColSpanSelector);
89
- useResizeObserver(mainRef, () => apiRef.current.resize());
89
+ const mainRefCallback = React.useCallback(node => {
90
+ mainRef.current = node;
91
+ if (!node) {
92
+ return undefined;
93
+ }
94
+ const initialRect = node.getBoundingClientRect();
95
+ let lastSize = {
96
+ width: initialRect.width,
97
+ height: initialRect.height
98
+ };
99
+ apiRef.current.publishEvent('resize', lastSize);
100
+ if (typeof ResizeObserver === 'undefined') {
101
+ return undefined;
102
+ }
103
+ const observer = new ResizeObserver(entries => {
104
+ const entry = entries[0];
105
+ if (!entry) {
106
+ return;
107
+ }
108
+ const newSize = {
109
+ width: entry.contentRect.width,
110
+ height: entry.contentRect.height
111
+ };
112
+ if (newSize.width === lastSize.width && newSize.height === lastSize.height) {
113
+ return;
114
+ }
115
+ apiRef.current.publishEvent('resize', newSize);
116
+ lastSize = newSize;
117
+ });
118
+ observer.observe(node);
119
+ if (reactMajor >= 19) {
120
+ return () => {
121
+ mainRef.current = null;
122
+ observer.disconnect();
123
+ };
124
+ }
125
+ return undefined;
126
+ }, [apiRef, mainRef]);
90
127
 
91
128
  /*
92
129
  * Scroll context logic
@@ -137,9 +174,13 @@ export const useGridVirtualScroller = () => {
137
174
  previousContextScrollPosition.current = scrollPosition.current;
138
175
  }, [apiRef, dimensions.isReady]);
139
176
  const triggerUpdateRenderContext = useEventCallback(() => {
177
+ const scroller = scrollerRef.current;
178
+ if (!scroller) {
179
+ return undefined;
180
+ }
140
181
  const newScroll = {
141
- top: scrollerRef.current.scrollTop,
142
- left: scrollerRef.current.scrollLeft
182
+ top: scroller.scrollTop,
183
+ left: scroller.scrollLeft
143
184
  };
144
185
  const dx = newScroll.left - scrollPosition.current.left;
145
186
  const dy = newScroll.top - scrollPosition.current.top;
@@ -389,10 +430,6 @@ export const useGridVirtualScroller = () => {
389
430
  React.useEffect(() => {
390
431
  apiRef.current.publishEvent('virtualScrollerContentSizeChange');
391
432
  }, [apiRef, contentSize]);
392
- useEnhancedEffect(() => {
393
- // FIXME: Is this really necessary?
394
- apiRef.current.resize();
395
- }, [apiRef, rowsMeta.currentPageTotalHeight]);
396
433
  useEnhancedEffect(() => {
397
434
  // TODO a scroll reset should not be necessary
398
435
  if (enabledForColumns) {
@@ -428,7 +465,7 @@ export const useGridVirtualScroller = () => {
428
465
  setPanels,
429
466
  getRows,
430
467
  getContainerProps: () => ({
431
- ref: mainRef
468
+ ref: mainRefCallback
432
469
  }),
433
470
  getScrollerProps: () => ({
434
471
  ref: scrollerRef,
@@ -485,7 +522,8 @@ function inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns) {
485
522
  pinnedColumns: gridVisiblePinnedColumnDefinitionsSelector(apiRef),
486
523
  visibleColumns,
487
524
  hiddenCellsOriginMap,
488
- listView: rootProps.unstable_listView ?? false
525
+ listView: rootProps.unstable_listView ?? false,
526
+ virtualizeColumnsWithAutoRowHeight: rootProps.virtualizeColumnsWithAutoRowHeight
489
527
  };
490
528
  }
491
529
  function computeRenderContext(inputs, scrollPosition, scrollCache) {
@@ -533,11 +571,13 @@ function computeRenderContext(inputs, scrollPosition, scrollCache) {
533
571
  positions: inputs.rowsMeta.positions,
534
572
  lastSize: inputs.lastRowHeight
535
573
  });
536
- for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
537
- const row = inputs.rows[i];
538
- hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
574
+ if (!inputs.virtualizeColumnsWithAutoRowHeight) {
575
+ for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
576
+ const row = inputs.rows[i];
577
+ hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
578
+ }
539
579
  }
540
- if (!hasRowWithAutoHeight) {
580
+ if (!hasRowWithAutoHeight || inputs.virtualizeColumnsWithAutoRowHeight) {
541
581
  firstColumnIndex = binarySearch(realLeft, inputs.columnPositions, {
542
582
  atStart: true,
543
583
  lastPosition: inputs.columnsTotalWidth
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.22.3
2
+ * @mui/x-data-grid v7.23.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the