@mui/x-data-grid 7.0.0-beta.4 → 7.0.0-beta.6

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 (116) hide show
  1. package/CHANGELOG.md +271 -61
  2. package/DataGrid/DataGrid.js +2 -0
  3. package/colDef/gridBooleanOperators.js +1 -1
  4. package/components/GridPinnedRows.d.ts +1 -2
  5. package/components/GridRow.d.ts +7 -9
  6. package/components/GridRow.js +41 -54
  7. package/components/cell/GridCell.d.ts +2 -3
  8. package/components/cell/GridCell.js +10 -10
  9. package/components/cell/GridSkeletonCell.d.ts +3 -2
  10. package/components/cell/GridSkeletonCell.js +14 -6
  11. package/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  12. package/components/columnsManagement/GridColumnsManagement.js +1 -1
  13. package/components/containers/GridRootStyles.js +9 -4
  14. package/components/virtualization/GridBottomContainer.js +1 -1
  15. package/components/virtualization/GridTopContainer.js +1 -1
  16. package/components/virtualization/GridVirtualScroller.js +7 -5
  17. package/components/virtualization/GridVirtualScrollerRenderZone.js +9 -3
  18. package/hooks/core/pipeProcessing/useGridPipeProcessing.js +22 -20
  19. package/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
  20. package/hooks/features/columns/gridColumnsSelector.d.ts +6 -0
  21. package/hooks/features/columns/gridColumnsSelector.js +8 -1
  22. package/hooks/features/columns/useGridColumns.js +4 -0
  23. package/hooks/features/dimensions/useGridDimensions.js +1 -0
  24. package/hooks/features/editing/useGridRowEditing.js +1 -2
  25. package/hooks/features/filter/useGridFilter.js +2 -2
  26. package/hooks/features/rows/useGridParamsApi.js +6 -10
  27. package/hooks/features/rows/useGridRows.js +8 -4
  28. package/hooks/features/rows/useGridRowsMeta.js +5 -13
  29. package/hooks/features/sorting/gridSortingUtils.js +9 -1
  30. package/hooks/features/sorting/useGridSorting.js +2 -2
  31. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +0 -9
  32. package/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
  33. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +3 -0
  34. package/hooks/features/virtualization/useGridVirtualScroller.js +88 -138
  35. package/hooks/features/virtualization/useGridVirtualization.d.ts +0 -8
  36. package/hooks/features/virtualization/useGridVirtualization.js +1 -6
  37. package/hooks/utils/useTimeout.d.ts +5 -3
  38. package/hooks/utils/useTimeout.js +13 -5
  39. package/index.js +1 -1
  40. package/internals/index.d.ts +1 -1
  41. package/internals/index.js +1 -1
  42. package/models/api/gridApiCommon.d.ts +2 -1
  43. package/models/api/gridInfiniteLoaderApi.d.ts +6 -0
  44. package/models/api/gridInfiniteLoaderApi.js +1 -0
  45. package/models/colDef/gridColDef.d.ts +7 -0
  46. package/modern/DataGrid/DataGrid.js +2 -0
  47. package/modern/colDef/gridBooleanOperators.js +1 -1
  48. package/modern/components/GridRow.js +40 -53
  49. package/modern/components/cell/GridCell.js +10 -10
  50. package/modern/components/cell/GridSkeletonCell.js +14 -6
  51. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  52. package/modern/components/columnsManagement/GridColumnsManagement.js +1 -1
  53. package/modern/components/containers/GridRootStyles.js +9 -4
  54. package/modern/components/virtualization/GridBottomContainer.js +1 -1
  55. package/modern/components/virtualization/GridTopContainer.js +1 -1
  56. package/modern/components/virtualization/GridVirtualScroller.js +7 -5
  57. package/modern/components/virtualization/GridVirtualScrollerRenderZone.js +8 -3
  58. package/modern/hooks/core/pipeProcessing/useGridPipeProcessing.js +22 -20
  59. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
  60. package/modern/hooks/features/columns/gridColumnsSelector.js +8 -1
  61. package/modern/hooks/features/columns/useGridColumns.js +2 -0
  62. package/modern/hooks/features/dimensions/useGridDimensions.js +1 -0
  63. package/modern/hooks/features/editing/useGridRowEditing.js +1 -2
  64. package/modern/hooks/features/filter/useGridFilter.js +2 -2
  65. package/modern/hooks/features/rows/useGridParamsApi.js +6 -10
  66. package/modern/hooks/features/rows/useGridRows.js +8 -4
  67. package/modern/hooks/features/rows/useGridRowsMeta.js +5 -13
  68. package/modern/hooks/features/sorting/gridSortingUtils.js +9 -1
  69. package/modern/hooks/features/sorting/useGridSorting.js +2 -2
  70. package/modern/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
  71. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +85 -136
  72. package/modern/hooks/features/virtualization/useGridVirtualization.js +1 -6
  73. package/modern/hooks/utils/useTimeout.js +13 -5
  74. package/modern/index.js +1 -1
  75. package/modern/internals/index.js +1 -1
  76. package/modern/models/api/gridInfiniteLoaderApi.js +1 -0
  77. package/modern/utils/createSelector.js +12 -20
  78. package/modern/utils/utils.js +9 -0
  79. package/node/DataGrid/DataGrid.js +1 -0
  80. package/node/colDef/gridBooleanOperators.js +1 -1
  81. package/node/components/GridRow.js +40 -53
  82. package/node/components/cell/GridCell.js +10 -10
  83. package/node/components/cell/GridSkeletonCell.js +15 -7
  84. package/node/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
  85. package/node/components/columnsManagement/GridColumnsManagement.js +1 -1
  86. package/node/components/containers/GridRootStyles.js +9 -4
  87. package/node/components/virtualization/GridBottomContainer.js +1 -1
  88. package/node/components/virtualization/GridTopContainer.js +1 -1
  89. package/node/components/virtualization/GridVirtualScroller.js +7 -5
  90. package/node/components/virtualization/GridVirtualScrollerRenderZone.js +7 -2
  91. package/node/hooks/core/pipeProcessing/useGridPipeProcessing.js +22 -20
  92. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +8 -5
  93. package/node/hooks/features/columns/gridColumnsSelector.js +9 -2
  94. package/node/hooks/features/columns/useGridColumns.js +2 -0
  95. package/node/hooks/features/dimensions/useGridDimensions.js +1 -0
  96. package/node/hooks/features/editing/useGridRowEditing.js +1 -2
  97. package/node/hooks/features/filter/useGridFilter.js +2 -2
  98. package/node/hooks/features/rows/useGridParamsApi.js +6 -10
  99. package/node/hooks/features/rows/useGridRows.js +8 -4
  100. package/node/hooks/features/rows/useGridRowsMeta.js +5 -13
  101. package/node/hooks/features/sorting/gridSortingUtils.js +9 -1
  102. package/node/hooks/features/sorting/useGridSorting.js +2 -2
  103. package/node/hooks/features/virtualization/gridVirtualizationSelectors.js +1 -8
  104. package/node/hooks/features/virtualization/useGridVirtualScroller.js +86 -136
  105. package/node/hooks/features/virtualization/useGridVirtualization.js +2 -7
  106. package/node/hooks/utils/useTimeout.js +13 -4
  107. package/node/index.js +1 -1
  108. package/node/internals/index.js +0 -7
  109. package/node/models/api/gridInfiniteLoaderApi.js +5 -0
  110. package/node/utils/createSelector.js +14 -23
  111. package/node/utils/utils.js +12 -1
  112. package/package.json +2 -2
  113. package/utils/createSelector.d.ts +0 -1
  114. package/utils/createSelector.js +12 -22
  115. package/utils/utils.d.ts +4 -0
  116. package/utils/utils.js +9 -0
@@ -3,24 +3,23 @@ import * as React from 'react';
3
3
  import * as ReactDOM from 'react-dom';
4
4
  import { unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
5
5
  import { useTheme } from '@mui/material/styles';
6
- import { defaultMemoize } from 'reselect';
7
6
  import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
8
7
  import { useGridRootProps } from '../../utils/useGridRootProps';
9
8
  import { useGridSelector } from '../../utils/useGridSelector';
10
- import { useLazyRef } from '../../utils/useLazyRef';
11
9
  import { useResizeObserver } from '../../utils/useResizeObserver';
12
10
  import { useRunOnce } from '../../utils/useRunOnce';
13
- import { gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, gridColumnPositionsSelector } from '../columns/gridColumnsSelector';
11
+ import { gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, gridColumnPositionsSelector, gridHasColSpanSelector } from '../columns/gridColumnsSelector';
14
12
  import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors';
15
13
  import { gridPinnedRowsSelector } from '../rows/gridRowsSelector';
16
14
  import { gridFocusCellSelector, gridTabIndexCellSelector } from '../focus/gridFocusStateSelector';
17
15
  import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows';
18
- import { clamp } from '../../../utils/utils';
16
+ import { useGridApiEventHandler } from '../../utils';
17
+ import { clamp, range } from '../../../utils/utils';
19
18
  import { selectedIdsLookupSelector } from '../rowSelection/gridRowSelectionSelector';
20
19
  import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
21
20
  import { getFirstNonSpannedColumnToRender } from '../columns/gridColumnsUtils';
22
21
  import { getMinimalContentHeight } from '../rows/gridRowsUtils';
23
- import { gridOffsetsSelector, gridRenderContextSelector, gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
22
+ import { gridRenderContextSelector, gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
24
23
  import { EMPTY_RENDER_CONTEXT } from './useGridVirtualization';
25
24
  import { jsx as _jsx } from "react/jsx-runtime";
26
25
  export const EMPTY_DETAIL_PANELS = Object.freeze(new Map());
@@ -49,40 +48,29 @@ export const useGridVirtualScroller = () => {
49
48
  const scrollbarHorizontalRef = React.useRef(null);
50
49
  const contentHeight = dimensions.contentSize.height;
51
50
  const columnsTotalWidth = dimensions.columnsTotalWidth;
51
+ const hasColSpan = useGridSelector(apiRef, gridHasColSpanSelector);
52
52
  useResizeObserver(mainRef, () => apiRef.current.resize());
53
53
  const previousContext = React.useRef(EMPTY_RENDER_CONTEXT);
54
54
  const previousRowContext = React.useRef(EMPTY_RENDER_CONTEXT);
55
- const offsets = useGridSelector(apiRef, gridOffsetsSelector);
56
55
  const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
57
56
  const scrollPosition = React.useRef({
58
57
  top: 0,
59
58
  left: 0
60
59
  }).current;
61
60
  const prevTotalWidth = React.useRef(columnsTotalWidth);
62
- const getRenderedColumns = useLazyRef(createGetRenderedColumns).current;
63
- const indexOfRowWithFocusedCell = React.useMemo(() => {
64
- if (cellFocus !== null) {
65
- return currentPage.rows.findIndex(row => row.id === cellFocus.id);
66
- }
67
- return -1;
68
- }, [cellFocus, currentPage.rows]);
69
- const indexOfColumnWithFocusedCell = React.useMemo(() => {
70
- if (cellFocus !== null) {
71
- return visibleColumns.findIndex(column => column.field === cellFocus.field);
72
- }
73
- return -1;
74
- }, [cellFocus, visibleColumns]);
61
+ const focusedCell = {
62
+ rowIndex: React.useMemo(() => cellFocus ? currentPage.rows.findIndex(row => row.id === cellFocus.id) : -1, [cellFocus, currentPage.rows]),
63
+ columnIndex: React.useMemo(() => cellFocus ? visibleColumns.findIndex(column => column.field === cellFocus.field) : -1, [cellFocus, visibleColumns])
64
+ };
75
65
  const updateRenderContext = React.useCallback((nextRenderContext, rawRenderContext) => {
76
66
  if (areRenderContextsEqual(nextRenderContext, apiRef.current.state.virtualization.renderContext)) {
77
67
  return;
78
68
  }
79
69
  const didRowsIntervalChange = nextRenderContext.firstRowIndex !== previousRowContext.current.firstRowIndex || nextRenderContext.lastRowIndex !== previousRowContext.current.lastRowIndex;
80
- const nextOffsets = computeOffsets(apiRef, nextRenderContext, theme.direction, pinnedColumns.left.length);
81
70
  apiRef.current.setState(state => {
82
71
  return _extends({}, state, {
83
72
  virtualization: _extends({}, state.virtualization, {
84
- renderContext: nextRenderContext,
85
- offsets: nextOffsets
73
+ renderContext: nextRenderContext
86
74
  })
87
75
  });
88
76
  });
@@ -96,7 +84,7 @@ export const useGridVirtualScroller = () => {
96
84
  }
97
85
  previousContext.current = rawRenderContext;
98
86
  prevTotalWidth.current = dimensions.columnsTotalWidth;
99
- }, [apiRef, pinnedColumns.left.length, theme.direction, dimensions.isReady, dimensions.columnsTotalWidth]);
87
+ }, [apiRef, dimensions.isReady, dimensions.columnsTotalWidth]);
100
88
  const triggerUpdateRenderContext = () => {
101
89
  const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
102
90
  const [nextRenderContext, rawRenderContext] = computeRenderContext(inputs, scrollPosition);
@@ -157,10 +145,13 @@ export const useGridVirtualScroller = () => {
157
145
  const handleTouchMove = useEventCallback(event => {
158
146
  apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
159
147
  });
160
- const minFirstColumn = pinnedColumns.left.length;
161
- const maxLastColumn = visibleColumns.length - pinnedColumns.right.length;
162
148
  const getRows = (params = {}) => {
163
- var _params$rows, _rootProps$slotProps;
149
+ var _params$renderContext, _params$rows, _rootProps$slotProps;
150
+ if (!params.rows && !currentPage.range) {
151
+ return [];
152
+ }
153
+ const columnPositions = gridColumnPositionsSelector(apiRef);
154
+ const currentRenderContext = (_params$renderContext = params.renderContext) != null ? _params$renderContext : renderContext;
164
155
  const isLastSection = !hasBottomPinnedRows && params.position === undefined || hasBottomPinnedRows && params.position === 'bottom';
165
156
  const isPinnedSection = params.position !== undefined;
166
157
  let rowIndexOffset;
@@ -177,78 +168,58 @@ export const useGridVirtualScroller = () => {
177
168
  rowIndexOffset = pinnedRows.top.length;
178
169
  break;
179
170
  }
180
- const firstRowToRender = renderContext.firstRowIndex;
181
- const lastRowToRender = renderContext.lastRowIndex;
182
- const firstColumnToRender = renderContext.firstColumnIndex;
183
- const lastColumnToRender = renderContext.lastColumnIndex;
184
- if (!params.rows && !currentPage.range) {
185
- return [];
186
- }
187
- const renderedRows = (_params$rows = params.rows) != null ? _params$rows : currentPage.rows.slice(firstRowToRender, lastRowToRender);
188
-
189
- // If the selected row is not within the current range of rows being displayed,
190
- // we need to render it at either the top or bottom of the rows,
191
- // depending on whether it is above or below the range.
192
- let isRowWithFocusedCellNotInRange = false;
193
- if (!isPinnedSection && indexOfRowWithFocusedCell > -1 && (firstRowToRender > indexOfRowWithFocusedCell || lastRowToRender < indexOfRowWithFocusedCell)) {
194
- isRowWithFocusedCellNotInRange = true;
195
- const rowWithFocusedCell = currentPage.rows[indexOfRowWithFocusedCell];
196
- if (indexOfRowWithFocusedCell > firstRowToRender) {
197
- renderedRows.push(rowWithFocusedCell);
198
- } else {
199
- renderedRows.unshift(rowWithFocusedCell);
171
+ const rowModels = (_params$rows = params.rows) != null ? _params$rows : currentPage.rows;
172
+ const firstRowToRender = currentRenderContext.firstRowIndex;
173
+ const lastRowToRender = Math.min(currentRenderContext.lastRowIndex, rowModels.length);
174
+ const rowIndexes = params.rows ? range(0, params.rows.length) : range(firstRowToRender, lastRowToRender);
175
+ let virtualRowIndex = -1;
176
+ if (!isPinnedSection && focusedCell.rowIndex !== -1) {
177
+ if (focusedCell.rowIndex < firstRowToRender) {
178
+ virtualRowIndex = focusedCell.rowIndex;
179
+ rowIndexes.unshift(virtualRowIndex);
200
180
  }
201
- }
202
- let isColumnWihFocusedCellNotInRange = false;
203
- if (!isPinnedSection && (firstColumnToRender > indexOfColumnWithFocusedCell || lastColumnToRender < indexOfColumnWithFocusedCell)) {
204
- isColumnWihFocusedCellNotInRange = true;
205
- }
206
- const {
207
- focusedCellColumnIndexNotInRange,
208
- renderedColumns
209
- } = getRenderedColumns(visibleColumns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, isColumnWihFocusedCellNotInRange ? indexOfColumnWithFocusedCell : -1);
210
- renderedRows.forEach(row => {
211
- apiRef.current.calculateColSpan({
212
- rowId: row.id,
213
- minFirstColumn,
214
- maxLastColumn,
215
- columns: visibleColumns
216
- });
217
- if (pinnedColumns.left.length > 0) {
218
- apiRef.current.calculateColSpan({
219
- rowId: row.id,
220
- minFirstColumn: 0,
221
- maxLastColumn: pinnedColumns.left.length,
222
- columns: visibleColumns
223
- });
224
- }
225
- if (pinnedColumns.right.length > 0) {
226
- apiRef.current.calculateColSpan({
227
- rowId: row.id,
228
- minFirstColumn: visibleColumns.length - pinnedColumns.right.length,
229
- maxLastColumn: visibleColumns.length,
230
- columns: visibleColumns
231
- });
181
+ if (focusedCell.rowIndex >= lastRowToRender) {
182
+ virtualRowIndex = focusedCell.rowIndex;
183
+ rowIndexes.push(virtualRowIndex);
232
184
  }
233
- });
185
+ }
234
186
  const rows = [];
235
187
  const rowProps = (_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.row;
236
- let isRowWithFocusedCellRendered = false;
237
- for (let i = 0; i < renderedRows.length; i += 1) {
188
+ rowIndexes.forEach(rowIndexInPage => {
238
189
  var _currentPage$range;
239
190
  const {
240
191
  id,
241
192
  model
242
- } = renderedRows[i];
243
- const rowIndexInPage = ((currentPage == null || (_currentPage$range = currentPage.range) == null ? void 0 : _currentPage$range.firstRowIndex) || 0) + firstRowToRender + i;
244
- let index = rowIndexOffset + rowIndexInPage;
245
- if (isRowWithFocusedCellNotInRange && (cellFocus == null ? void 0 : cellFocus.id) === id) {
246
- index = indexOfRowWithFocusedCell;
247
- isRowWithFocusedCellRendered = true;
248
- } else if (isRowWithFocusedCellRendered) {
249
- index -= 1;
193
+ } = rowModels[rowIndexInPage];
194
+
195
+ // NOTE: This is an expensive feature, the colSpan code could be optimized.
196
+ if (hasColSpan) {
197
+ const minFirstColumn = pinnedColumns.left.length;
198
+ const maxLastColumn = visibleColumns.length - pinnedColumns.right.length;
199
+ apiRef.current.calculateColSpan({
200
+ rowId: id,
201
+ minFirstColumn,
202
+ maxLastColumn,
203
+ columns: visibleColumns
204
+ });
205
+ if (pinnedColumns.left.length > 0) {
206
+ apiRef.current.calculateColSpan({
207
+ rowId: id,
208
+ minFirstColumn: 0,
209
+ maxLastColumn: pinnedColumns.left.length,
210
+ columns: visibleColumns
211
+ });
212
+ }
213
+ if (pinnedColumns.right.length > 0) {
214
+ apiRef.current.calculateColSpan({
215
+ rowId: id,
216
+ minFirstColumn: visibleColumns.length - pinnedColumns.right.length,
217
+ maxLastColumn: visibleColumns.length,
218
+ columns: visibleColumns
219
+ });
220
+ }
250
221
  }
251
- const isRowNotVisible = isRowWithFocusedCellNotInRange && cellFocus.id === id;
222
+ const hasFocus = (cellFocus == null ? void 0 : cellFocus.id) === id;
252
223
  const baseRowHeight = !apiRef.current.rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
253
224
  let isSelected;
254
225
  if (selectedRowsLookup[id] == null) {
@@ -264,47 +235,52 @@ export const useGridVirtualScroller = () => {
264
235
  if (isLastSection) {
265
236
  if (!isPinnedSection) {
266
237
  const lastIndex = currentPage.rows.length - 1;
267
- const isLastVisibleRowIndex = isRowWithFocusedCellNotInRange ? firstRowToRender + i === lastIndex + 1 : firstRowToRender + i === lastIndex;
238
+ const isLastVisibleRowIndex = rowIndexInPage === lastIndex;
268
239
  if (isLastVisibleRowIndex) {
269
240
  isLastVisible = true;
270
241
  }
271
242
  } else {
272
- isLastVisible = i === renderedRows.length - 1;
243
+ isLastVisible = rowIndexInPage === rowModels.length - 1;
273
244
  }
274
245
  }
275
- const focusedCell = cellFocus !== null && cellFocus.id === id ? cellFocus.field : null;
276
- const columnWithFocusedCellNotInRange = focusedCellColumnIndexNotInRange !== undefined && visibleColumns[focusedCellColumnIndexNotInRange];
277
- const renderedColumnsWithFocusedCell = columnWithFocusedCellNotInRange && focusedCell ? [columnWithFocusedCellNotInRange, ...renderedColumns] : renderedColumns;
246
+ const isVirtualRow = rowIndexInPage === virtualRowIndex;
247
+ const isNotVisible = isVirtualRow;
278
248
  let tabbableCell = null;
279
249
  if (cellTabIndex !== null && cellTabIndex.id === id) {
280
250
  const cellParams = apiRef.current.getCellParams(id, cellTabIndex.field);
281
251
  tabbableCell = cellParams.cellMode === 'view' ? cellTabIndex.field : null;
282
252
  }
253
+ const offsetLeft = computeOffsetLeft(columnPositions, currentRenderContext, theme.direction, pinnedColumns.left.length);
254
+ const rowIndex = ((currentPage == null || (_currentPage$range = currentPage.range) == null ? void 0 : _currentPage$range.firstRowIndex) || 0) + rowIndexOffset + rowIndexInPage;
283
255
  rows.push( /*#__PURE__*/_jsx(rootProps.slots.row, _extends({
284
256
  row: model,
285
257
  rowId: id,
286
- index: index,
258
+ index: rowIndex,
259
+ selected: isSelected,
260
+ offsetTop: params.rows ? undefined : rowsMeta.positions[rowIndexInPage],
261
+ offsetLeft: offsetLeft,
262
+ dimensions: dimensions,
287
263
  rowHeight: baseRowHeight,
288
- focusedCell: focusedCell,
289
264
  tabbableCell: tabbableCell,
290
- focusedCellColumnIndexNotInRange: focusedCellColumnIndexNotInRange,
291
- renderedColumns: renderedColumnsWithFocusedCell,
292
- visibleColumns: visibleColumns,
293
265
  pinnedColumns: pinnedColumns,
294
- firstColumnToRender: firstColumnToRender,
295
- lastColumnToRender: lastColumnToRender,
296
- selected: isSelected,
297
- offsets: offsets,
298
- dimensions: dimensions,
266
+ visibleColumns: visibleColumns,
267
+ renderContext: currentRenderContext,
268
+ focusedColumnIndex: hasFocus ? focusedCell.columnIndex : undefined,
299
269
  isFirstVisible: isFirstVisible,
300
270
  isLastVisible: isLastVisible,
301
- isNotVisible: isRowNotVisible
271
+ isNotVisible: isNotVisible
302
272
  }, rowProps), id));
303
273
  const panel = panels.get(id);
304
274
  if (panel) {
305
275
  rows.push(panel);
306
276
  }
307
- }
277
+ if (isLastVisible) {
278
+ var _apiRef$current$getIn, _apiRef$current;
279
+ rows.push((_apiRef$current$getIn = (_apiRef$current = apiRef.current).getInfiniteLoadingTriggerElement) == null ? void 0 : _apiRef$current$getIn.call(_apiRef$current, {
280
+ lastRowId: id
281
+ }));
282
+ }
283
+ });
308
284
  return rows;
309
285
  };
310
286
  const needsHorizontalScrollbar = outerSize.width && columnsTotalWidth >= outerSize.width;
@@ -357,6 +333,9 @@ export const useGridVirtualScroller = () => {
357
333
  apiRef.current.register('private', {
358
334
  updateRenderContext: forceUpdateRenderContext
359
335
  });
336
+ useGridApiEventHandler(apiRef, 'columnsChange', forceUpdateRenderContext);
337
+ useGridApiEventHandler(apiRef, 'filteredRowsSet', forceUpdateRenderContext);
338
+ useGridApiEventHandler(apiRef, 'rowExpansionChange', forceUpdateRenderContext);
360
339
  return {
361
340
  renderContext,
362
341
  setPanels,
@@ -390,29 +369,6 @@ export const useGridVirtualScroller = () => {
390
369
  })
391
370
  };
392
371
  };
393
- function createGetRenderedColumns() {
394
- return defaultMemoize((columns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, indexOfColumnWithFocusedCell) => {
395
- // If the selected column is not within the current range of columns being displayed,
396
- // we need to render it at either the left or right of the columns,
397
- // depending on whether it is above or below the range.
398
- let focusedCellColumnIndexNotInRange;
399
- const renderedColumns = columns.slice(firstColumnToRender, lastColumnToRender);
400
- if (indexOfColumnWithFocusedCell > -1) {
401
- // check if it is not on the left pinned column.
402
- if (firstColumnToRender > indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell >= minFirstColumn) {
403
- focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
404
- }
405
- // check if it is not on the right pinned column.
406
- else if (lastColumnToRender < indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell < maxLastColumn) {
407
- focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
408
- }
409
- }
410
- return {
411
- focusedCellColumnIndexNotInRange,
412
- renderedColumns
413
- };
414
- });
415
- }
416
372
  function inputsSelector(apiRef, rootProps, enabled, enabledForColumns) {
417
373
  const dimensions = gridDimensionsSelector(apiRef.current.state);
418
374
  const currentPage = getVisibleRows(apiRef, rootProps);
@@ -591,15 +547,9 @@ export function areRenderContextsEqual(context1, context2) {
591
547
  }
592
548
  return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
593
549
  }
594
- function computeOffsets(apiRef, renderContext, direction, pinnedLeftLength) {
595
- var _rowPositions$renderC, _columnPositions$rend, _columnPositions$pinn;
550
+ export function computeOffsetLeft(columnPositions, renderContext, direction, pinnedLeftLength) {
551
+ var _columnPositions$rend, _columnPositions$pinn;
596
552
  const factor = direction === 'ltr' ? 1 : -1;
597
- const rowPositions = gridRowsMetaSelector(apiRef.current.state).positions;
598
- const columnPositions = gridColumnPositionsSelector(apiRef);
599
- const top = (_rowPositions$renderC = rowPositions[renderContext.firstRowIndex]) != null ? _rowPositions$renderC : 0;
600
553
  const left = factor * ((_columnPositions$rend = columnPositions[renderContext.firstColumnIndex]) != null ? _columnPositions$rend : 0) - ((_columnPositions$pinn = columnPositions[pinnedLeftLength]) != null ? _columnPositions$pinn : 0);
601
- return {
602
- top,
603
- left
604
- };
554
+ return left;
605
555
  }
@@ -8,14 +8,6 @@ export type GridVirtualizationState = {
8
8
  enabled: boolean;
9
9
  enabledForColumns: boolean;
10
10
  renderContext: GridRenderContext;
11
- offsets: {
12
- top: number;
13
- left: number;
14
- };
15
- };
16
- export declare const EMPTY_OFFSETS: {
17
- top: number;
18
- left: number;
19
11
  };
20
12
  export declare const EMPTY_RENDER_CONTEXT: {
21
13
  firstRowIndex: number;
@@ -1,10 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
4
- export const EMPTY_OFFSETS = {
5
- top: 0,
6
- left: 0
7
- };
8
4
  export const EMPTY_RENDER_CONTEXT = {
9
5
  firstRowIndex: 0,
10
6
  lastRowIndex: 0,
@@ -15,8 +11,7 @@ export const virtualizationStateInitializer = (state, props) => {
15
11
  const virtualization = {
16
12
  enabled: !props.disableVirtualization,
17
13
  enabledForColumns: true,
18
- renderContext: EMPTY_RENDER_CONTEXT,
19
- offsets: EMPTY_OFFSETS
14
+ renderContext: EMPTY_RENDER_CONTEXT
20
15
  };
21
16
  return _extends({}, state, {
22
17
  virtualization
@@ -1,9 +1,11 @@
1
- declare class Timeout {
1
+ export declare class Timeout {
2
2
  static create(): Timeout;
3
- currentId: number;
3
+ currentId: ReturnType<typeof setTimeout> | null;
4
+ /**
5
+ * Executes `fn` after `delay`, clearing any previously scheduled call.
6
+ */
4
7
  start(delay: number, fn: Function): void;
5
8
  clear: () => void;
6
9
  disposeEffect: () => () => void;
7
10
  }
8
11
  export declare function useTimeout(): Timeout;
9
- export {};
@@ -1,12 +1,14 @@
1
+ 'use client';
2
+
1
3
  import { useLazyRef } from './useLazyRef';
2
4
  import { useOnMount } from './useOnMount';
3
- class Timeout {
5
+ export class Timeout {
4
6
  constructor() {
5
- this.currentId = 0;
7
+ this.currentId = null;
6
8
  this.clear = () => {
7
- if (this.currentId !== 0) {
9
+ if (this.currentId !== null) {
8
10
  clearTimeout(this.currentId);
9
- this.currentId = 0;
11
+ this.currentId = null;
10
12
  }
11
13
  };
12
14
  this.disposeEffect = () => {
@@ -16,9 +18,15 @@ class Timeout {
16
18
  static create() {
17
19
  return new Timeout();
18
20
  }
21
+ /**
22
+ * Executes `fn` after `delay`, clearing any previously scheduled call.
23
+ */
19
24
  start(delay, fn) {
20
25
  this.clear();
21
- this.currentId = setTimeout(fn, delay);
26
+ this.currentId = setTimeout(() => {
27
+ this.currentId = null;
28
+ fn();
29
+ }, delay);
22
30
  }
23
31
  }
24
32
  export function useTimeout() {
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.0.0-beta.4
2
+ * @mui/x-data-grid v7.0.0-beta.6
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -68,7 +68,7 @@ export type { GridStateInitializer } from '../hooks/utils/useGridInitializeState
68
68
  export type { GridExperimentalFeatures, DataGridPropsWithoutDefaultValue, DataGridPropsWithDefaultValues, DataGridPropsWithComplexDefaultValueAfterProcessing, DataGridPropsWithComplexDefaultValueBeforeProcessing, } from '../models/props/DataGridProps';
69
69
  export { getColumnsToExport, defaultGetRowsToExport } from '../hooks/features/export/utils';
70
70
  export * from '../utils/createControllablePromise';
71
- export { createSelector, createSelectorMemoized, unstable_resetCreateSelectorCache, } from '../utils/createSelector';
71
+ export { createSelector, createSelectorMemoized } from '../utils/createSelector';
72
72
  export { findParentElementFromClassName, getActiveElement, isEventTargetInPortal, } from '../utils/domUtils';
73
73
  export { isNavigationKey, isPasteShortcut } from '../utils/keyboardUtils';
74
74
  export * from '../utils/utils';
@@ -54,7 +54,7 @@ export { useGridVisibleRows, getVisibleRows } from '../hooks/utils/useGridVisibl
54
54
  export { useGridInitializeState } from '../hooks/utils/useGridInitializeState';
55
55
  export { getColumnsToExport, defaultGetRowsToExport } from '../hooks/features/export/utils';
56
56
  export * from '../utils/createControllablePromise';
57
- export { createSelector, createSelectorMemoized, unstable_resetCreateSelectorCache } from '../utils/createSelector';
57
+ export { createSelector, createSelectorMemoized } from '../utils/createSelector';
58
58
  export { findParentElementFromClassName, getActiveElement, isEventTargetInPortal } from '../utils/domUtils';
59
59
  export { isNavigationKey, isPasteShortcut } from '../utils/keyboardUtils';
60
60
  export * from '../utils/utils';
@@ -28,9 +28,10 @@ import { GridColumnGroupingApi } from './gridColumnGroupingApi';
28
28
  import type { GridInitialStateCommunity, GridStateCommunity } from '../gridStateCommunity';
29
29
  import { GridHeaderFilteringApi, GridHeaderFilteringPrivateApi } from './gridHeaderFilteringApi';
30
30
  import type { DataGridProcessedProps } from '../props/DataGridProps';
31
+ import type { GridInfiniteLoaderPrivateApi } from './gridInfiniteLoaderApi';
31
32
  export interface GridApiCommon<GridState extends GridStateCommunity = any, GridInitialState extends GridInitialStateCommunity = any> extends GridCoreApi, GridPipeProcessingApi, GridDensityApi, GridDimensionsApi, GridRowApi, GridRowsMetaApi, GridEditingApi, GridParamsApi, GridColumnApi, GridRowSelectionApi, GridSortApi, GridPaginationApi, GridCsvExportApi, GridFocusApi, GridFilterApi, GridColumnMenuApi, GridPreferencesPanelApi, GridPrintExportApi, GridVirtualizationApi, GridLocaleTextApi, GridScrollApi, GridColumnSpanningApi, GridStateApi<GridState>, GridStatePersistenceApi<GridInitialState>, GridColumnGroupingApi, GridHeaderFilteringApi {
32
33
  }
33
- export interface GridPrivateOnlyApiCommon<Api extends GridApiCommon, PrivateApi extends GridPrivateApiCommon, Props extends DataGridProcessedProps> extends GridCorePrivateApi<Api, PrivateApi, Props>, GridStatePrivateApi<PrivateApi['state']>, GridPipeProcessingPrivateApi, GridStrategyProcessingApi, GridColumnSpanningPrivateApi, GridRowsMetaPrivateApi, GridDimensionsPrivateApi, GridEditingPrivateApi, GridLoggerApi, GridFocusPrivateApi, GridHeaderFilteringPrivateApi, GridVirtualizationPrivateApi {
34
+ export interface GridPrivateOnlyApiCommon<Api extends GridApiCommon, PrivateApi extends GridPrivateApiCommon, Props extends DataGridProcessedProps> extends GridCorePrivateApi<Api, PrivateApi, Props>, GridStatePrivateApi<PrivateApi['state']>, GridPipeProcessingPrivateApi, GridStrategyProcessingApi, GridColumnSpanningPrivateApi, GridRowsMetaPrivateApi, GridDimensionsPrivateApi, GridEditingPrivateApi, GridLoggerApi, GridFocusPrivateApi, GridHeaderFilteringPrivateApi, GridVirtualizationPrivateApi, GridInfiniteLoaderPrivateApi {
34
35
  }
35
36
  export interface GridPrivateApiCommon extends GridApiCommon, GridPrivateOnlyApiCommon<GridApiCommon, GridPrivateApiCommon, DataGridProcessedProps> {
36
37
  }
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ export interface GridInfiniteLoaderPrivateApi {
3
+ getInfiniteLoadingTriggerElement?: ({ lastRowId, }: {
4
+ lastRowId: string | number;
5
+ }) => React.ReactNode;
6
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -108,6 +108,13 @@ export interface GridBaseColDef<R extends GridValidRowModel = GridValidRowModel,
108
108
  * A comparator function used to sort rows.
109
109
  */
110
110
  sortComparator?: GridComparatorFn<V>;
111
+ /**
112
+ * Allows to use a different comparator function depending on the sort direction.
113
+ * Takes precedence over `sortComparator`.
114
+ * @param {GridSortDirection} sortDirection The direction of the sort.
115
+ * @returns {GridComparatorFn<V>} The comparator function to use.
116
+ */
117
+ getSortComparator?: (sortDirection: GridSortDirection) => GridComparatorFn<V> | undefined;
111
118
  /**
112
119
  * The type of the column.
113
120
  * @default 'string'
@@ -1,3 +1,5 @@
1
+ 'use client';
2
+
1
3
  import _extends from "@babel/runtime/helpers/esm/extends";
2
4
  import * as React from 'react';
3
5
  import PropTypes from 'prop-types';
@@ -5,7 +5,7 @@ export const getGridBooleanOperators = () => [{
5
5
  if (!filterItem.value) {
6
6
  return null;
7
7
  }
8
- const valueAsBoolean = filterItem.value === 'true';
8
+ const valueAsBoolean = String(filterItem.value) === 'true';
9
9
  return value => {
10
10
  return Boolean(value) === valueAsBoolean;
11
11
  };