@mui/x-data-grid 7.0.0-beta.4 → 7.0.0-beta.5
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.
- package/CHANGELOG.md +138 -14
- package/DataGrid/DataGrid.js +2 -0
- package/colDef/gridBooleanOperators.js +1 -1
- package/components/GridRow.d.ts +7 -9
- package/components/GridRow.js +36 -47
- package/components/cell/GridCell.d.ts +2 -1
- package/components/cell/GridCell.js +7 -3
- package/components/cell/GridSkeletonCell.d.ts +3 -2
- package/components/cell/GridSkeletonCell.js +14 -6
- package/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
- package/components/columnsManagement/GridColumnsManagement.js +1 -1
- package/components/containers/GridRootStyles.js +9 -2
- package/components/virtualization/GridBottomContainer.js +1 -1
- package/components/virtualization/GridTopContainer.js +1 -1
- package/components/virtualization/GridVirtualScroller.js +2 -2
- package/components/virtualization/GridVirtualScrollerRenderZone.js +9 -3
- package/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
- package/hooks/features/columns/gridColumnsSelector.d.ts +6 -0
- package/hooks/features/columns/gridColumnsSelector.js +8 -1
- package/hooks/features/columns/useGridColumns.js +4 -0
- package/hooks/features/editing/useGridRowEditing.js +1 -2
- package/hooks/features/filter/useGridFilter.js +2 -2
- package/hooks/features/rows/useGridRows.js +8 -4
- package/hooks/features/rows/useGridRowsMeta.js +5 -13
- package/hooks/features/sorting/gridSortingUtils.js +9 -1
- package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +0 -9
- package/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
- package/hooks/features/virtualization/useGridVirtualScroller.d.ts +3 -0
- package/hooks/features/virtualization/useGridVirtualScroller.js +82 -138
- package/hooks/features/virtualization/useGridVirtualization.d.ts +0 -8
- package/hooks/features/virtualization/useGridVirtualization.js +1 -6
- package/hooks/utils/useTimeout.d.ts +5 -3
- package/hooks/utils/useTimeout.js +13 -5
- package/index.js +1 -1
- package/models/colDef/gridColDef.d.ts +7 -0
- package/modern/DataGrid/DataGrid.js +2 -0
- package/modern/colDef/gridBooleanOperators.js +1 -1
- package/modern/components/GridRow.js +35 -46
- package/modern/components/cell/GridCell.js +7 -3
- package/modern/components/cell/GridSkeletonCell.js +14 -6
- package/modern/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
- package/modern/components/columnsManagement/GridColumnsManagement.js +1 -1
- package/modern/components/containers/GridRootStyles.js +9 -2
- package/modern/components/virtualization/GridBottomContainer.js +1 -1
- package/modern/components/virtualization/GridTopContainer.js +1 -1
- package/modern/components/virtualization/GridVirtualScroller.js +2 -2
- package/modern/components/virtualization/GridVirtualScrollerRenderZone.js +8 -3
- package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +11 -8
- package/modern/hooks/features/columns/gridColumnsSelector.js +8 -1
- package/modern/hooks/features/columns/useGridColumns.js +2 -0
- package/modern/hooks/features/editing/useGridRowEditing.js +1 -2
- package/modern/hooks/features/filter/useGridFilter.js +2 -2
- package/modern/hooks/features/rows/useGridRows.js +8 -4
- package/modern/hooks/features/rows/useGridRowsMeta.js +5 -13
- package/modern/hooks/features/sorting/gridSortingUtils.js +9 -1
- package/modern/hooks/features/virtualization/gridVirtualizationSelectors.js +0 -7
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +80 -136
- package/modern/hooks/features/virtualization/useGridVirtualization.js +1 -6
- package/modern/hooks/utils/useTimeout.js +13 -5
- package/modern/index.js +1 -1
- package/modern/utils/utils.js +9 -0
- package/node/DataGrid/DataGrid.js +1 -0
- package/node/colDef/gridBooleanOperators.js +1 -1
- package/node/components/GridRow.js +35 -46
- package/node/components/cell/GridCell.js +7 -3
- package/node/components/cell/GridSkeletonCell.js +15 -7
- package/node/components/columnSelection/GridCellCheckboxRenderer.js +6 -4
- package/node/components/columnsManagement/GridColumnsManagement.js +1 -1
- package/node/components/containers/GridRootStyles.js +9 -2
- package/node/components/virtualization/GridBottomContainer.js +1 -1
- package/node/components/virtualization/GridTopContainer.js +1 -1
- package/node/components/virtualization/GridVirtualScroller.js +2 -2
- package/node/components/virtualization/GridVirtualScrollerRenderZone.js +7 -2
- package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +8 -5
- package/node/hooks/features/columns/gridColumnsSelector.js +9 -2
- package/node/hooks/features/columns/useGridColumns.js +2 -0
- package/node/hooks/features/editing/useGridRowEditing.js +1 -2
- package/node/hooks/features/filter/useGridFilter.js +2 -2
- package/node/hooks/features/rows/useGridRows.js +8 -4
- package/node/hooks/features/rows/useGridRowsMeta.js +5 -13
- package/node/hooks/features/sorting/gridSortingUtils.js +9 -1
- package/node/hooks/features/virtualization/gridVirtualizationSelectors.js +1 -8
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +81 -136
- package/node/hooks/features/virtualization/useGridVirtualization.js +2 -7
- package/node/hooks/utils/useTimeout.js +13 -4
- package/node/index.js +1 -1
- package/node/utils/utils.js +12 -1
- package/package.json +1 -1
- package/utils/utils.d.ts +4 -0
- 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 {
|
|
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 {
|
|
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
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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,
|
|
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
|
|
181
|
-
const
|
|
182
|
-
const
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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);
|
|
200
|
-
}
|
|
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
|
-
});
|
|
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);
|
|
224
180
|
}
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
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
|
-
} =
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
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
|
|
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,46 @@ export const useGridVirtualScroller = () => {
|
|
|
264
235
|
if (isLastSection) {
|
|
265
236
|
if (!isPinnedSection) {
|
|
266
237
|
const lastIndex = currentPage.rows.length - 1;
|
|
267
|
-
const isLastVisibleRowIndex =
|
|
238
|
+
const isLastVisibleRowIndex = rowIndexInPage === lastIndex;
|
|
268
239
|
if (isLastVisibleRowIndex) {
|
|
269
240
|
isLastVisible = true;
|
|
270
241
|
}
|
|
271
242
|
} else {
|
|
272
|
-
isLastVisible =
|
|
243
|
+
isLastVisible = rowIndexInPage === rowModels.length - 1;
|
|
273
244
|
}
|
|
274
245
|
}
|
|
275
|
-
const
|
|
276
|
-
const
|
|
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:
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
|
|
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:
|
|
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
|
+
});
|
|
308
278
|
return rows;
|
|
309
279
|
};
|
|
310
280
|
const needsHorizontalScrollbar = outerSize.width && columnsTotalWidth >= outerSize.width;
|
|
@@ -357,6 +327,9 @@ export const useGridVirtualScroller = () => {
|
|
|
357
327
|
apiRef.current.register('private', {
|
|
358
328
|
updateRenderContext: forceUpdateRenderContext
|
|
359
329
|
});
|
|
330
|
+
useGridApiEventHandler(apiRef, 'columnsChange', forceUpdateRenderContext);
|
|
331
|
+
useGridApiEventHandler(apiRef, 'filteredRowsSet', forceUpdateRenderContext);
|
|
332
|
+
useGridApiEventHandler(apiRef, 'rowExpansionChange', forceUpdateRenderContext);
|
|
360
333
|
return {
|
|
361
334
|
renderContext,
|
|
362
335
|
setPanels,
|
|
@@ -390,29 +363,6 @@ export const useGridVirtualScroller = () => {
|
|
|
390
363
|
})
|
|
391
364
|
};
|
|
392
365
|
};
|
|
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
366
|
function inputsSelector(apiRef, rootProps, enabled, enabledForColumns) {
|
|
417
367
|
const dimensions = gridDimensionsSelector(apiRef.current.state);
|
|
418
368
|
const currentPage = getVisibleRows(apiRef, rootProps);
|
|
@@ -591,15 +541,9 @@ export function areRenderContextsEqual(context1, context2) {
|
|
|
591
541
|
}
|
|
592
542
|
return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
|
|
593
543
|
}
|
|
594
|
-
function
|
|
595
|
-
var
|
|
544
|
+
export function computeOffsetLeft(columnPositions, renderContext, direction, pinnedLeftLength) {
|
|
545
|
+
var _columnPositions$rend, _columnPositions$pinn;
|
|
596
546
|
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
547
|
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
|
-
};
|
|
548
|
+
return left;
|
|
605
549
|
}
|
|
@@ -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:
|
|
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 =
|
|
7
|
+
this.currentId = null;
|
|
6
8
|
this.clear = () => {
|
|
7
|
-
if (this.currentId !==
|
|
9
|
+
if (this.currentId !== null) {
|
|
8
10
|
clearTimeout(this.currentId);
|
|
9
|
-
this.currentId =
|
|
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(
|
|
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
|
@@ -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'
|
|
@@ -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
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
|
-
const _excluded = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "
|
|
3
|
+
const _excluded = ["selected", "rowId", "row", "index", "style", "rowHeight", "className", "visibleColumns", "pinnedColumns", "offsetTop", "offsetLeft", "dimensions", "renderContext", "focusedColumnIndex", "isFirstVisible", "isLastVisible", "isNotVisible", "focusedCell", "tabbableCell", "onClick", "onDoubleClick", "onMouseEnter", "onMouseLeave", "onMouseOut", "onMouseOver"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import clsx from 'clsx';
|
|
@@ -21,7 +21,6 @@ import { gridSortModelSelector } from '../hooks/features/sorting/gridSortingSele
|
|
|
21
21
|
import { gridRowMaximumTreeDepthSelector } from '../hooks/features/rows/gridRowsSelector';
|
|
22
22
|
import { gridColumnGroupsHeaderMaxDepthSelector } from '../hooks/features/columnGrouping/gridColumnGroupsSelector';
|
|
23
23
|
import { gridEditRowsStateSelector } from '../hooks/features/editing/gridEditingSelectors';
|
|
24
|
-
import { randomNumberBetween } from '../utils/utils';
|
|
25
24
|
import { PinnedPosition } from './cell/GridCell';
|
|
26
25
|
import { GridScrollbarFillerCell as ScrollbarFiller } from './GridScrollbarFillerCell';
|
|
27
26
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -65,16 +64,14 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
65
64
|
rowHeight,
|
|
66
65
|
className,
|
|
67
66
|
visibleColumns,
|
|
68
|
-
renderedColumns,
|
|
69
67
|
pinnedColumns,
|
|
70
|
-
|
|
68
|
+
offsetLeft,
|
|
71
69
|
dimensions,
|
|
72
|
-
|
|
70
|
+
renderContext,
|
|
71
|
+
focusedColumnIndex,
|
|
73
72
|
isFirstVisible,
|
|
74
73
|
isLastVisible,
|
|
75
|
-
focusedCellColumnIndexNotInRange,
|
|
76
74
|
isNotVisible,
|
|
77
|
-
focusedCell,
|
|
78
75
|
onClick,
|
|
79
76
|
onDoubleClick,
|
|
80
77
|
onMouseEnter,
|
|
@@ -95,6 +92,9 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
95
92
|
const handleRef = useForkRef(ref, refProp);
|
|
96
93
|
const rowNode = apiRef.current.getRowNode(rowId);
|
|
97
94
|
const scrollbarWidth = dimensions.hasScrollY ? dimensions.scrollbarSize : 0;
|
|
95
|
+
const hasFocusCell = focusedColumnIndex !== undefined;
|
|
96
|
+
const hasVirtualFocusCellLeft = hasFocusCell && focusedColumnIndex >= pinnedColumns.left.length && focusedColumnIndex < renderContext.firstColumnIndex;
|
|
97
|
+
const hasVirtualFocusCellRight = hasFocusCell && focusedColumnIndex < visibleColumns.length - pinnedColumns.right.length && focusedColumnIndex >= renderContext.lastColumnIndex;
|
|
98
98
|
const ariaRowIndex = index + headerGroupingMaxDepth + 2; // 1 for the header row and 1 as it's 1-based
|
|
99
99
|
|
|
100
100
|
const ownerState = {
|
|
@@ -243,12 +243,13 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
243
243
|
});
|
|
244
244
|
rowClassNames.push(rootProps.getRowClassName(rowParams));
|
|
245
245
|
}
|
|
246
|
-
const randomNumber = randomNumberBetween(10000, 20, 80);
|
|
247
246
|
const getCell = (column, indexInSection, indexRelativeToAllColumns, sectionLength, pinnedPosition = PinnedPosition.NONE) => {
|
|
248
247
|
const cellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowId, indexRelativeToAllColumns);
|
|
249
|
-
if (
|
|
248
|
+
if (cellColSpanInfo?.spannedByColSpan) {
|
|
250
249
|
return null;
|
|
251
250
|
}
|
|
251
|
+
const width = cellColSpanInfo?.cellProps.width ?? column.computedWidth;
|
|
252
|
+
const colSpan = cellColSpanInfo?.cellProps.colSpan ?? 1;
|
|
252
253
|
let pinnedOffset;
|
|
253
254
|
// FIXME: Why is the switch check exhaustiveness not validated with typescript-eslint?
|
|
254
255
|
// eslint-disable-next-line default-case
|
|
@@ -260,25 +261,18 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
260
261
|
pinnedOffset = dimensions.columnsTotalWidth - columnPositions[indexRelativeToAllColumns] - column.computedWidth + scrollbarWidth;
|
|
261
262
|
break;
|
|
262
263
|
case PinnedPosition.NONE:
|
|
264
|
+
case PinnedPosition.VIRTUAL:
|
|
263
265
|
pinnedOffset = 0;
|
|
264
266
|
break;
|
|
265
267
|
}
|
|
266
268
|
if (rowNode?.type === 'skeletonRow') {
|
|
267
|
-
const {
|
|
268
|
-
width
|
|
269
|
-
} = cellColSpanInfo.cellProps;
|
|
270
|
-
const contentWidth = Math.round(randomNumber());
|
|
271
269
|
return /*#__PURE__*/_jsx(slots.skeletonCell, {
|
|
272
270
|
width: width,
|
|
273
|
-
|
|
271
|
+
height: rowHeight,
|
|
274
272
|
field: column.field,
|
|
275
273
|
align: column.align ?? 'left'
|
|
276
274
|
}, column.field);
|
|
277
275
|
}
|
|
278
|
-
const {
|
|
279
|
-
colSpan,
|
|
280
|
-
width
|
|
281
|
-
} = cellColSpanInfo.cellProps;
|
|
282
276
|
const editCellState = editRowsState[rowId]?.[column.field] ?? null;
|
|
283
277
|
|
|
284
278
|
// when the cell is a reorder cell we are not allowing to reorder the col
|
|
@@ -288,10 +282,7 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
288
282
|
const canReorderColumn = !(disableColumnReorder || column.disableReorder);
|
|
289
283
|
const canReorderRow = rowReordering && !sortModel.length && treeDepth <= 1 && !isEditingRows;
|
|
290
284
|
const disableDragEvents = !(canReorderColumn || isReorderCell && canReorderRow);
|
|
291
|
-
|
|
292
|
-
if (focusedCellColumnIndexNotInRange !== undefined && visibleColumns[focusedCellColumnIndexNotInRange].field === column.field) {
|
|
293
|
-
cellIsNotVisible = true;
|
|
294
|
-
}
|
|
285
|
+
const cellIsNotVisible = pinnedPosition === PinnedPosition.VIRTUAL;
|
|
295
286
|
return /*#__PURE__*/_jsx(slots.cell, _extends({
|
|
296
287
|
column: column,
|
|
297
288
|
width: width,
|
|
@@ -327,18 +318,16 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
327
318
|
});
|
|
328
319
|
const middleColumnsLength = visibleColumns.length - pinnedColumns.left.length - pinnedColumns.right.length;
|
|
329
320
|
const cells = [];
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
const indexInSection = indexRelativeToAllColumns - pinnedColumns.left.length;
|
|
341
|
-
cells.push(getCell(column, indexInSection, indexRelativeToAllColumns, middleColumnsLength));
|
|
321
|
+
if (hasVirtualFocusCellLeft) {
|
|
322
|
+
cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, PinnedPosition.VIRTUAL));
|
|
323
|
+
}
|
|
324
|
+
for (let i = renderContext.firstColumnIndex; i < renderContext.lastColumnIndex; i += 1) {
|
|
325
|
+
const column = visibleColumns[i];
|
|
326
|
+
const indexInSection = i - pinnedColumns.left.length;
|
|
327
|
+
cells.push(getCell(column, indexInSection, i, middleColumnsLength));
|
|
328
|
+
}
|
|
329
|
+
if (hasVirtualFocusCellRight) {
|
|
330
|
+
cells.push(getCell(visibleColumns[focusedColumnIndex], focusedColumnIndex - pinnedColumns.left.length, focusedColumnIndex, middleColumnsLength, PinnedPosition.VIRTUAL));
|
|
342
331
|
}
|
|
343
332
|
const eventHandlers = row ? {
|
|
344
333
|
onClick: publishClick,
|
|
@@ -364,7 +353,7 @@ const GridRow = /*#__PURE__*/React.forwardRef(function GridRow(props, refProp) {
|
|
|
364
353
|
role: "presentation",
|
|
365
354
|
className: gridClasses.cellOffsetLeft,
|
|
366
355
|
style: {
|
|
367
|
-
width:
|
|
356
|
+
width: offsetLeft
|
|
368
357
|
}
|
|
369
358
|
}), cells, emptyCellWidth > 0 && /*#__PURE__*/_jsx(EmptyCell, {
|
|
370
359
|
width: emptyCellWidth
|
|
@@ -418,13 +407,11 @@ process.env.NODE_ENV !== "production" ? GridRow.propTypes = {
|
|
|
418
407
|
width: PropTypes.number.isRequired
|
|
419
408
|
}).isRequired
|
|
420
409
|
}).isRequired,
|
|
421
|
-
firstColumnToRender: PropTypes.number.isRequired,
|
|
422
410
|
/**
|
|
423
411
|
* Determines which cell has focus.
|
|
424
412
|
* If `null`, no cell in this row has focus.
|
|
425
413
|
*/
|
|
426
|
-
|
|
427
|
-
focusedCellColumnIndexNotInRange: PropTypes.number,
|
|
414
|
+
focusedColumnIndex: PropTypes.number,
|
|
428
415
|
/**
|
|
429
416
|
* Index of the row in the whole sorted and filtered dataset.
|
|
430
417
|
* If some rows above have expanded children, this index also take those children into account.
|
|
@@ -432,19 +419,21 @@ process.env.NODE_ENV !== "production" ? GridRow.propTypes = {
|
|
|
432
419
|
index: PropTypes.number.isRequired,
|
|
433
420
|
isFirstVisible: PropTypes.bool.isRequired,
|
|
434
421
|
isLastVisible: PropTypes.bool.isRequired,
|
|
435
|
-
isNotVisible: PropTypes.bool,
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
left: PropTypes.number.isRequired,
|
|
439
|
-
top: PropTypes.number.isRequired
|
|
440
|
-
}).isRequired,
|
|
422
|
+
isNotVisible: PropTypes.bool.isRequired,
|
|
423
|
+
offsetLeft: PropTypes.number.isRequired,
|
|
424
|
+
offsetTop: PropTypes.number,
|
|
441
425
|
onClick: PropTypes.func,
|
|
442
426
|
onDoubleClick: PropTypes.func,
|
|
443
427
|
onMouseEnter: PropTypes.func,
|
|
444
428
|
onMouseLeave: PropTypes.func,
|
|
445
429
|
pinnedColumns: PropTypes.object.isRequired,
|
|
446
|
-
|
|
447
|
-
|
|
430
|
+
renderContext: PropTypes.shape({
|
|
431
|
+
firstColumnIndex: PropTypes.number.isRequired,
|
|
432
|
+
firstRowIndex: PropTypes.number.isRequired,
|
|
433
|
+
lastColumnIndex: PropTypes.number.isRequired,
|
|
434
|
+
lastRowIndex: PropTypes.number.isRequired
|
|
435
|
+
}).isRequired,
|
|
436
|
+
row: PropTypes.object.isRequired,
|
|
448
437
|
rowHeight: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]).isRequired,
|
|
449
438
|
rowId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
|
450
439
|
selected: PropTypes.bool.isRequired,
|