@mui/x-data-grid 7.19.0 → 7.21.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 +224 -43
- package/DataGrid/DataGrid.js +8 -0
- package/DataGrid/index.d.ts +0 -1
- package/DataGrid/index.js +1 -2
- package/DataGrid/useDataGridComponent.js +4 -1
- package/DataGrid/useDataGridProps.d.ts +1 -5
- package/DataGrid/useDataGridProps.js +3 -62
- package/components/GridPagination.js +1 -0
- package/components/GridRow.js +25 -36
- package/components/base/GridOverlays.js +8 -0
- package/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/components/containers/GridRootStyles.js +1 -0
- package/components/menu/columnMenu/GridColumnMenu.js +32 -0
- package/components/toolbar/GridToolbarExport.d.ts +9 -3
- package/components/toolbar/GridToolbarExport.js +55 -3
- package/components/virtualization/GridVirtualScrollbar.js +4 -0
- package/components/virtualization/GridVirtualScroller.js +2 -2
- package/constants/dataGridPropsDefaultValues.d.ts +5 -0
- package/constants/dataGridPropsDefaultValues.js +60 -0
- package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +2 -1
- package/hooks/core/useGridRefs.js +4 -0
- package/hooks/features/clipboard/useGridClipboard.js +2 -1
- package/hooks/features/columnHeaders/useGridColumnHeaders.js +3 -1
- package/hooks/features/columns/gridColumnsUtils.d.ts +1 -1
- package/hooks/features/columns/gridColumnsUtils.js +3 -0
- package/hooks/features/dimensions/useGridDimensions.js +6 -4
- package/hooks/features/editing/useGridCellEditing.js +3 -1
- package/hooks/features/editing/useGridRowEditing.js +3 -1
- package/hooks/features/events/useGridEvents.d.ts +1 -1
- package/hooks/features/events/useGridEvents.js +1 -0
- package/hooks/features/filter/gridFilterUtils.js +1 -1
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +9 -5
- package/hooks/features/listView/gridListViewSelectors.d.ts +5 -0
- package/hooks/features/listView/gridListViewSelectors.js +4 -0
- package/hooks/features/listView/useGridListView.d.ts +10 -0
- package/hooks/features/listView/useGridListView.js +54 -0
- package/hooks/features/rowSelection/useGridRowSelection.js +11 -2
- package/hooks/features/rowSelection/utils.js +6 -6
- package/hooks/features/rows/gridRowsMetaInterfaces.d.ts +16 -0
- package/hooks/features/rows/gridRowsMetaInterfaces.js +1 -0
- package/hooks/features/rows/gridRowsUtils.d.ts +3 -0
- package/hooks/features/rows/gridRowsUtils.js +15 -2
- package/hooks/features/rows/useGridParamsApi.d.ts +2 -1
- package/hooks/features/rows/useGridParamsApi.js +4 -3
- package/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/hooks/features/rows/useGridRowsMeta.js +135 -154
- package/hooks/features/scroll/useGridScroll.d.ts +1 -1
- package/hooks/features/scroll/useGridScroll.js +10 -5
- package/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/hooks/features/virtualization/useGridVirtualScroller.js +25 -11
- package/hooks/utils/useGridApiContext.js +1 -1
- package/hooks/utils/useGridApiEventHandler.d.ts +1 -1
- package/hooks/utils/useGridApiEventHandler.js +1 -1
- package/hooks/utils/useGridApiMethod.js +2 -1
- package/hooks/utils/useGridConfiguration.js +1 -1
- package/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/index.d.ts +3 -2
- package/index.js +4 -3
- package/internals/index.d.ts +2 -1
- package/internals/index.js +2 -1
- package/joy/icons.js +0 -1
- package/locales/jaJP.js +4 -4
- package/models/api/gridApiCommunity.d.ts +1 -1
- package/models/api/gridCoreApi.d.ts +9 -1
- package/models/api/gridFilterApi.d.ts +1 -1
- package/models/api/gridRowsMetaApi.d.ts +15 -14
- package/models/colDef/gridColDef.d.ts +6 -0
- package/models/colDef/index.d.ts +1 -1
- package/models/events/gridEventLookup.d.ts +7 -0
- package/models/gridApiCaches.d.ts +2 -0
- package/models/gridStateCommunity.d.ts +4 -2
- package/models/props/DataGridProps.d.ts +37 -17
- package/modern/DataGrid/DataGrid.js +8 -0
- package/modern/DataGrid/index.js +1 -2
- package/modern/DataGrid/useDataGridComponent.js +4 -1
- package/modern/DataGrid/useDataGridProps.js +3 -62
- package/modern/components/GridPagination.js +1 -0
- package/modern/components/GridRow.js +25 -36
- package/modern/components/base/GridOverlays.js +8 -0
- package/modern/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/modern/components/containers/GridRootStyles.js +1 -0
- package/modern/components/menu/columnMenu/GridColumnMenu.js +32 -0
- package/modern/components/toolbar/GridToolbarExport.js +55 -3
- package/modern/components/virtualization/GridVirtualScrollbar.js +4 -0
- package/modern/components/virtualization/GridVirtualScroller.js +2 -2
- package/modern/constants/dataGridPropsDefaultValues.js +60 -0
- package/modern/hooks/core/useGridRefs.js +4 -0
- package/modern/hooks/features/clipboard/useGridClipboard.js +2 -1
- package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +3 -1
- package/modern/hooks/features/columns/gridColumnsUtils.js +3 -0
- package/modern/hooks/features/dimensions/useGridDimensions.js +6 -4
- package/modern/hooks/features/editing/useGridCellEditing.js +3 -1
- package/modern/hooks/features/editing/useGridRowEditing.js +3 -1
- package/modern/hooks/features/events/useGridEvents.js +1 -0
- package/modern/hooks/features/filter/gridFilterUtils.js +1 -1
- package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +9 -5
- package/modern/hooks/features/listView/gridListViewSelectors.js +4 -0
- package/modern/hooks/features/listView/useGridListView.js +54 -0
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +11 -2
- package/modern/hooks/features/rowSelection/utils.js +6 -6
- package/modern/hooks/features/rows/gridRowsMetaInterfaces.js +1 -0
- package/modern/hooks/features/rows/gridRowsUtils.js +15 -2
- package/modern/hooks/features/rows/useGridParamsApi.js +4 -3
- package/modern/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/modern/hooks/features/rows/useGridRowsMeta.js +135 -154
- package/modern/hooks/features/scroll/useGridScroll.js +10 -5
- package/modern/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +25 -11
- package/modern/hooks/utils/useGridApiContext.js +1 -1
- package/modern/hooks/utils/useGridApiEventHandler.js +1 -1
- package/modern/hooks/utils/useGridApiMethod.js +2 -1
- package/modern/hooks/utils/useGridConfiguration.js +1 -1
- package/modern/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/modern/index.js +4 -3
- package/modern/internals/index.js +2 -1
- package/modern/joy/icons.js +0 -1
- package/modern/locales/jaJP.js +4 -4
- package/modern/utils/ResizeObserver.js +10 -0
- package/modern/utils/domUtils.js +1 -1
- package/modern/utils/keyboardUtils.js +12 -4
- package/node/DataGrid/DataGrid.js +8 -0
- package/node/DataGrid/index.js +1 -12
- package/node/DataGrid/useDataGridComponent.js +4 -1
- package/node/DataGrid/useDataGridProps.js +6 -65
- package/node/components/GridPagination.js +1 -0
- package/node/components/GridRow.js +25 -36
- package/node/components/base/GridOverlays.js +8 -0
- package/node/components/columnHeaders/GridColumnHeaderItem.js +1 -0
- package/node/components/containers/GridRootStyles.js +1 -0
- package/node/components/menu/columnMenu/GridColumnMenu.js +32 -0
- package/node/components/toolbar/GridToolbarExport.js +52 -0
- package/node/components/virtualization/GridVirtualScrollbar.js +4 -0
- package/node/components/virtualization/GridVirtualScroller.js +2 -2
- package/node/constants/dataGridPropsDefaultValues.js +66 -0
- package/node/hooks/core/useGridRefs.js +4 -0
- package/node/hooks/features/clipboard/useGridClipboard.js +2 -1
- package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +3 -1
- package/node/hooks/features/columns/gridColumnsUtils.js +3 -0
- package/node/hooks/features/dimensions/useGridDimensions.js +5 -3
- package/node/hooks/features/editing/useGridCellEditing.js +3 -1
- package/node/hooks/features/editing/useGridRowEditing.js +3 -1
- package/node/hooks/features/events/useGridEvents.js +1 -0
- package/node/hooks/features/filter/gridFilterUtils.js +1 -1
- package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +9 -5
- package/node/hooks/features/listView/gridListViewSelectors.js +11 -0
- package/node/hooks/features/listView/useGridListView.js +64 -0
- package/node/hooks/features/rowSelection/useGridRowSelection.js +11 -2
- package/node/hooks/features/rowSelection/utils.js +6 -6
- package/node/hooks/features/rows/gridRowsMetaInterfaces.js +5 -0
- package/node/hooks/features/rows/gridRowsUtils.js +17 -3
- package/node/hooks/features/rows/useGridParamsApi.js +4 -3
- package/node/hooks/features/rows/useGridRowSpanning.js +1 -1
- package/node/hooks/features/rows/useGridRowsMeta.js +136 -154
- package/node/hooks/features/scroll/useGridScroll.js +10 -5
- package/node/hooks/features/sorting/gridSortingUtils.js +1 -1
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +25 -11
- package/node/hooks/utils/useGridApiContext.js +1 -1
- package/node/hooks/utils/useGridApiEventHandler.js +1 -1
- package/node/hooks/utils/useGridApiMethod.js +3 -1
- package/node/hooks/utils/useGridConfiguration.js +1 -1
- package/node/hooks/utils/useGridPrivateApiContext.js +1 -1
- package/node/index.js +13 -1
- package/node/internals/index.js +22 -0
- package/node/joy/icons.js +0 -1
- package/node/locales/jaJP.js +4 -4
- package/node/utils/ResizeObserver.js +16 -0
- package/node/utils/domUtils.js +1 -1
- package/node/utils/keyboardUtils.js +15 -5
- package/package.json +4 -4
- package/utils/ResizeObserver.d.ts +4 -0
- package/utils/ResizeObserver.js +10 -0
- package/utils/domUtils.js +1 -1
- package/utils/keyboardUtils.d.ts +1 -0
- package/utils/keyboardUtils.js +12 -4
|
@@ -246,7 +246,11 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
246
246
|
/*
|
|
247
247
|
* EVENTS
|
|
248
248
|
*/
|
|
249
|
+
const isFirstRender = React.useRef(true);
|
|
249
250
|
const removeOutdatedSelection = React.useCallback((sortModelUpdated = false) => {
|
|
251
|
+
if (isFirstRender.current) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
250
254
|
const currentSelection = gridRowSelectionStateSelector(apiRef.current.state);
|
|
251
255
|
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
|
|
252
256
|
|
|
@@ -254,7 +258,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
254
258
|
const selectionLookup = _extends({}, selectedIdsLookupSelector(apiRef));
|
|
255
259
|
let hasChanged = false;
|
|
256
260
|
currentSelection.forEach(id => {
|
|
257
|
-
if (filteredRowsLookup[id]
|
|
261
|
+
if (filteredRowsLookup[id] !== true) {
|
|
258
262
|
if (props.keepNonExistentRowsSelected) {
|
|
259
263
|
return;
|
|
260
264
|
}
|
|
@@ -408,7 +412,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
408
412
|
handleSingleRowSelection(params.id, event);
|
|
409
413
|
return;
|
|
410
414
|
}
|
|
411
|
-
if (event.
|
|
415
|
+
if (String.fromCharCode(event.keyCode) === 'A' && (event.ctrlKey || event.metaKey)) {
|
|
412
416
|
event.preventDefault();
|
|
413
417
|
selectRows(apiRef.current.getAllRowIds(), true);
|
|
414
418
|
}
|
|
@@ -462,4 +466,9 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
462
466
|
React.useEffect(() => {
|
|
463
467
|
runIfRowSelectionIsEnabled(removeOutdatedSelection);
|
|
464
468
|
}, [removeOutdatedSelection, runIfRowSelectionIsEnabled]);
|
|
469
|
+
React.useEffect(() => {
|
|
470
|
+
if (isFirstRender.current) {
|
|
471
|
+
isFirstRender.current = false;
|
|
472
|
+
}
|
|
473
|
+
}, []);
|
|
465
474
|
};
|
|
@@ -44,21 +44,21 @@ export function getCheckboxPropsSelector(groupId, autoSelectParents) {
|
|
|
44
44
|
isChecked: true
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
|
-
let
|
|
48
|
-
let
|
|
47
|
+
let selectableDescendantsCount = 0;
|
|
48
|
+
let selectedDescendantsCount = 0;
|
|
49
49
|
const startIndex = sortedRowIds.findIndex(id => id === groupId) + 1;
|
|
50
50
|
for (let index = startIndex; index < sortedRowIds.length && rowTree[sortedRowIds[index]]?.depth > groupNode.depth; index += 1) {
|
|
51
51
|
const id = sortedRowIds[index];
|
|
52
52
|
if (filteredRowsLookup[id] !== false) {
|
|
53
|
-
|
|
53
|
+
selectableDescendantsCount += 1;
|
|
54
54
|
if (rowSelectionLookup[id] !== undefined) {
|
|
55
|
-
|
|
55
|
+
selectedDescendantsCount += 1;
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
return {
|
|
60
|
-
isIndeterminate:
|
|
61
|
-
isChecked: autoSelectParents ?
|
|
60
|
+
isIndeterminate: selectedDescendantsCount > 0 && (selectedDescendantsCount < selectableDescendantsCount || rowSelectionLookup[groupId] === undefined),
|
|
61
|
+
isChecked: autoSelectParents ? selectedDescendantsCount > 0 : rowSelectionLookup[groupId] === groupId
|
|
62
62
|
};
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -24,7 +24,7 @@ export const buildRootGroup = () => ({
|
|
|
24
24
|
*/
|
|
25
25
|
export function checkGridRowIdIsValid(id, row, detailErrorMessage = 'A row was provided without id in the rows prop:') {
|
|
26
26
|
if (id == null) {
|
|
27
|
-
throw new Error(['MUI X: The
|
|
27
|
+
throw new Error(['MUI X: The Data Grid component requires all rows to have a unique `id` property.', 'Alternatively, you can use the `getRowId` prop to specify a custom id for each row.', detailErrorMessage, JSON.stringify(row)].join('\n'));
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
export const getRowIdFromRowModel = (rowModel, getRowId, detailErrorMessage) => {
|
|
@@ -306,4 +306,17 @@ export function computeRowsUpdates(apiRef, updates, getRowId) {
|
|
|
306
306
|
}
|
|
307
307
|
});
|
|
308
308
|
return nonPinnedRowsUpdates;
|
|
309
|
-
}
|
|
309
|
+
}
|
|
310
|
+
let warnedOnceInvalidRowHeight = false;
|
|
311
|
+
export const getValidRowHeight = (rowHeightProp, defaultRowHeight, warningMessage) => {
|
|
312
|
+
if (typeof rowHeightProp === 'number' && rowHeightProp > 0) {
|
|
313
|
+
return rowHeightProp;
|
|
314
|
+
}
|
|
315
|
+
if (process.env.NODE_ENV !== 'production' && !warnedOnceInvalidRowHeight && typeof rowHeightProp !== 'undefined' && rowHeightProp !== null) {
|
|
316
|
+
console.warn(warningMessage);
|
|
317
|
+
warnedOnceInvalidRowHeight = true;
|
|
318
|
+
}
|
|
319
|
+
return defaultRowHeight;
|
|
320
|
+
};
|
|
321
|
+
export const rowHeightWarning = [`MUI X: The \`rowHeight\` prop should be a number greater than 0.`, `The default value will be used instead.`].join('\n');
|
|
322
|
+
export const getRowHeightWarning = [`MUI X: The \`getRowHeight\` prop should return a number greater than 0 or 'auto'.`, `The default value will be used instead.`].join('\n');
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import { getGridCellElement, getGridColumnHeaderElement, getGridRowElement } from "../../../utils/domUtils.js";
|
|
3
3
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
|
|
4
4
|
import { gridFocusCellSelector, gridTabIndexCellSelector } from "../focus/gridFocusStateSelector.js";
|
|
5
|
+
import { gridListColumnSelector } from "../listView/gridListViewSelectors.js";
|
|
5
6
|
export class MissingRowIdError extends Error {}
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -12,7 +13,7 @@ export class MissingRowIdError extends Error {}
|
|
|
12
13
|
* TODO: Impossible priority - useGridEditing also needs to be after useGridParamsApi
|
|
13
14
|
* TODO: Impossible priority - useGridFocus also needs to be after useGridParamsApi
|
|
14
15
|
*/
|
|
15
|
-
export function useGridParamsApi(apiRef) {
|
|
16
|
+
export function useGridParamsApi(apiRef, props) {
|
|
16
17
|
const getColumnHeaderParams = React.useCallback(field => ({
|
|
17
18
|
field,
|
|
18
19
|
colDef: apiRef.current.getColumn(field)
|
|
@@ -30,7 +31,7 @@ export function useGridParamsApi(apiRef) {
|
|
|
30
31
|
return params;
|
|
31
32
|
}, [apiRef]);
|
|
32
33
|
const getCellParams = React.useCallback((id, field) => {
|
|
33
|
-
const colDef = apiRef.current.getColumn(field);
|
|
34
|
+
const colDef = props.unstable_listView ? gridListColumnSelector(apiRef.current.state) : apiRef.current.getColumn(field);
|
|
34
35
|
const row = apiRef.current.getRow(id);
|
|
35
36
|
const rowNode = apiRef.current.getRowNode(id);
|
|
36
37
|
if (!row || !rowNode) {
|
|
@@ -59,7 +60,7 @@ export function useGridParamsApi(apiRef) {
|
|
|
59
60
|
}
|
|
60
61
|
params.isEditable = colDef && apiRef.current.isCellEditable(params);
|
|
61
62
|
return params;
|
|
62
|
-
}, [apiRef]);
|
|
63
|
+
}, [apiRef, props.unstable_listView]);
|
|
63
64
|
const getCellValue = React.useCallback((id, field) => {
|
|
64
65
|
const colDef = apiRef.current.getColumn(field);
|
|
65
66
|
const row = apiRef.current.getRow(id);
|
|
@@ -202,7 +202,7 @@ export const useGridRowSpanning = (apiRef, props) => {
|
|
|
202
202
|
}
|
|
203
203
|
const rangeToProcess = getUnprocessedRange({
|
|
204
204
|
firstRowIndex: renderContext.firstRowIndex,
|
|
205
|
-
lastRowIndex: renderContext.lastRowIndex - 1
|
|
205
|
+
lastRowIndex: Math.min(renderContext.lastRowIndex - 1, range.lastRowIndex)
|
|
206
206
|
}, processedRange.current);
|
|
207
207
|
if (rangeToProcess === null) {
|
|
208
208
|
return;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import
|
|
3
|
+
import useLazyRef from '@mui/utils/useLazyRef';
|
|
4
|
+
import { ResizeObserver } from "../../../utils/ResizeObserver.js";
|
|
4
5
|
import { useGridVisibleRows } from "../../utils/useGridVisibleRows.js";
|
|
6
|
+
import { eslintUseValue } from "../../../utils/utils.js";
|
|
5
7
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
|
|
6
8
|
import { useGridSelector } from "../../utils/useGridSelector.js";
|
|
7
9
|
import { gridDensityFactorSelector } from "../density/densitySelector.js";
|
|
@@ -10,29 +12,21 @@ import { gridPaginationSelector } from "../pagination/gridPaginationSelector.js"
|
|
|
10
12
|
import { gridSortModelSelector } from "../sorting/gridSortingSelector.js";
|
|
11
13
|
import { useGridRegisterPipeApplier } from "../../core/pipeProcessing/index.js";
|
|
12
14
|
import { gridPinnedRowsSelector } from "./gridRowsSelector.js";
|
|
13
|
-
import {
|
|
15
|
+
import { gridDimensionsSelector } from "../dimensions/gridDimensionsSelectors.js";
|
|
16
|
+
import { getValidRowHeight, getRowHeightWarning } from "./gridRowsUtils.js";
|
|
17
|
+
/* eslint-disable no-underscore-dangle */
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (typeof rowHeightProp === 'number' && rowHeightProp > 0) {
|
|
26
|
-
return rowHeightProp;
|
|
27
|
-
}
|
|
28
|
-
if (process.env.NODE_ENV !== 'production' && !warnedOnceInvalidRowHeight && typeof rowHeightProp !== 'undefined' && rowHeightProp !== null) {
|
|
29
|
-
console.warn(warningMessage);
|
|
30
|
-
warnedOnceInvalidRowHeight = true;
|
|
31
|
-
}
|
|
32
|
-
return defaultRowHeight;
|
|
19
|
+
export const rowsMetaStateInitializer = (state, props, apiRef) => {
|
|
20
|
+
apiRef.current.caches.rowsMeta = {
|
|
21
|
+
heights: new Map()
|
|
22
|
+
};
|
|
23
|
+
return _extends({}, state, {
|
|
24
|
+
rowsMeta: {
|
|
25
|
+
currentPageTotalHeight: 0,
|
|
26
|
+
positions: []
|
|
27
|
+
}
|
|
28
|
+
});
|
|
33
29
|
};
|
|
34
|
-
const rowHeightWarning = [`MUI X: The \`rowHeight\` prop should be a number greater than 0.`, `The default value will be used instead.`].join('\n');
|
|
35
|
-
const getRowHeightWarning = [`MUI X: The \`getRowHeight\` prop should return a number greater than 0 or 'auto'.`, `The default value will be used instead.`].join('\n');
|
|
36
30
|
|
|
37
31
|
/**
|
|
38
32
|
* @requires useGridPageSize (method)
|
|
@@ -44,105 +38,94 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
44
38
|
getRowSpacing,
|
|
45
39
|
getEstimatedRowHeight
|
|
46
40
|
} = props;
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
// Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
|
|
41
|
+
const heightCache = apiRef.current.caches.rowsMeta.heights;
|
|
50
42
|
const lastMeasuredRowIndex = React.useRef(-1);
|
|
51
43
|
const hasRowWithAutoHeight = React.useRef(false);
|
|
44
|
+
const isHeightMetaValid = React.useRef(false);
|
|
52
45
|
const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector);
|
|
53
46
|
const filterModel = useGridSelector(apiRef, gridFilterModelSelector);
|
|
54
47
|
const paginationState = useGridSelector(apiRef, gridPaginationSelector);
|
|
55
48
|
const sortModel = useGridSelector(apiRef, gridSortModelSelector);
|
|
56
49
|
const currentPage = useGridVisibleRows(apiRef, props);
|
|
57
50
|
const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector);
|
|
58
|
-
const
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
51
|
+
const rowHeight = useGridSelector(apiRef, () => gridDimensionsSelector(apiRef.current.state).rowHeight);
|
|
52
|
+
const getRowHeightEntry = rowId => {
|
|
53
|
+
let entry = heightCache.get(rowId);
|
|
54
|
+
if (entry === undefined) {
|
|
55
|
+
entry = {
|
|
56
|
+
content: rowHeight,
|
|
57
|
+
spacingTop: 0,
|
|
58
|
+
spacingBottom: 0,
|
|
59
|
+
detail: 0,
|
|
60
|
+
autoHeight: false,
|
|
61
|
+
needsFirstMeasurement: true
|
|
62
|
+
};
|
|
63
|
+
heightCache.set(rowId, entry);
|
|
64
|
+
}
|
|
65
|
+
return entry;
|
|
66
|
+
};
|
|
67
|
+
const processHeightEntry = React.useCallback(row => {
|
|
68
|
+
// HACK: rowHeight trails behind the most up-to-date value just enough to
|
|
69
|
+
// mess the initial rowsMeta hydration :/
|
|
70
|
+
const baseRowHeight = gridDimensionsSelector(apiRef.current.state).rowHeight;
|
|
71
|
+
eslintUseValue(rowHeight);
|
|
72
|
+
const entry = apiRef.current.getRowHeightEntry(row.id);
|
|
73
|
+
if (!getRowHeightProp) {
|
|
74
|
+
entry.content = baseRowHeight;
|
|
75
|
+
entry.needsFirstMeasurement = false;
|
|
76
|
+
} else {
|
|
77
|
+
const rowHeightFromUser = getRowHeightProp(_extends({}, row, {
|
|
78
|
+
densityFactor
|
|
79
|
+
}));
|
|
80
|
+
if (rowHeightFromUser === 'auto') {
|
|
81
|
+
if (entry.needsFirstMeasurement) {
|
|
82
|
+
const estimatedRowHeight = getEstimatedRowHeight ? getEstimatedRowHeight(_extends({}, row, {
|
|
83
|
+
densityFactor
|
|
84
|
+
})) : baseRowHeight;
|
|
92
85
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
} else {
|
|
96
|
-
baseRowHeight = existingBaseRowHeight;
|
|
97
|
-
}
|
|
98
|
-
hasRowWithAutoHeight.current = true;
|
|
99
|
-
rowsHeightLookup.current[row.id].autoHeight = true;
|
|
100
|
-
} else {
|
|
101
|
-
// Default back to base rowHeight if getRowHeight returns invalid value.
|
|
102
|
-
baseRowHeight = getValidRowHeight(rowHeightFromUser, rowHeight, getRowHeightWarning);
|
|
103
|
-
rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
|
|
104
|
-
rowsHeightLookup.current[row.id].autoHeight = false;
|
|
86
|
+
// If the row was not measured yet use the estimated row height
|
|
87
|
+
entry.content = estimatedRowHeight ?? baseRowHeight;
|
|
105
88
|
}
|
|
89
|
+
hasRowWithAutoHeight.current = true;
|
|
90
|
+
entry.autoHeight = true;
|
|
106
91
|
} else {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
};
|
|
112
|
-
if (getRowSpacing) {
|
|
113
|
-
const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
|
|
114
|
-
const spacing = getRowSpacing(_extends({}, row, {
|
|
115
|
-
isFirstVisible: indexRelativeToCurrentPage === 0,
|
|
116
|
-
isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1,
|
|
117
|
-
indexRelativeToCurrentPage
|
|
118
|
-
}));
|
|
119
|
-
initialHeights.spacingTop = spacing.top ?? 0;
|
|
120
|
-
initialHeights.spacingBottom = spacing.bottom ?? 0;
|
|
92
|
+
// Default back to base rowHeight if getRowHeight returns invalid value.
|
|
93
|
+
entry.content = getValidRowHeight(rowHeightFromUser, baseRowHeight, getRowHeightWarning);
|
|
94
|
+
entry.needsFirstMeasurement = false;
|
|
95
|
+
entry.autoHeight = false;
|
|
121
96
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
97
|
+
}
|
|
98
|
+
if (getRowSpacing) {
|
|
99
|
+
const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
|
|
100
|
+
const spacing = getRowSpacing(_extends({}, row, {
|
|
101
|
+
isFirstVisible: indexRelativeToCurrentPage === 0,
|
|
102
|
+
isLastVisible: indexRelativeToCurrentPage === currentPage.rows.length - 1,
|
|
103
|
+
indexRelativeToCurrentPage
|
|
104
|
+
}));
|
|
105
|
+
entry.spacingTop = spacing.top ?? 0;
|
|
106
|
+
entry.spacingBottom = spacing.bottom ?? 0;
|
|
107
|
+
} else {
|
|
108
|
+
entry.spacingTop = 0;
|
|
109
|
+
entry.spacingBottom = 0;
|
|
110
|
+
}
|
|
111
|
+
apiRef.current.unstable_applyPipeProcessors('rowHeight', entry, row);
|
|
112
|
+
return entry;
|
|
113
|
+
}, [apiRef, currentPage.rows.length, getRowHeightProp, getEstimatedRowHeight, rowHeight, getRowSpacing, densityFactor]);
|
|
114
|
+
const hydrateRowsMeta = React.useCallback(() => {
|
|
115
|
+
hasRowWithAutoHeight.current = false;
|
|
116
|
+
pinnedRows.top.forEach(processHeightEntry);
|
|
117
|
+
pinnedRows.bottom.forEach(processHeightEntry);
|
|
126
118
|
const positions = [];
|
|
127
119
|
const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => {
|
|
128
120
|
positions.push(acc);
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
for (const key in processedSizes) {
|
|
133
|
-
const value = processedSizes[key];
|
|
134
|
-
if (key !== 'baseCenter') {
|
|
135
|
-
otherSizes += value;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return acc + processedSizes.baseCenter + otherSizes;
|
|
121
|
+
const entry = processHeightEntry(row);
|
|
122
|
+
const total = entry.content + entry.spacingTop + entry.spacingBottom + entry.detail;
|
|
123
|
+
return acc + total;
|
|
139
124
|
}, 0);
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
calculateRowProcessedSizes(row);
|
|
145
|
-
});
|
|
125
|
+
if (!hasRowWithAutoHeight.current) {
|
|
126
|
+
// No row has height=auto, so all rows are already measured
|
|
127
|
+
lastMeasuredRowIndex.current = Infinity;
|
|
128
|
+
}
|
|
146
129
|
apiRef.current.setState(state => {
|
|
147
130
|
return _extends({}, state, {
|
|
148
131
|
rowsMeta: {
|
|
@@ -151,70 +134,68 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
151
134
|
}
|
|
152
135
|
});
|
|
153
136
|
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}, [hydrateRowsMeta]);
|
|
171
|
-
const debouncedHydrateRowsMeta = React.useMemo(() => debounce(hydrateRowsMeta, props.rowPositionsDebounceMs), [hydrateRowsMeta, props.rowPositionsDebounceMs]);
|
|
172
|
-
const storeMeasuredRowHeight = React.useCallback((id, height) => {
|
|
173
|
-
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Only trigger hydration if the value is different, otherwise we trigger a loop
|
|
178
|
-
const needsHydration = rowsHeightLookup.current[id].sizes.baseCenter !== height;
|
|
179
|
-
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
180
|
-
rowsHeightLookup.current[id].sizes.baseCenter = height;
|
|
181
|
-
if (needsHydration) {
|
|
182
|
-
debouncedHydrateRowsMeta();
|
|
183
|
-
}
|
|
184
|
-
}, [debouncedHydrateRowsMeta]);
|
|
185
|
-
const rowHasAutoHeight = React.useCallback(id => {
|
|
186
|
-
return rowsHeightLookup.current[id]?.autoHeight || false;
|
|
187
|
-
}, []);
|
|
188
|
-
const getLastMeasuredRowIndex = React.useCallback(() => {
|
|
137
|
+
isHeightMetaValid.current = true;
|
|
138
|
+
}, [apiRef, pinnedRows, currentPage.rows, processHeightEntry]);
|
|
139
|
+
const getRowHeight = rowId => {
|
|
140
|
+
return heightCache.get(rowId)?.content ?? rowHeight;
|
|
141
|
+
};
|
|
142
|
+
const storeRowHeightMeasurement = (id, height) => {
|
|
143
|
+
const entry = apiRef.current.getRowHeightEntry(id);
|
|
144
|
+
const didChange = entry.content !== height;
|
|
145
|
+
entry.needsFirstMeasurement = false;
|
|
146
|
+
entry.content = height;
|
|
147
|
+
isHeightMetaValid.current && (isHeightMetaValid.current = !didChange);
|
|
148
|
+
};
|
|
149
|
+
const rowHasAutoHeight = id => {
|
|
150
|
+
return heightCache.get(id)?.autoHeight ?? false;
|
|
151
|
+
};
|
|
152
|
+
const getLastMeasuredRowIndex = () => {
|
|
189
153
|
return lastMeasuredRowIndex.current;
|
|
190
|
-
}
|
|
191
|
-
const setLastMeasuredRowIndex =
|
|
154
|
+
};
|
|
155
|
+
const setLastMeasuredRowIndex = index => {
|
|
192
156
|
if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) {
|
|
193
157
|
lastMeasuredRowIndex.current = index;
|
|
194
158
|
}
|
|
195
|
-
}
|
|
196
|
-
const resetRowHeights =
|
|
197
|
-
|
|
159
|
+
};
|
|
160
|
+
const resetRowHeights = () => {
|
|
161
|
+
heightCache.clear();
|
|
198
162
|
hydrateRowsMeta();
|
|
199
|
-
}
|
|
163
|
+
};
|
|
164
|
+
const resizeObserver = useLazyRef(() => new ResizeObserver(entries => {
|
|
165
|
+
for (let i = 0; i < entries.length; i += 1) {
|
|
166
|
+
const entry = entries[i];
|
|
167
|
+
const height = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height;
|
|
168
|
+
const rowId = entry.target.__mui_id;
|
|
169
|
+
apiRef.current.unstable_storeRowHeightMeasurement(rowId, height);
|
|
170
|
+
}
|
|
171
|
+
if (!isHeightMetaValid.current) {
|
|
172
|
+
apiRef.current.requestPipeProcessorsApplication('rowHeight');
|
|
173
|
+
}
|
|
174
|
+
})).current;
|
|
175
|
+
const observeRowHeight = (element, rowId) => {
|
|
176
|
+
element.__mui_id = rowId;
|
|
177
|
+
resizeObserver.observe(element);
|
|
178
|
+
return () => resizeObserver.unobserve(element);
|
|
179
|
+
};
|
|
180
|
+
useGridRegisterPipeApplier(apiRef, 'rowHeight', hydrateRowsMeta);
|
|
200
181
|
|
|
201
182
|
// The effect is used to build the rows meta data - currentPageTotalHeight and positions.
|
|
202
183
|
// Because of variable row height this is needed for the virtualization
|
|
203
184
|
React.useEffect(() => {
|
|
204
185
|
hydrateRowsMeta();
|
|
205
|
-
}, [
|
|
206
|
-
useGridRegisterPipeApplier(apiRef, 'rowHeight', hydrateRowsMeta);
|
|
186
|
+
}, [filterModel, paginationState, sortModel, hydrateRowsMeta]);
|
|
207
187
|
const rowsMetaApi = {
|
|
208
|
-
unstable_setLastMeasuredRowIndex: setLastMeasuredRowIndex,
|
|
209
188
|
unstable_getRowHeight: getRowHeight,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight,
|
|
189
|
+
unstable_setLastMeasuredRowIndex: setLastMeasuredRowIndex,
|
|
190
|
+
unstable_storeRowHeightMeasurement: storeRowHeightMeasurement,
|
|
213
191
|
resetRowHeights
|
|
214
192
|
};
|
|
215
193
|
const rowsMetaPrivateApi = {
|
|
216
|
-
|
|
217
|
-
|
|
194
|
+
hydrateRowsMeta,
|
|
195
|
+
observeRowHeight,
|
|
196
|
+
rowHasAutoHeight,
|
|
197
|
+
getRowHeightEntry,
|
|
198
|
+
getLastMeasuredRowIndex
|
|
218
199
|
};
|
|
219
200
|
useGridApiMethod(apiRef, rowsMetaApi, 'public');
|
|
220
201
|
useGridApiMethod(apiRef, rowsMetaPrivateApi, 'private');
|
|
@@ -9,6 +9,7 @@ import { gridRowsMetaSelector } from "../rows/gridRowsMetaSelector.js";
|
|
|
9
9
|
import { useGridApiMethod } from "../../utils/useGridApiMethod.js";
|
|
10
10
|
import { gridExpandedSortedRowEntriesSelector } from "../filter/gridFilterSelector.js";
|
|
11
11
|
import { gridDimensionsSelector } from "../dimensions/index.js";
|
|
12
|
+
import { gridListColumnSelector } from "../listView/gridListViewSelectors.js";
|
|
12
13
|
|
|
13
14
|
// Logic copied from https://www.w3.org/TR/wai-aria-practices/examples/listbox/js/listbox.js
|
|
14
15
|
// Similar to https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
|
|
@@ -47,11 +48,13 @@ export const useGridScroll = (apiRef, props) => {
|
|
|
47
48
|
const logger = useGridLogger(apiRef, 'useGridScroll');
|
|
48
49
|
const colRef = apiRef.current.columnHeadersContainerRef;
|
|
49
50
|
const virtualScrollerRef = apiRef.current.virtualScrollerRef;
|
|
51
|
+
const virtualScrollbarHorizontalRef = apiRef.current.virtualScrollbarHorizontalRef;
|
|
52
|
+
const virtualScrollbarVerticalRef = apiRef.current.virtualScrollbarVerticalRef;
|
|
50
53
|
const visibleSortedRows = useGridSelector(apiRef, gridExpandedSortedRowEntriesSelector);
|
|
51
54
|
const scrollToIndexes = React.useCallback(params => {
|
|
52
55
|
const dimensions = gridDimensionsSelector(apiRef.current.state);
|
|
53
56
|
const totalRowCount = gridRowCountSelector(apiRef);
|
|
54
|
-
const visibleColumns = gridVisibleColumnDefinitionsSelector(apiRef);
|
|
57
|
+
const visibleColumns = props.unstable_listView ? [gridListColumnSelector(apiRef.current.state)] : gridVisibleColumnDefinitionsSelector(apiRef);
|
|
55
58
|
const scrollToHeader = params.rowIndex == null;
|
|
56
59
|
if (!scrollToHeader && totalRowCount === 0 || visibleColumns.length === 0) {
|
|
57
60
|
return false;
|
|
@@ -98,20 +101,22 @@ export const useGridScroll = (apiRef, props) => {
|
|
|
98
101
|
return true;
|
|
99
102
|
}
|
|
100
103
|
return false;
|
|
101
|
-
}, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows]);
|
|
104
|
+
}, [logger, apiRef, virtualScrollerRef, props.pagination, visibleSortedRows, props.unstable_listView]);
|
|
102
105
|
const scroll = React.useCallback(params => {
|
|
103
|
-
if (virtualScrollerRef.current && params.left !== undefined && colRef.current) {
|
|
106
|
+
if (virtualScrollerRef.current && virtualScrollbarHorizontalRef.current && params.left !== undefined && colRef.current) {
|
|
104
107
|
const direction = isRtl ? -1 : 1;
|
|
105
108
|
colRef.current.scrollLeft = params.left;
|
|
106
109
|
virtualScrollerRef.current.scrollLeft = direction * params.left;
|
|
110
|
+
virtualScrollbarHorizontalRef.current.scrollLeft = direction * params.left;
|
|
107
111
|
logger.debug(`Scrolling left: ${params.left}`);
|
|
108
112
|
}
|
|
109
|
-
if (virtualScrollerRef.current && params.top !== undefined) {
|
|
113
|
+
if (virtualScrollerRef.current && virtualScrollbarVerticalRef.current && params.top !== undefined) {
|
|
110
114
|
virtualScrollerRef.current.scrollTop = params.top;
|
|
115
|
+
virtualScrollbarVerticalRef.current.scrollTop = params.top;
|
|
111
116
|
logger.debug(`Scrolling top: ${params.top}`);
|
|
112
117
|
}
|
|
113
118
|
logger.debug(`Scrolling, updating container, and viewport`);
|
|
114
|
-
}, [virtualScrollerRef, isRtl, colRef, logger]);
|
|
119
|
+
}, [virtualScrollerRef, virtualScrollbarHorizontalRef, virtualScrollbarVerticalRef, isRtl, colRef, logger]);
|
|
115
120
|
const getScrollPosition = React.useCallback(() => {
|
|
116
121
|
if (!virtualScrollerRef?.current) {
|
|
117
122
|
return {
|
|
@@ -3,7 +3,7 @@ import { warnOnce } from '@mui/x-internals/warning';
|
|
|
3
3
|
export const sanitizeSortModel = (model, disableMultipleColumnsSorting) => {
|
|
4
4
|
if (disableMultipleColumnsSorting && model.length > 1) {
|
|
5
5
|
if (process.env.NODE_ENV !== 'production') {
|
|
6
|
-
warnOnce(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the
|
|
6
|
+
warnOnce(['MUI X: The `sortModel` can only contain a single item when the `disableMultipleColumnsSorting` prop is set to `true`.', 'If you are using the community version of the Data Grid, this prop is always `true`.'], 'error');
|
|
7
7
|
}
|
|
8
8
|
return [model[0]];
|
|
9
9
|
}
|