@mui/x-data-grid 7.0.0-beta.7 → 7.0.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.
- package/CHANGELOG.md +195 -12
- package/DataGrid/DataGrid.js +13 -17
- package/DataGrid/useDataGridProps.js +3 -5
- package/README.md +1 -1
- package/components/GridFooter.js +2 -3
- package/components/GridHeader.js +1 -2
- package/components/GridPagination.d.ts +6 -5
- package/components/GridPagination.js +12 -4
- package/components/GridRow.js +13 -17
- package/components/base/GridFooterPlaceholder.js +1 -2
- package/components/base/GridOverlays.js +3 -6
- package/components/cell/GridActionsCell.js +4 -6
- package/components/cell/GridActionsCellItem.d.ts +8 -25
- package/components/cell/GridActionsCellItem.js +8 -5
- package/components/cell/GridBooleanCell.d.ts +1 -0
- package/components/cell/GridBooleanCell.js +3 -2
- package/components/cell/GridCell.js +7 -8
- package/components/cell/GridEditBooleanCell.js +1 -2
- package/components/cell/GridEditDateCell.js +2 -3
- package/components/cell/GridEditInputCell.js +2 -2
- package/components/cell/GridEditSingleSelectCell.js +5 -8
- package/components/columnHeaders/ColumnHeaderMenuIcon.js +2 -3
- package/components/columnHeaders/GridColumnGroupHeader.js +4 -5
- package/components/columnHeaders/GridColumnHeaderFilterIconButton.js +2 -3
- package/components/columnHeaders/GridColumnHeaderItem.js +5 -6
- package/components/columnHeaders/GridColumnHeaderSortIcon.js +1 -2
- package/components/columnHeaders/GridColumnHeaderTitle.js +2 -3
- package/components/columnHeaders/GridGenericColumnHeaderItem.js +1 -1
- package/components/columnSelection/GridCellCheckboxRenderer.js +3 -5
- package/components/columnSelection/GridHeaderCheckbox.js +1 -2
- package/components/columnsManagement/GridColumnsManagement.js +17 -21
- package/components/containers/GridRoot.js +3 -3
- package/components/menu/GridMenu.js +4 -6
- package/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
- package/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +2 -3
- package/components/panel/GridColumnsPanel.js +1 -2
- package/components/panel/GridPanel.d.ts +1 -10
- package/components/panel/GridPanel.js +1 -2
- package/components/panel/GridPreferencesPanel.js +2 -3
- package/components/panel/filterPanel/GridFilterForm.js +24 -27
- package/components/panel/filterPanel/GridFilterInputBoolean.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputBoolean.js +6 -7
- package/components/panel/filterPanel/GridFilterInputDate.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputDate.js +3 -4
- package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +11 -15
- package/components/panel/filterPanel/GridFilterInputMultipleValue.js +10 -14
- package/components/panel/filterPanel/GridFilterInputSingleSelect.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputSingleSelect.js +10 -11
- package/components/panel/filterPanel/GridFilterInputValue.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputValue.js +5 -7
- package/components/panel/filterPanel/GridFilterPanel.js +5 -9
- package/components/panel/filterPanel/filterPanelUtils.js +1 -1
- package/components/toolbar/GridToolbarColumnsButton.js +3 -5
- package/components/toolbar/GridToolbarDensitySelector.js +8 -10
- package/components/toolbar/GridToolbarExport.js +2 -2
- package/components/toolbar/GridToolbarExportContainer.js +3 -5
- package/components/toolbar/GridToolbarFilterButton.js +3 -5
- package/components/toolbar/GridToolbarQuickFilter.js +4 -5
- package/components/virtualization/GridVirtualScrollerContent.js +1 -2
- package/components/virtualization/GridVirtualScrollerRenderZone.js +1 -2
- package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +1 -2
- package/hooks/core/useGridApiInitialization.js +4 -6
- package/hooks/features/clipboard/useGridClipboard.js +6 -5
- package/hooks/features/columnGrouping/gridColumnGroupsSelector.js +4 -16
- package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +4 -8
- package/hooks/features/columnGrouping/useGridColumnGrouping.js +12 -23
- package/hooks/features/columnHeaders/useGridColumnHeaders.js +6 -8
- package/hooks/features/columnMenu/useGridColumnMenuSlots.js +2 -2
- package/hooks/features/columnResize/useGridColumnResize.js +9 -19
- package/hooks/features/columns/gridColumnsSelector.js +1 -2
- package/hooks/features/columns/gridColumnsUtils.d.ts +0 -9
- package/hooks/features/columns/gridColumnsUtils.js +2 -22
- package/hooks/features/columns/useGridColumnSpanning.js +1 -2
- package/hooks/features/columns/useGridColumns.js +11 -19
- package/hooks/features/density/densitySelector.d.ts +4 -2
- package/hooks/features/density/densitySelector.js +8 -2
- package/hooks/features/density/densityState.d.ts +1 -4
- package/hooks/features/density/useGridDensity.d.ts +2 -4
- package/hooks/features/density/useGridDensity.js +21 -29
- package/hooks/features/dimensions/useGridDimensions.js +3 -5
- package/hooks/features/editing/useGridCellEditing.js +4 -6
- package/hooks/features/editing/useGridEditing.js +1 -2
- package/hooks/features/editing/useGridRowEditing.js +4 -6
- package/hooks/features/export/serializers/csvSerializer.d.ts +2 -0
- package/hooks/features/export/serializers/csvSerializer.js +25 -16
- package/hooks/features/export/useGridCsvExport.js +9 -10
- package/hooks/features/export/useGridPrintExport.js +9 -15
- package/hooks/features/export/utils.js +2 -3
- package/hooks/features/filter/gridFilterSelector.js +15 -22
- package/hooks/features/filter/gridFilterUtils.js +10 -16
- package/hooks/features/filter/useGridFilter.js +9 -15
- package/hooks/features/focus/useGridFocus.js +5 -6
- package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.js +1 -4
- package/hooks/features/headerFiltering/useGridHeaderFiltering.js +12 -17
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +1 -2
- package/hooks/features/pagination/gridPaginationSelector.js +1 -2
- package/hooks/features/pagination/useGridPagination.js +2 -3
- package/hooks/features/pagination/useGridPaginationModel.js +6 -11
- package/hooks/features/pagination/useGridRowCount.js +3 -6
- package/hooks/features/preferencesPanel/useGridPreferencesPanel.js +7 -12
- package/hooks/features/rowSelection/useGridRowSelection.js +11 -16
- package/hooks/features/rows/gridRowsSelector.js +11 -19
- package/hooks/features/rows/gridRowsUtils.js +7 -9
- package/hooks/features/rows/useGridParamsApi.js +1 -1
- package/hooks/features/rows/useGridRows.js +4 -13
- package/hooks/features/rows/useGridRowsMeta.js +7 -13
- package/hooks/features/scroll/useGridScroll.js +2 -3
- package/hooks/features/sorting/gridSortingSelector.js +4 -7
- package/hooks/features/sorting/useGridSorting.js +8 -14
- package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
- package/hooks/features/virtualization/useGridVirtualScroller.js +220 -71
- package/hooks/utils/useGridApiEventHandler.js +5 -10
- package/hooks/utils/useGridNativeEventListener.js +1 -2
- package/index.js +1 -1
- package/internals/index.d.ts +2 -0
- package/internals/index.js +1 -0
- package/internals/utils/useProps.js +1 -2
- package/joy/joySlots.js +7 -13
- package/models/api/gridRowsMetaApi.d.ts +1 -1
- package/models/api/index.d.ts +1 -1
- package/models/api/index.js +0 -1
- package/models/events/gridEventLookup.d.ts +7 -0
- package/models/gridExport.d.ts +6 -0
- package/models/gridStateCommunity.d.ts +1 -0
- package/models/props/DataGridProps.d.ts +23 -27
- package/modern/DataGrid/DataGrid.js +13 -17
- package/modern/DataGrid/useDataGridProps.js +3 -5
- package/modern/components/GridPagination.js +11 -2
- package/modern/components/cell/GridActionsCell.js +1 -1
- package/modern/components/cell/GridActionsCellItem.js +4 -0
- package/modern/components/cell/GridBooleanCell.js +3 -2
- package/modern/components/containers/GridRoot.js +3 -3
- package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputDate.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputValue.js +1 -1
- package/modern/components/toolbar/GridToolbarDensitySelector.js +5 -5
- package/modern/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/modern/hooks/features/columnResize/useGridColumnResize.js +1 -1
- package/modern/hooks/features/columns/gridColumnsUtils.js +0 -19
- package/modern/hooks/features/density/densitySelector.js +8 -2
- package/modern/hooks/features/density/useGridDensity.js +21 -29
- package/modern/hooks/features/editing/useGridCellEditing.js +1 -1
- package/modern/hooks/features/editing/useGridRowEditing.js +1 -1
- package/modern/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/modern/hooks/features/export/useGridCsvExport.js +2 -1
- package/modern/hooks/features/filter/gridFilterUtils.js +1 -1
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +3 -2
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
- package/modern/index.js +1 -1
- package/modern/internals/index.js +1 -0
- package/modern/models/api/index.js +0 -1
- package/modern/utils/createSelector.js +1 -1
- package/modern/utils/domUtils.js +1 -1
- package/modern/utils/keyboardUtils.js +1 -1
- package/node/DataGrid/DataGrid.js +13 -17
- package/node/DataGrid/useDataGridProps.js +3 -5
- package/node/components/GridPagination.js +9 -1
- package/node/components/cell/GridActionsCell.js +1 -1
- package/node/components/cell/GridActionsCellItem.js +4 -0
- package/node/components/cell/GridBooleanCell.js +3 -2
- package/node/components/containers/GridRoot.js +2 -2
- package/node/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputDate.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputValue.js +1 -1
- package/node/components/toolbar/GridToolbarDensitySelector.js +4 -4
- package/node/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/node/hooks/features/columnResize/useGridColumnResize.js +1 -1
- package/node/hooks/features/columns/gridColumnsUtils.js +0 -20
- package/node/hooks/features/density/densitySelector.js +9 -3
- package/node/hooks/features/density/useGridDensity.js +22 -30
- package/node/hooks/features/editing/useGridCellEditing.js +1 -1
- package/node/hooks/features/editing/useGridRowEditing.js +1 -1
- package/node/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/node/hooks/features/export/useGridCsvExport.js +2 -1
- package/node/hooks/features/filter/gridFilterUtils.js +1 -1
- package/node/hooks/features/rowSelection/useGridRowSelection.js +2 -1
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
- package/node/index.js +1 -1
- package/node/internals/index.js +12 -0
- package/node/models/api/index.js +0 -11
- package/node/utils/createSelector.js +1 -1
- package/node/utils/domUtils.js +1 -1
- package/node/utils/keyboardUtils.js +1 -1
- package/package.json +4 -4
- package/utils/createSelector.js +9 -9
- package/utils/domUtils.js +4 -7
- package/utils/getGridLocalization.js +9 -12
- package/utils/keyboardUtils.js +1 -1
|
@@ -13,8 +13,7 @@ import { buildAggregatedSortingApplier, mergeStateWithSortModel, getNextGridSort
|
|
|
13
13
|
import { useGridRegisterPipeProcessor } from '../../core/pipeProcessing';
|
|
14
14
|
import { getTreeNodeDescendants } from '../rows/gridRowsUtils';
|
|
15
15
|
export const sortingStateInitializer = (state, props) => {
|
|
16
|
-
|
|
17
|
-
const sortModel = (_ref = (_props$sortModel = props.sortModel) != null ? _props$sortModel : (_props$initialState = props.initialState) == null || (_props$initialState = _props$initialState.sorting) == null ? void 0 : _props$initialState.sortModel) != null ? _ref : [];
|
|
16
|
+
const sortModel = props.sortModel ?? props.initialState?.sorting?.sortModel ?? [];
|
|
18
17
|
return _extends({}, state, {
|
|
19
18
|
sorting: {
|
|
20
19
|
sortModel: sanitizeSortModel(sortModel, props.disableMultipleColumnsSorting),
|
|
@@ -28,7 +27,6 @@ export const sortingStateInitializer = (state, props) => {
|
|
|
28
27
|
* @requires useGridColumns (event)
|
|
29
28
|
*/
|
|
30
29
|
export const useGridSorting = (apiRef, props) => {
|
|
31
|
-
var _props$initialState3;
|
|
32
30
|
const logger = useGridLogger(apiRef, 'useGridSorting');
|
|
33
31
|
apiRef.current.registerControlState({
|
|
34
32
|
stateId: 'sortModel',
|
|
@@ -42,7 +40,7 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
42
40
|
const existingIdx = sortModel.findIndex(c => c.field === field);
|
|
43
41
|
let newSortModel = [...sortModel];
|
|
44
42
|
if (existingIdx > -1) {
|
|
45
|
-
if (
|
|
43
|
+
if (sortItem?.sort == null) {
|
|
46
44
|
newSortModel.splice(existingIdx, 1);
|
|
47
45
|
} else {
|
|
48
46
|
newSortModel.splice(existingIdx, 1, sortItem);
|
|
@@ -53,19 +51,17 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
53
51
|
return newSortModel;
|
|
54
52
|
}, [apiRef]);
|
|
55
53
|
const createSortItem = React.useCallback((col, directionOverride) => {
|
|
56
|
-
var _col$sortingOrder2;
|
|
57
54
|
const sortModel = gridSortModelSelector(apiRef);
|
|
58
55
|
const existing = sortModel.find(c => c.field === col.field);
|
|
59
56
|
if (existing) {
|
|
60
|
-
|
|
61
|
-
const nextSort = directionOverride === undefined ? getNextGridSortDirection((_col$sortingOrder = col.sortingOrder) != null ? _col$sortingOrder : props.sortingOrder, existing.sort) : directionOverride;
|
|
57
|
+
const nextSort = directionOverride === undefined ? getNextGridSortDirection(col.sortingOrder ?? props.sortingOrder, existing.sort) : directionOverride;
|
|
62
58
|
return nextSort === undefined ? undefined : _extends({}, existing, {
|
|
63
59
|
sort: nextSort
|
|
64
60
|
});
|
|
65
61
|
}
|
|
66
62
|
return {
|
|
67
63
|
field: col.field,
|
|
68
|
-
sort: directionOverride === undefined ? getNextGridSortDirection(
|
|
64
|
+
sort: directionOverride === undefined ? getNextGridSortDirection(col.sortingOrder ?? props.sortingOrder) : directionOverride
|
|
69
65
|
};
|
|
70
66
|
}, [apiRef, props.sortingOrder]);
|
|
71
67
|
const addColumnMenuItem = React.useCallback((columnMenuItems, colDef) => {
|
|
@@ -120,7 +116,7 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
120
116
|
const sortItem = createSortItem(column, direction);
|
|
121
117
|
let sortModel;
|
|
122
118
|
if (!allowMultipleSorting || props.disableMultipleColumnsSorting) {
|
|
123
|
-
sortModel =
|
|
119
|
+
sortModel = sortItem?.sort == null ? [] : [sortItem];
|
|
124
120
|
} else {
|
|
125
121
|
sortModel = upsertSortModel(column.field, sortItem);
|
|
126
122
|
}
|
|
@@ -148,7 +144,6 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
148
144
|
* PRE-PROCESSING
|
|
149
145
|
*/
|
|
150
146
|
const stateExportPreProcessing = React.useCallback((prevState, context) => {
|
|
151
|
-
var _props$initialState2;
|
|
152
147
|
const sortModelToExport = gridSortModelSelector(apiRef);
|
|
153
148
|
const shouldExportSortModel =
|
|
154
149
|
// Always export if the `exportOnlyDirtyModels` property is not activated
|
|
@@ -156,7 +151,7 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
156
151
|
// Always export if the model is controlled
|
|
157
152
|
props.sortModel != null ||
|
|
158
153
|
// Always export if the model has been initialized
|
|
159
|
-
|
|
154
|
+
props.initialState?.sorting?.sortModel != null ||
|
|
160
155
|
// Export if the model is not empty
|
|
161
156
|
sortModelToExport.length > 0;
|
|
162
157
|
if (!shouldExportSortModel) {
|
|
@@ -167,10 +162,9 @@ export const useGridSorting = (apiRef, props) => {
|
|
|
167
162
|
sortModel: sortModelToExport
|
|
168
163
|
}
|
|
169
164
|
});
|
|
170
|
-
}, [apiRef, props.sortModel,
|
|
165
|
+
}, [apiRef, props.sortModel, props.initialState?.sorting?.sortModel]);
|
|
171
166
|
const stateRestorePreProcessing = React.useCallback((params, context) => {
|
|
172
|
-
|
|
173
|
-
const sortModel = (_context$stateToResto = context.stateToRestore.sorting) == null ? void 0 : _context$stateToResto.sortModel;
|
|
167
|
+
const sortModel = context.stateToRestore.sorting?.sortModel;
|
|
174
168
|
if (sortModel == null) {
|
|
175
169
|
return params;
|
|
176
170
|
}
|
|
@@ -2,8 +2,8 @@ import * as React from 'react';
|
|
|
2
2
|
import { Theme } from '@mui/material/styles';
|
|
3
3
|
import { GridPinnedRowsPosition } from '../rows/gridRowsInterfaces';
|
|
4
4
|
import type { GridRenderContext, GridColumnsRenderContext, GridRowEntry, GridRowId } from '../../../models';
|
|
5
|
-
export declare const EMPTY_DETAIL_PANELS: Readonly<Map<GridRowId, React.ReactNode>>;
|
|
6
5
|
export type VirtualScroller = ReturnType<typeof useGridVirtualScroller>;
|
|
6
|
+
export declare const EMPTY_DETAIL_PANELS: Readonly<Map<GridRowId, React.ReactNode>>;
|
|
7
7
|
export declare const useGridVirtualScroller: () => {
|
|
8
8
|
renderContext: GridRenderContext;
|
|
9
9
|
setPanels: React.Dispatch<React.SetStateAction<Readonly<Map<GridRowId, React.ReactNode>>>>;
|
|
@@ -2,6 +2,8 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
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
|
+
import useLazyRef from '@mui/utils/useLazyRef';
|
|
6
|
+
import useTimeout from '@mui/utils/useTimeout';
|
|
5
7
|
import { useTheme } from '@mui/material/styles';
|
|
6
8
|
import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
|
|
7
9
|
import { useGridRootProps } from '../../utils/useGridRootProps';
|
|
@@ -22,13 +24,31 @@ import { getMinimalContentHeight } from '../rows/gridRowsUtils';
|
|
|
22
24
|
import { gridRenderContextSelector, gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
|
|
23
25
|
import { EMPTY_RENDER_CONTEXT } from './useGridVirtualization';
|
|
24
26
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
27
|
+
const MINIMUM_COLUMN_WIDTH = 50;
|
|
28
|
+
var ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
|
|
29
|
+
ScrollDirection[ScrollDirection["NONE"] = 0] = "NONE";
|
|
30
|
+
ScrollDirection[ScrollDirection["UP"] = 1] = "UP";
|
|
31
|
+
ScrollDirection[ScrollDirection["DOWN"] = 2] = "DOWN";
|
|
32
|
+
ScrollDirection[ScrollDirection["LEFT"] = 3] = "LEFT";
|
|
33
|
+
ScrollDirection[ScrollDirection["RIGHT"] = 4] = "RIGHT";
|
|
34
|
+
return ScrollDirection;
|
|
35
|
+
}(ScrollDirection || {});
|
|
36
|
+
const EMPTY_SCROLL_POSITION = {
|
|
37
|
+
top: 0,
|
|
38
|
+
left: 0
|
|
39
|
+
};
|
|
25
40
|
export const EMPTY_DETAIL_PANELS = Object.freeze(new Map());
|
|
41
|
+
const createScrollCache = (rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer) => ({
|
|
42
|
+
direction: ScrollDirection.NONE,
|
|
43
|
+
buffer: bufferForDirection(ScrollDirection.NONE, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer)
|
|
44
|
+
});
|
|
45
|
+
const isJSDOM = typeof window !== 'undefined' ? /jsdom/.test(window.navigator.userAgent) : false;
|
|
26
46
|
export const useGridVirtualScroller = () => {
|
|
27
47
|
const apiRef = useGridPrivateApiContext();
|
|
28
48
|
const rootProps = useGridRootProps();
|
|
29
49
|
const visibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
|
|
30
|
-
const enabled = useGridSelector(apiRef, gridVirtualizationEnabledSelector);
|
|
31
|
-
const enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector);
|
|
50
|
+
const enabled = useGridSelector(apiRef, gridVirtualizationEnabledSelector) && !isJSDOM;
|
|
51
|
+
const enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector) && !isJSDOM;
|
|
32
52
|
const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
|
|
33
53
|
const outerSize = dimensions.viewportOuterSize;
|
|
34
54
|
const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector);
|
|
@@ -50,19 +70,34 @@ export const useGridVirtualScroller = () => {
|
|
|
50
70
|
const columnsTotalWidth = dimensions.columnsTotalWidth;
|
|
51
71
|
const hasColSpan = useGridSelector(apiRef, gridHasColSpanSelector);
|
|
52
72
|
useResizeObserver(mainRef, () => apiRef.current.resize());
|
|
53
|
-
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
* Scroll context logic
|
|
76
|
+
* ====================
|
|
77
|
+
* We only render the cells contained in the `renderContext`. However, when the user starts scrolling the grid
|
|
78
|
+
* in a direction, we want to render as many cells as possible in that direction, as to avoid presenting white
|
|
79
|
+
* areas if the user scrolls too fast/far and the viewport ends up in a region we haven't rendered yet. To render
|
|
80
|
+
* more cells, we store some offsets to add to the viewport in `scrollCache.buffer`. Those offsets make the render
|
|
81
|
+
* context wider in the direction the user is going, but also makes the buffer around the viewport `0` for the
|
|
82
|
+
* dimension (horizontal or vertical) in which the user is not scrolling. So if the normal viewport is 8 columns
|
|
83
|
+
* wide, with a 1 column buffer (10 columns total), then we want it to be exactly 8 columns wide during vertical
|
|
84
|
+
* scroll.
|
|
85
|
+
* However, we don't want the rows in the old context to re-render from e.g. 10 columns to 8 columns, because that's
|
|
86
|
+
* work that's not necessary. Thus we store the context at the start of the scroll in `frozenContext`, and the rows
|
|
87
|
+
* that are part of this old context will keep their same render context as to avoid re-rendering.
|
|
88
|
+
*/
|
|
89
|
+
const scrollPosition = React.useRef(EMPTY_SCROLL_POSITION);
|
|
90
|
+
const previousContextScrollPosition = React.useRef(EMPTY_SCROLL_POSITION);
|
|
54
91
|
const previousRowContext = React.useRef(EMPTY_RENDER_CONTEXT);
|
|
55
92
|
const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}).current;
|
|
60
|
-
const prevTotalWidth = React.useRef(columnsTotalWidth);
|
|
93
|
+
const scrollTimeout = useTimeout();
|
|
94
|
+
const frozenContext = React.useRef(undefined);
|
|
95
|
+
const scrollCache = useLazyRef(() => createScrollCache(rootProps.rowBufferPx, rootProps.columnBufferPx, dimensions.rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6)).current;
|
|
61
96
|
const focusedCell = {
|
|
62
97
|
rowIndex: React.useMemo(() => cellFocus ? currentPage.rows.findIndex(row => row.id === cellFocus.id) : -1, [cellFocus, currentPage.rows]),
|
|
63
98
|
columnIndex: React.useMemo(() => cellFocus ? visibleColumns.findIndex(column => column.field === cellFocus.field) : -1, [cellFocus, visibleColumns])
|
|
64
99
|
};
|
|
65
|
-
const updateRenderContext = React.useCallback(
|
|
100
|
+
const updateRenderContext = React.useCallback(nextRenderContext => {
|
|
66
101
|
if (areRenderContextsEqual(nextRenderContext, apiRef.current.state.virtualization.renderContext)) {
|
|
67
102
|
return;
|
|
68
103
|
}
|
|
@@ -82,41 +117,67 @@ export const useGridVirtualScroller = () => {
|
|
|
82
117
|
previousRowContext.current = nextRenderContext;
|
|
83
118
|
apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext);
|
|
84
119
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}, [apiRef, dimensions.isReady, dimensions.columnsTotalWidth]);
|
|
120
|
+
previousContextScrollPosition.current = scrollPosition.current;
|
|
121
|
+
}, [apiRef, dimensions.isReady]);
|
|
88
122
|
const triggerUpdateRenderContext = () => {
|
|
89
|
-
const
|
|
90
|
-
|
|
123
|
+
const newScroll = {
|
|
124
|
+
top: scrollerRef.current.scrollTop,
|
|
125
|
+
left: scrollerRef.current.scrollLeft
|
|
126
|
+
};
|
|
127
|
+
const dx = newScroll.left - scrollPosition.current.left;
|
|
128
|
+
const dy = newScroll.top - scrollPosition.current.top;
|
|
129
|
+
const isScrolling = dx !== 0 || dy !== 0;
|
|
130
|
+
scrollPosition.current = newScroll;
|
|
131
|
+
const direction = isScrolling ? directionForDelta(dx, dy) : ScrollDirection.NONE;
|
|
91
132
|
|
|
92
133
|
// Since previous render, we have scrolled...
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
134
|
+
const rowScroll = Math.abs(scrollPosition.current.top - previousContextScrollPosition.current.top);
|
|
135
|
+
const columnScroll = Math.abs(scrollPosition.current.left - previousContextScrollPosition.current.left);
|
|
136
|
+
|
|
137
|
+
// PERF: use the computed minimum column width instead of a static one
|
|
138
|
+
const didCrossThreshold = rowScroll >= dimensions.rowHeight || columnScroll >= MINIMUM_COLUMN_WIDTH;
|
|
139
|
+
const didChangeDirection = scrollCache.direction !== direction;
|
|
140
|
+
const shouldUpdate = didCrossThreshold || didChangeDirection;
|
|
98
141
|
if (!shouldUpdate) {
|
|
99
|
-
return
|
|
142
|
+
return renderContext;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Render a new context
|
|
146
|
+
|
|
147
|
+
if (didChangeDirection) {
|
|
148
|
+
switch (direction) {
|
|
149
|
+
case ScrollDirection.NONE:
|
|
150
|
+
case ScrollDirection.LEFT:
|
|
151
|
+
case ScrollDirection.RIGHT:
|
|
152
|
+
frozenContext.current = undefined;
|
|
153
|
+
break;
|
|
154
|
+
default:
|
|
155
|
+
frozenContext.current = renderContext;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
100
158
|
}
|
|
159
|
+
scrollCache.direction = direction;
|
|
160
|
+
scrollCache.buffer = bufferForDirection(direction, rootProps.rowBufferPx, rootProps.columnBufferPx, dimensions.rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6);
|
|
161
|
+
const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
|
|
162
|
+
const nextRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache);
|
|
101
163
|
|
|
102
164
|
// Prevents batching render context changes
|
|
103
165
|
ReactDOM.flushSync(() => {
|
|
104
|
-
updateRenderContext(nextRenderContext
|
|
166
|
+
updateRenderContext(nextRenderContext);
|
|
105
167
|
});
|
|
168
|
+
scrollTimeout.start(1000, triggerUpdateRenderContext);
|
|
106
169
|
return nextRenderContext;
|
|
107
170
|
};
|
|
108
171
|
const forceUpdateRenderContext = () => {
|
|
109
172
|
const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
|
|
110
|
-
const
|
|
111
|
-
updateRenderContext(nextRenderContext
|
|
173
|
+
const nextRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache);
|
|
174
|
+
updateRenderContext(nextRenderContext);
|
|
112
175
|
};
|
|
113
176
|
const handleScroll = useEventCallback(event => {
|
|
114
177
|
const {
|
|
115
178
|
scrollTop,
|
|
116
179
|
scrollLeft
|
|
117
180
|
} = event.currentTarget;
|
|
118
|
-
scrollPosition.top = scrollTop;
|
|
119
|
-
scrollPosition.left = scrollLeft;
|
|
120
181
|
|
|
121
182
|
// On iOS and macOS, negative offsets are possible when swiping past the start
|
|
122
183
|
if (scrollTop < 0) {
|
|
@@ -146,12 +207,10 @@ export const useGridVirtualScroller = () => {
|
|
|
146
207
|
apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
|
|
147
208
|
});
|
|
148
209
|
const getRows = (params = {}) => {
|
|
149
|
-
var _params$renderContext, _params$rows, _rootProps$slotProps;
|
|
150
210
|
if (!params.rows && !currentPage.range) {
|
|
151
211
|
return [];
|
|
152
212
|
}
|
|
153
|
-
const
|
|
154
|
-
const currentRenderContext = (_params$renderContext = params.renderContext) != null ? _params$renderContext : renderContext;
|
|
213
|
+
const baseRenderContext = params.renderContext ?? renderContext;
|
|
155
214
|
const isLastSection = !hasBottomPinnedRows && params.position === undefined || hasBottomPinnedRows && params.position === 'bottom';
|
|
156
215
|
const isPinnedSection = params.position !== undefined;
|
|
157
216
|
let rowIndexOffset;
|
|
@@ -168,9 +227,9 @@ export const useGridVirtualScroller = () => {
|
|
|
168
227
|
rowIndexOffset = pinnedRows.top.length;
|
|
169
228
|
break;
|
|
170
229
|
}
|
|
171
|
-
const rowModels =
|
|
172
|
-
const firstRowToRender =
|
|
173
|
-
const lastRowToRender = Math.min(
|
|
230
|
+
const rowModels = params.rows ?? currentPage.rows;
|
|
231
|
+
const firstRowToRender = baseRenderContext.firstRowIndex;
|
|
232
|
+
const lastRowToRender = Math.min(baseRenderContext.lastRowIndex, rowModels.length);
|
|
174
233
|
const rowIndexes = params.rows ? range(0, params.rows.length) : range(firstRowToRender, lastRowToRender);
|
|
175
234
|
let virtualRowIndex = -1;
|
|
176
235
|
if (!isPinnedSection && focusedCell.rowIndex !== -1) {
|
|
@@ -184,9 +243,9 @@ export const useGridVirtualScroller = () => {
|
|
|
184
243
|
}
|
|
185
244
|
}
|
|
186
245
|
const rows = [];
|
|
187
|
-
const rowProps =
|
|
246
|
+
const rowProps = rootProps.slotProps?.row;
|
|
247
|
+
const columnPositions = gridColumnPositionsSelector(apiRef);
|
|
188
248
|
rowIndexes.forEach(rowIndexInPage => {
|
|
189
|
-
var _currentPage$range;
|
|
190
249
|
const {
|
|
191
250
|
id,
|
|
192
251
|
model
|
|
@@ -219,7 +278,7 @@ export const useGridVirtualScroller = () => {
|
|
|
219
278
|
});
|
|
220
279
|
}
|
|
221
280
|
}
|
|
222
|
-
const hasFocus =
|
|
281
|
+
const hasFocus = cellFocus?.id === id;
|
|
223
282
|
const baseRowHeight = !apiRef.current.rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
|
|
224
283
|
let isSelected;
|
|
225
284
|
if (selectedRowsLookup[id] == null) {
|
|
@@ -250,8 +309,12 @@ export const useGridVirtualScroller = () => {
|
|
|
250
309
|
const cellParams = apiRef.current.getCellParams(id, cellTabIndex.field);
|
|
251
310
|
tabbableCell = cellParams.cellMode === 'view' ? cellTabIndex.field : null;
|
|
252
311
|
}
|
|
312
|
+
let currentRenderContext = baseRenderContext;
|
|
313
|
+
if (!isPinnedSection && frozenContext.current && rowIndexInPage >= frozenContext.current.firstRowIndex && rowIndexInPage < frozenContext.current.lastRowIndex) {
|
|
314
|
+
currentRenderContext = frozenContext.current;
|
|
315
|
+
}
|
|
253
316
|
const offsetLeft = computeOffsetLeft(columnPositions, currentRenderContext, theme.direction, pinnedColumns.left.length);
|
|
254
|
-
const rowIndex = (
|
|
317
|
+
const rowIndex = (currentPage?.range?.firstRowIndex || 0) + rowIndexOffset + rowIndexInPage;
|
|
255
318
|
rows.push( /*#__PURE__*/_jsx(rootProps.slots.row, _extends({
|
|
256
319
|
row: model,
|
|
257
320
|
rowId: id,
|
|
@@ -275,8 +338,7 @@ export const useGridVirtualScroller = () => {
|
|
|
275
338
|
rows.push(panel);
|
|
276
339
|
}
|
|
277
340
|
if (isLastVisible) {
|
|
278
|
-
|
|
279
|
-
rows.push((_apiRef$current$getIn = (_apiRef$current = apiRef.current).getInfiniteLoadingTriggerElement) == null ? void 0 : _apiRef$current$getIn.call(_apiRef$current, {
|
|
341
|
+
rows.push(apiRef.current.getInfiniteLoadingTriggerElement?.({
|
|
280
342
|
lastRowId: id
|
|
281
343
|
}));
|
|
282
344
|
}
|
|
@@ -322,11 +384,11 @@ export const useGridVirtualScroller = () => {
|
|
|
322
384
|
}, [enabled, gridRootRef, scrollerRef]);
|
|
323
385
|
useRunOnce(outerSize.width !== 0, () => {
|
|
324
386
|
const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
|
|
325
|
-
const
|
|
326
|
-
updateRenderContext(initialRenderContext
|
|
387
|
+
const initialRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache);
|
|
388
|
+
updateRenderContext(initialRenderContext);
|
|
327
389
|
apiRef.current.publishEvent('scrollPositionChange', {
|
|
328
|
-
top: scrollPosition.top,
|
|
329
|
-
left: scrollPosition.left,
|
|
390
|
+
top: scrollPosition.current.top,
|
|
391
|
+
left: scrollPosition.current.left,
|
|
330
392
|
renderContext: initialRenderContext
|
|
331
393
|
});
|
|
332
394
|
});
|
|
@@ -372,26 +434,31 @@ export const useGridVirtualScroller = () => {
|
|
|
372
434
|
function inputsSelector(apiRef, rootProps, enabled, enabledForColumns) {
|
|
373
435
|
const dimensions = gridDimensionsSelector(apiRef.current.state);
|
|
374
436
|
const currentPage = getVisibleRows(apiRef, rootProps);
|
|
437
|
+
const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
|
|
438
|
+
const lastRowId = apiRef.current.state.rows.dataRowIds.at(-1);
|
|
439
|
+
const lastColumn = visibleColumns.at(-1);
|
|
375
440
|
return {
|
|
376
441
|
enabled,
|
|
377
442
|
enabledForColumns,
|
|
378
443
|
apiRef,
|
|
379
444
|
autoHeight: rootProps.autoHeight,
|
|
380
|
-
|
|
381
|
-
|
|
445
|
+
rowBufferPx: rootProps.rowBufferPx,
|
|
446
|
+
columnBufferPx: rootProps.columnBufferPx,
|
|
382
447
|
leftPinnedWidth: dimensions.leftPinnedWidth,
|
|
383
448
|
columnsTotalWidth: dimensions.columnsTotalWidth,
|
|
384
449
|
viewportInnerWidth: dimensions.viewportInnerSize.width,
|
|
385
450
|
viewportInnerHeight: dimensions.viewportInnerSize.height,
|
|
451
|
+
lastRowHeight: lastRowId !== undefined ? apiRef.current.unstable_getRowHeight(lastRowId) : 0,
|
|
452
|
+
lastColumnWidth: lastColumn?.computedWidth ?? 0,
|
|
386
453
|
rowsMeta: gridRowsMetaSelector(apiRef.current.state),
|
|
387
454
|
columnPositions: gridColumnPositionsSelector(apiRef),
|
|
388
455
|
rows: currentPage.rows,
|
|
389
456
|
range: currentPage.range,
|
|
390
457
|
pinnedColumns: gridVisiblePinnedColumnDefinitionsSelector(apiRef),
|
|
391
|
-
visibleColumns
|
|
458
|
+
visibleColumns
|
|
392
459
|
};
|
|
393
460
|
}
|
|
394
|
-
function computeRenderContext(inputs, scrollPosition) {
|
|
461
|
+
function computeRenderContext(inputs, scrollPosition, scrollCache) {
|
|
395
462
|
let renderContext;
|
|
396
463
|
if (!inputs.enabled) {
|
|
397
464
|
renderContext = {
|
|
@@ -409,7 +476,10 @@ function computeRenderContext(inputs, scrollPosition) {
|
|
|
409
476
|
|
|
410
477
|
// Clamp the value because the search may return an index out of bounds.
|
|
411
478
|
// In the last index, this is not needed because Array.slice doesn't include it.
|
|
412
|
-
const firstRowIndex = Math.min(getNearestIndexToRender(inputs, top
|
|
479
|
+
const firstRowIndex = Math.min(getNearestIndexToRender(inputs, top, {
|
|
480
|
+
atStart: true,
|
|
481
|
+
lastPosition: inputs.rowsMeta.positions[inputs.rowsMeta.positions.length - 1] + inputs.lastRowHeight
|
|
482
|
+
}), inputs.rowsMeta.positions.length - 1);
|
|
413
483
|
const lastRowIndex = inputs.autoHeight ? firstRowIndex + inputs.rows.length : getNearestIndexToRender(inputs, top + inputs.viewportInnerHeight);
|
|
414
484
|
let firstColumnIndex = 0;
|
|
415
485
|
let lastColumnIndex = inputs.columnPositions.length;
|
|
@@ -420,7 +490,10 @@ function computeRenderContext(inputs, scrollPosition) {
|
|
|
420
490
|
lastIndex: lastRowIndex,
|
|
421
491
|
minFirstIndex: 0,
|
|
422
492
|
maxLastIndex: inputs.rows.length,
|
|
423
|
-
|
|
493
|
+
bufferBefore: scrollCache.buffer.rowBefore,
|
|
494
|
+
bufferAfter: scrollCache.buffer.rowAfter,
|
|
495
|
+
positions: inputs.rowsMeta.positions,
|
|
496
|
+
lastSize: inputs.lastRowHeight
|
|
424
497
|
});
|
|
425
498
|
for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
|
|
426
499
|
const row = inputs.rows[i];
|
|
@@ -441,29 +514,28 @@ function computeRenderContext(inputs, scrollPosition) {
|
|
|
441
514
|
lastColumnIndex
|
|
442
515
|
};
|
|
443
516
|
}
|
|
444
|
-
const actualRenderContext = deriveRenderContext(inputs
|
|
445
|
-
return
|
|
517
|
+
const actualRenderContext = deriveRenderContext(inputs, renderContext, scrollCache);
|
|
518
|
+
return actualRenderContext;
|
|
446
519
|
}
|
|
447
|
-
function getNearestIndexToRender(inputs, offset) {
|
|
448
|
-
var _inputs$range, _inputs$range2;
|
|
520
|
+
function getNearestIndexToRender(inputs, offset, options) {
|
|
449
521
|
const lastMeasuredIndexRelativeToAllRows = inputs.apiRef.current.getLastMeasuredRowIndex();
|
|
450
522
|
let allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
|
|
451
|
-
if (
|
|
523
|
+
if (inputs.range?.lastRowIndex && !allRowsMeasured) {
|
|
452
524
|
// Check if all rows in this page are already measured
|
|
453
525
|
allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= inputs.range.lastRowIndex;
|
|
454
526
|
}
|
|
455
|
-
const lastMeasuredIndexRelativeToCurrentPage = clamp(lastMeasuredIndexRelativeToAllRows - (
|
|
527
|
+
const lastMeasuredIndexRelativeToCurrentPage = clamp(lastMeasuredIndexRelativeToAllRows - (inputs.range?.firstRowIndex || 0), 0, inputs.rowsMeta.positions.length);
|
|
456
528
|
if (allRowsMeasured || inputs.rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset) {
|
|
457
529
|
// If all rows were measured (when no row has "auto" as height) or all rows before the offset
|
|
458
530
|
// were measured, then use a binary search because it's faster.
|
|
459
|
-
return binarySearch(offset, inputs.rowsMeta.positions);
|
|
531
|
+
return binarySearch(offset, inputs.rowsMeta.positions, options);
|
|
460
532
|
}
|
|
461
533
|
|
|
462
534
|
// Otherwise, use an exponential search.
|
|
463
535
|
// If rows have "auto" as height, their positions will be based on estimated heights.
|
|
464
536
|
// In this case, we can skip several steps until we find a position higher than the offset.
|
|
465
537
|
// Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
|
|
466
|
-
return exponentialSearch(offset, inputs.rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage);
|
|
538
|
+
return exponentialSearch(offset, inputs.rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage, options);
|
|
467
539
|
}
|
|
468
540
|
|
|
469
541
|
/**
|
|
@@ -471,27 +543,33 @@ function getNearestIndexToRender(inputs, offset) {
|
|
|
471
543
|
* computes the actual render context based on pinned elements, buffer dimensions and
|
|
472
544
|
* spanning.
|
|
473
545
|
*/
|
|
474
|
-
function deriveRenderContext(
|
|
546
|
+
function deriveRenderContext(inputs, nextRenderContext, scrollCache) {
|
|
475
547
|
const [firstRowToRender, lastRowToRender] = getIndexesToRender({
|
|
476
548
|
firstIndex: nextRenderContext.firstRowIndex,
|
|
477
549
|
lastIndex: nextRenderContext.lastRowIndex,
|
|
478
550
|
minFirstIndex: 0,
|
|
479
|
-
maxLastIndex: rows.length,
|
|
480
|
-
|
|
551
|
+
maxLastIndex: inputs.rows.length,
|
|
552
|
+
bufferBefore: scrollCache.buffer.rowBefore,
|
|
553
|
+
bufferAfter: scrollCache.buffer.rowAfter,
|
|
554
|
+
positions: inputs.rowsMeta.positions,
|
|
555
|
+
lastSize: inputs.lastRowHeight
|
|
481
556
|
});
|
|
482
557
|
const [initialFirstColumnToRender, lastColumnToRender] = getIndexesToRender({
|
|
483
558
|
firstIndex: nextRenderContext.firstColumnIndex,
|
|
484
559
|
lastIndex: nextRenderContext.lastColumnIndex,
|
|
485
|
-
minFirstIndex: pinnedColumns.left.length,
|
|
486
|
-
maxLastIndex: visibleColumns.length - pinnedColumns.right.length,
|
|
487
|
-
|
|
560
|
+
minFirstIndex: inputs.pinnedColumns.left.length,
|
|
561
|
+
maxLastIndex: inputs.visibleColumns.length - inputs.pinnedColumns.right.length,
|
|
562
|
+
bufferBefore: scrollCache.buffer.columnBefore,
|
|
563
|
+
bufferAfter: scrollCache.buffer.columnAfter,
|
|
564
|
+
positions: inputs.columnPositions,
|
|
565
|
+
lastSize: inputs.lastColumnWidth
|
|
488
566
|
});
|
|
489
567
|
const firstColumnToRender = getFirstNonSpannedColumnToRender({
|
|
490
568
|
firstColumnToRender: initialFirstColumnToRender,
|
|
491
|
-
apiRef,
|
|
569
|
+
apiRef: inputs.apiRef,
|
|
492
570
|
firstRowToRender,
|
|
493
571
|
lastRowToRender,
|
|
494
|
-
visibleRows: rows
|
|
572
|
+
visibleRows: inputs.rows
|
|
495
573
|
});
|
|
496
574
|
return {
|
|
497
575
|
firstRowIndex: firstRowToRender,
|
|
@@ -516,7 +594,7 @@ function binarySearch(offset, positions, options = undefined, sliceStart = 0, sl
|
|
|
516
594
|
const pivot = sliceStart + Math.floor((sliceEnd - sliceStart) / 2);
|
|
517
595
|
const position = positions[pivot];
|
|
518
596
|
let isBefore;
|
|
519
|
-
if (options
|
|
597
|
+
if (options?.atStart) {
|
|
520
598
|
const width = (pivot === positions.length - 1 ? options.lastPosition : positions[pivot + 1]) - position;
|
|
521
599
|
isBefore = offset - width < position;
|
|
522
600
|
} else {
|
|
@@ -524,22 +602,32 @@ function binarySearch(offset, positions, options = undefined, sliceStart = 0, sl
|
|
|
524
602
|
}
|
|
525
603
|
return isBefore ? binarySearch(offset, positions, options, sliceStart, pivot) : binarySearch(offset, positions, options, pivot + 1, sliceEnd);
|
|
526
604
|
}
|
|
527
|
-
function exponentialSearch(offset, positions, index) {
|
|
605
|
+
function exponentialSearch(offset, positions, index, options = undefined) {
|
|
528
606
|
let interval = 1;
|
|
529
607
|
while (index < positions.length && Math.abs(positions[index]) < offset) {
|
|
530
608
|
index += interval;
|
|
531
609
|
interval *= 2;
|
|
532
610
|
}
|
|
533
|
-
return binarySearch(offset, positions,
|
|
611
|
+
return binarySearch(offset, positions, options, Math.floor(index / 2), Math.min(index, positions.length));
|
|
534
612
|
}
|
|
535
613
|
function getIndexesToRender({
|
|
536
614
|
firstIndex,
|
|
537
615
|
lastIndex,
|
|
538
|
-
|
|
616
|
+
bufferBefore,
|
|
617
|
+
bufferAfter,
|
|
539
618
|
minFirstIndex,
|
|
540
|
-
maxLastIndex
|
|
619
|
+
maxLastIndex,
|
|
620
|
+
positions,
|
|
621
|
+
lastSize
|
|
541
622
|
}) {
|
|
542
|
-
|
|
623
|
+
const firstPosition = positions[firstIndex] - bufferBefore;
|
|
624
|
+
const lastPosition = positions[lastIndex] + bufferAfter;
|
|
625
|
+
const firstIndexPadded = binarySearch(firstPosition, positions, {
|
|
626
|
+
atStart: true,
|
|
627
|
+
lastPosition: positions[positions.length - 1] + lastSize
|
|
628
|
+
});
|
|
629
|
+
const lastIndexPadded = binarySearch(lastPosition, positions);
|
|
630
|
+
return [clamp(firstIndexPadded, minFirstIndex, maxLastIndex), clamp(lastIndexPadded, minFirstIndex, maxLastIndex)];
|
|
543
631
|
}
|
|
544
632
|
export function areRenderContextsEqual(context1, context2) {
|
|
545
633
|
if (context1 === context2) {
|
|
@@ -548,8 +636,69 @@ export function areRenderContextsEqual(context1, context2) {
|
|
|
548
636
|
return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
|
|
549
637
|
}
|
|
550
638
|
export function computeOffsetLeft(columnPositions, renderContext, direction, pinnedLeftLength) {
|
|
551
|
-
var _columnPositions$rend, _columnPositions$pinn;
|
|
552
639
|
const factor = direction === 'ltr' ? 1 : -1;
|
|
553
|
-
const left = factor * (
|
|
640
|
+
const left = factor * (columnPositions[renderContext.firstColumnIndex] ?? 0) - (columnPositions[pinnedLeftLength] ?? 0);
|
|
554
641
|
return left;
|
|
642
|
+
}
|
|
643
|
+
function directionForDelta(dx, dy) {
|
|
644
|
+
if (dx === 0 && dy === 0) {
|
|
645
|
+
return ScrollDirection.NONE;
|
|
646
|
+
}
|
|
647
|
+
/* eslint-disable */
|
|
648
|
+
if (Math.abs(dy) >= Math.abs(dx)) {
|
|
649
|
+
if (dy > 0) {
|
|
650
|
+
return ScrollDirection.DOWN;
|
|
651
|
+
} else {
|
|
652
|
+
return ScrollDirection.UP;
|
|
653
|
+
}
|
|
654
|
+
} else {
|
|
655
|
+
if (dx > 0) {
|
|
656
|
+
return ScrollDirection.RIGHT;
|
|
657
|
+
} else {
|
|
658
|
+
return ScrollDirection.LEFT;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
/* eslint-enable */
|
|
662
|
+
}
|
|
663
|
+
function bufferForDirection(direction, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer) {
|
|
664
|
+
switch (direction) {
|
|
665
|
+
case ScrollDirection.NONE:
|
|
666
|
+
return {
|
|
667
|
+
rowAfter: rowBufferPx,
|
|
668
|
+
rowBefore: rowBufferPx,
|
|
669
|
+
columnAfter: columnBufferPx,
|
|
670
|
+
columnBefore: columnBufferPx
|
|
671
|
+
};
|
|
672
|
+
case ScrollDirection.LEFT:
|
|
673
|
+
return {
|
|
674
|
+
rowAfter: 0,
|
|
675
|
+
rowBefore: 0,
|
|
676
|
+
columnAfter: 0,
|
|
677
|
+
columnBefore: horizontalBuffer
|
|
678
|
+
};
|
|
679
|
+
case ScrollDirection.RIGHT:
|
|
680
|
+
return {
|
|
681
|
+
rowAfter: 0,
|
|
682
|
+
rowBefore: 0,
|
|
683
|
+
columnAfter: horizontalBuffer,
|
|
684
|
+
columnBefore: 0
|
|
685
|
+
};
|
|
686
|
+
case ScrollDirection.UP:
|
|
687
|
+
return {
|
|
688
|
+
rowAfter: 0,
|
|
689
|
+
rowBefore: verticalBuffer,
|
|
690
|
+
columnAfter: 0,
|
|
691
|
+
columnBefore: 0
|
|
692
|
+
};
|
|
693
|
+
case ScrollDirection.DOWN:
|
|
694
|
+
return {
|
|
695
|
+
rowAfter: verticalBuffer,
|
|
696
|
+
rowBefore: 0,
|
|
697
|
+
columnAfter: 0,
|
|
698
|
+
columnBefore: 0
|
|
699
|
+
};
|
|
700
|
+
default:
|
|
701
|
+
// eslint unable to figure out enum exhaustiveness
|
|
702
|
+
throw new Error('unreachable');
|
|
703
|
+
}
|
|
555
704
|
}
|
|
@@ -29,8 +29,7 @@ export function createUseGridApiEventHandler(registryContainer) {
|
|
|
29
29
|
if (!subscription.current && handlerRef.current) {
|
|
30
30
|
const enhancedHandler = (params, event, details) => {
|
|
31
31
|
if (!event.defaultMuiPrevented) {
|
|
32
|
-
|
|
33
|
-
(_handlerRef$current = handlerRef.current) == null || _handlerRef$current.call(handlerRef, params, event, details);
|
|
32
|
+
handlerRef.current?.(params, event, details);
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
35
|
subscription.current = apiRef.current.subscribeEvent(eventName, enhancedHandler, options);
|
|
@@ -41,8 +40,7 @@ export function createUseGridApiEventHandler(registryContainer) {
|
|
|
41
40
|
registryContainer.registry.register(objectRetainedByReact,
|
|
42
41
|
// The callback below will be called once this reference stops being retained
|
|
43
42
|
() => {
|
|
44
|
-
|
|
45
|
-
(_subscription$current = subscription.current) == null || _subscription$current.call(subscription);
|
|
43
|
+
subscription.current?.();
|
|
46
44
|
subscription.current = null;
|
|
47
45
|
cleanupTokenRef.current = null;
|
|
48
46
|
}, cleanupTokenRef.current);
|
|
@@ -58,8 +56,7 @@ export function createUseGridApiEventHandler(registryContainer) {
|
|
|
58
56
|
if (!subscription.current && handlerRef.current) {
|
|
59
57
|
const enhancedHandler = (params, event, details) => {
|
|
60
58
|
if (!event.defaultMuiPrevented) {
|
|
61
|
-
|
|
62
|
-
(_handlerRef$current2 = handlerRef.current) == null || _handlerRef$current2.call(handlerRef, params, event, details);
|
|
59
|
+
handlerRef.current?.(params, event, details);
|
|
63
60
|
}
|
|
64
61
|
};
|
|
65
62
|
subscription.current = apiRef.current.subscribeEvent(eventName, enhancedHandler, options);
|
|
@@ -71,8 +68,7 @@ export function createUseGridApiEventHandler(registryContainer) {
|
|
|
71
68
|
cleanupTokenRef.current = null;
|
|
72
69
|
}
|
|
73
70
|
return () => {
|
|
74
|
-
|
|
75
|
-
(_subscription$current2 = subscription.current) == null || _subscription$current2.call(subscription);
|
|
71
|
+
subscription.current?.();
|
|
76
72
|
subscription.current = null;
|
|
77
73
|
};
|
|
78
74
|
}, [apiRef, eventName, options]);
|
|
@@ -85,8 +81,7 @@ const registryContainer = {
|
|
|
85
81
|
// TODO: move to @mui/x-data-grid/internals
|
|
86
82
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
87
83
|
export const unstable_resetCleanupTracking = () => {
|
|
88
|
-
|
|
89
|
-
(_registryContainer$re = registryContainer.registry) == null || _registryContainer$re.reset();
|
|
84
|
+
registryContainer.registry?.reset();
|
|
90
85
|
registryContainer.registry = null;
|
|
91
86
|
};
|
|
92
87
|
export const useGridApiEventHandler = createUseGridApiEventHandler(registryContainer);
|