@mui/x-data-grid 5.16.0 → 5.17.2
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 -1
- package/components/GridRow.d.ts +2 -1
- package/components/GridRow.js +132 -83
- package/components/cell/GridBooleanCell.js +2 -1
- package/components/cell/GridCell.js +9 -1
- package/components/cell/GridEditBooleanCell.js +2 -1
- package/components/cell/GridEditDateCell.js +2 -1
- package/components/cell/GridEditInputCell.js +2 -1
- package/components/cell/GridEditSingleSelectCell.js +2 -1
- package/components/cell/GridSkeletonCell.d.ts +12 -0
- package/components/cell/GridSkeletonCell.js +60 -0
- package/components/cell/index.d.ts +1 -0
- package/components/cell/index.js +2 -1
- package/components/columnSelection/GridCellCheckboxRenderer.js +2 -1
- package/components/containers/GridRootStyles.js +2 -0
- package/components/panel/GridColumnsPanel.d.ts +6 -1
- package/components/panel/GridColumnsPanel.js +38 -6
- package/constants/defaultGridSlotsComponents.js +2 -1
- package/constants/gridClasses.d.ts +8 -0
- package/constants/gridClasses.js +1 -1
- package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -1
- package/hooks/features/editRows/useGridCellEditing.new.js +8 -2
- package/hooks/features/editRows/useGridRowEditing.new.js +8 -2
- package/hooks/features/filter/gridFilterUtils.d.ts +1 -1
- package/hooks/features/filter/gridFilterUtils.js +55 -54
- package/hooks/features/filter/useGridFilter.js +1 -1
- package/hooks/features/focus/useGridFocus.js +13 -3
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -0
- package/hooks/features/rows/useGridParamsApi.js +1 -1
- package/hooks/features/rows/useGridRows.js +65 -8
- package/hooks/features/rows/useGridRowsMeta.js +36 -16
- package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
- package/hooks/features/virtualization/useGridVirtualScroller.js +17 -5
- package/index.js +1 -1
- package/internals/index.d.ts +1 -1
- package/internals/index.js +1 -1
- package/legacy/components/GridRow.js +135 -83
- package/legacy/components/cell/GridBooleanCell.js +2 -1
- package/legacy/components/cell/GridCell.js +11 -1
- package/legacy/components/cell/GridEditBooleanCell.js +2 -1
- package/legacy/components/cell/GridEditDateCell.js +2 -1
- package/legacy/components/cell/GridEditInputCell.js +2 -1
- package/legacy/components/cell/GridEditSingleSelectCell.js +2 -1
- package/legacy/components/cell/GridSkeletonCell.js +57 -0
- package/legacy/components/cell/index.js +2 -1
- package/legacy/components/columnSelection/GridCellCheckboxRenderer.js +2 -1
- package/legacy/components/containers/GridRootStyles.js +3 -3
- package/legacy/components/panel/GridColumnsPanel.js +41 -6
- package/legacy/constants/defaultGridSlotsComponents.js +2 -1
- package/legacy/constants/gridClasses.js +1 -1
- package/legacy/hooks/features/editRows/useGridCellEditing.new.js +11 -5
- package/legacy/hooks/features/editRows/useGridRowEditing.new.js +8 -2
- package/legacy/hooks/features/filter/gridFilterUtils.js +61 -56
- package/legacy/hooks/features/filter/useGridFilter.js +1 -1
- package/legacy/hooks/features/focus/useGridFocus.js +13 -3
- package/legacy/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -0
- package/legacy/hooks/features/rows/useGridParamsApi.js +1 -1
- package/legacy/hooks/features/rows/useGridRows.js +73 -8
- package/legacy/hooks/features/rows/useGridRowsMeta.js +45 -18
- package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +31 -13
- package/legacy/index.js +1 -1
- package/legacy/internals/index.js +1 -1
- package/legacy/models/events/gridEvents.js +2 -0
- package/legacy/models/params/gridRenderedRowsIntervalChangeParams.js +1 -0
- package/legacy/models/params/index.js +2 -1
- package/legacy/utils/utils.js +25 -0
- package/models/api/gridParamsApi.d.ts +1 -1
- package/models/api/gridRowApi.d.ts +6 -0
- package/models/api/gridRowsMetaApi.d.ts +6 -1
- package/models/events/gridEventLookup.d.ts +7 -1
- package/models/events/gridEvents.d.ts +3 -1
- package/models/events/gridEvents.js +2 -0
- package/models/gridSlotsComponent.d.ts +5 -0
- package/models/params/gridCellParams.d.ts +7 -2
- package/models/params/gridRenderedRowsIntervalChangeParams.d.ts +10 -0
- package/models/params/gridRenderedRowsIntervalChangeParams.js +1 -0
- package/models/params/index.d.ts +1 -0
- package/models/params/index.js +2 -1
- package/modern/components/GridRow.js +129 -82
- package/modern/components/cell/GridBooleanCell.js +2 -1
- package/modern/components/cell/GridCell.js +9 -1
- package/modern/components/cell/GridEditBooleanCell.js +2 -1
- package/modern/components/cell/GridEditDateCell.js +2 -1
- package/modern/components/cell/GridEditInputCell.js +2 -1
- package/modern/components/cell/GridEditSingleSelectCell.js +2 -1
- package/modern/components/cell/GridSkeletonCell.js +60 -0
- package/modern/components/cell/index.js +2 -1
- package/modern/components/columnSelection/GridCellCheckboxRenderer.js +2 -1
- package/modern/components/containers/GridRootStyles.js +2 -0
- package/modern/components/panel/GridColumnsPanel.js +38 -6
- package/modern/constants/defaultGridSlotsComponents.js +2 -1
- package/modern/constants/gridClasses.js +1 -1
- package/modern/hooks/features/editRows/useGridCellEditing.new.js +8 -2
- package/modern/hooks/features/editRows/useGridRowEditing.new.js +8 -2
- package/modern/hooks/features/filter/gridFilterUtils.js +54 -53
- package/modern/hooks/features/filter/useGridFilter.js +1 -1
- package/modern/hooks/features/focus/useGridFocus.js +13 -3
- package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -0
- package/modern/hooks/features/rows/useGridParamsApi.js +1 -1
- package/modern/hooks/features/rows/useGridRows.js +65 -8
- package/modern/hooks/features/rows/useGridRowsMeta.js +36 -16
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +17 -5
- package/modern/index.js +1 -1
- package/modern/internals/index.js +1 -1
- package/modern/models/events/gridEvents.js +2 -0
- package/modern/models/params/gridRenderedRowsIntervalChangeParams.js +1 -0
- package/modern/models/params/index.js +2 -1
- package/modern/utils/utils.js +23 -0
- package/node/components/GridRow.js +131 -75
- package/node/components/cell/GridBooleanCell.js +2 -1
- package/node/components/cell/GridCell.js +9 -1
- package/node/components/cell/GridEditBooleanCell.js +2 -1
- package/node/components/cell/GridEditDateCell.js +2 -1
- package/node/components/cell/GridEditInputCell.js +2 -1
- package/node/components/cell/GridEditSingleSelectCell.js +2 -1
- package/node/components/cell/GridSkeletonCell.js +81 -0
- package/node/components/cell/index.js +13 -0
- package/node/components/columnSelection/GridCellCheckboxRenderer.js +2 -1
- package/node/components/containers/GridRootStyles.js +2 -0
- package/node/components/panel/GridColumnsPanel.js +36 -5
- package/node/constants/defaultGridSlotsComponents.js +1 -0
- package/node/constants/gridClasses.js +1 -1
- package/node/hooks/features/editRows/useGridCellEditing.new.js +9 -2
- package/node/hooks/features/editRows/useGridRowEditing.new.js +9 -2
- package/node/hooks/features/filter/gridFilterUtils.js +55 -55
- package/node/hooks/features/filter/useGridFilter.js +1 -1
- package/node/hooks/features/focus/useGridFocus.js +13 -3
- package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -0
- package/node/hooks/features/rows/useGridParamsApi.js +1 -1
- package/node/hooks/features/rows/useGridRows.js +60 -7
- package/node/hooks/features/rows/useGridRowsMeta.js +35 -15
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +17 -5
- package/node/index.js +1 -1
- package/node/internals/index.js +6 -0
- package/node/models/events/gridEvents.js +2 -0
- package/node/models/params/gridRenderedRowsIntervalChangeParams.js +5 -0
- package/node/models/params/index.js +13 -0
- package/node/utils/utils.js +27 -0
- package/package.json +1 -1
- package/utils/utils.d.ts +2 -0
- package/utils/utils.js +23 -0
|
@@ -69,72 +69,72 @@ export const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiR
|
|
|
69
69
|
export const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => filteringState => _extends({}, filteringState, {
|
|
70
70
|
filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
|
|
71
71
|
});
|
|
72
|
-
/**
|
|
73
|
-
* Generates a method to easily check if a row is matching the current filter model.
|
|
74
|
-
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
75
|
-
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
|
|
76
|
-
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
|
|
77
|
-
*/
|
|
78
72
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const getFilterCallbackFromItem = filterItem => {
|
|
85
|
-
if (!filterItem.columnField || !filterItem.operatorValue) {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
73
|
+
const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
74
|
+
if (!filterItem.columnField || !filterItem.operatorValue) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
88
77
|
|
|
89
|
-
|
|
78
|
+
const column = apiRef.current.getColumn(filterItem.columnField);
|
|
90
79
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
80
|
+
if (!column) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
94
83
|
|
|
95
|
-
|
|
84
|
+
let parsedValue;
|
|
96
85
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
86
|
+
if (column.valueParser) {
|
|
87
|
+
const parser = column.valueParser;
|
|
88
|
+
parsedValue = Array.isArray(filterItem.value) ? filterItem.value?.map(x => parser(x)) : parser(filterItem.value);
|
|
89
|
+
} else {
|
|
90
|
+
parsedValue = filterItem.value;
|
|
91
|
+
}
|
|
103
92
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
const newFilterItem = _extends({}, filterItem, {
|
|
94
|
+
value: parsedValue
|
|
95
|
+
});
|
|
107
96
|
|
|
108
|
-
|
|
97
|
+
const filterOperators = column.filterOperators;
|
|
109
98
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
99
|
+
if (!filterOperators?.length) {
|
|
100
|
+
throw new Error(`MUI: No filter operators found for column '${column.field}'.`);
|
|
101
|
+
}
|
|
113
102
|
|
|
114
|
-
|
|
103
|
+
const filterOperator = filterOperators.find(operator => operator.value === newFilterItem.operatorValue);
|
|
115
104
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
105
|
+
if (!filterOperator) {
|
|
106
|
+
throw new Error(`MUI: No filter operator found for column '${column.field}' and operator value '${newFilterItem.operatorValue}'.`);
|
|
107
|
+
}
|
|
119
108
|
|
|
120
|
-
|
|
109
|
+
const applyFilterOnRow = filterOperator.getApplyFilterFn(newFilterItem, column);
|
|
121
110
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
if (typeof applyFilterOnRow !== 'function') {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
125
114
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
115
|
+
const fn = rowId => {
|
|
116
|
+
const cellParams = apiRef.current.getCellParams(rowId, newFilterItem.columnField);
|
|
117
|
+
return applyFilterOnRow(cellParams);
|
|
118
|
+
};
|
|
130
119
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
};
|
|
120
|
+
return {
|
|
121
|
+
fn,
|
|
122
|
+
item: newFilterItem
|
|
135
123
|
};
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Generates a method to easily check if a row is matching the current filter model.
|
|
127
|
+
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
128
|
+
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
|
|
129
|
+
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
|
|
130
|
+
*/
|
|
136
131
|
|
|
137
|
-
|
|
132
|
+
|
|
133
|
+
export const buildAggregatedFilterItemsApplier = (filterModel, apiRef) => {
|
|
134
|
+
const {
|
|
135
|
+
items
|
|
136
|
+
} = filterModel;
|
|
137
|
+
const appliers = items.map(item => getFilterCallbackFromItem(item, apiRef)).filter(callback => !!callback);
|
|
138
138
|
|
|
139
139
|
if (appliers.length === 0) {
|
|
140
140
|
return null;
|
|
@@ -215,7 +215,8 @@ export const buildAggregatedFilterApplier = (filterModel, apiRef) => {
|
|
|
215
215
|
passingQuickFilterValues: isRowMatchingQuickFilter && isRowMatchingQuickFilter(rowId, shouldApplyFilter)
|
|
216
216
|
});
|
|
217
217
|
};
|
|
218
|
-
export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel) => {
|
|
218
|
+
export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel, apiRef) => {
|
|
219
|
+
const cleanedFilterItems = filterModel.items.filter(item => getFilterCallbackFromItem(item, apiRef) !== null);
|
|
219
220
|
const cleanedAllFilterItemResults = allFilterItemResults.filter(result => result != null);
|
|
220
221
|
const cleanedAllQuickFilterResults = allQuickFilterResults.filter(result => result != null); // Defaultize operators
|
|
221
222
|
|
|
@@ -229,13 +230,13 @@ export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, fil
|
|
|
229
230
|
};
|
|
230
231
|
|
|
231
232
|
if (linkOperator === GridLinkOperator.And) {
|
|
232
|
-
const passesAllFilters =
|
|
233
|
+
const passesAllFilters = cleanedFilterItems.every(filterItemPredicate);
|
|
233
234
|
|
|
234
235
|
if (!passesAllFilters) {
|
|
235
236
|
return false;
|
|
236
237
|
}
|
|
237
238
|
} else {
|
|
238
|
-
const passesSomeFilters =
|
|
239
|
+
const passesSomeFilters = cleanedFilterItems.some(filterItemPredicate);
|
|
239
240
|
|
|
240
241
|
if (!passesSomeFilters) {
|
|
241
242
|
return false;
|
|
@@ -259,7 +259,7 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
259
259
|
passingFilterItems,
|
|
260
260
|
passingQuickFilterValues
|
|
261
261
|
} = params.isRowMatchingFilters(rowId);
|
|
262
|
-
isRowPassing = passFilterLogic([passingFilterItems], [passingQuickFilterValues], params.filterModel);
|
|
262
|
+
isRowPassing = passFilterLogic([passingFilterItems], [passingQuickFilterValues], params.filterModel, apiRef);
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
filteredRowsLookup[rowId] = isRowPassing;
|
|
@@ -131,8 +131,18 @@ export const useGridFocus = (apiRef, props) => {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
rowIndexToFocus = clamp(rowIndexToFocus, 0, currentPage.rows.length - 1);
|
|
134
|
-
columnIndexToFocus = clamp(columnIndexToFocus, 0, visibleColumns.length - 1);
|
|
135
134
|
const rowToFocus = currentPage.rows[rowIndexToFocus];
|
|
135
|
+
const colSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowToFocus.id, columnIndexToFocus);
|
|
136
|
+
|
|
137
|
+
if (colSpanInfo && colSpanInfo.spannedByColSpan) {
|
|
138
|
+
if (direction === 'left' || direction === 'below') {
|
|
139
|
+
columnIndexToFocus = colSpanInfo.leftVisibleCellIndex;
|
|
140
|
+
} else if (direction === 'right') {
|
|
141
|
+
columnIndexToFocus = colSpanInfo.rightVisibleCellIndex;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
columnIndexToFocus = clamp(columnIndexToFocus, 0, visibleColumns.length - 1);
|
|
136
146
|
const columnToFocus = visibleColumns[columnIndexToFocus];
|
|
137
147
|
apiRef.current.setCellFocus(rowToFocus.id, columnToFocus.field);
|
|
138
148
|
}, [apiRef, props.pagination, props.paginationMode]);
|
|
@@ -168,7 +178,7 @@ export const useGridFocus = (apiRef, props) => {
|
|
|
168
178
|
}
|
|
169
179
|
}));
|
|
170
180
|
}, [logger, apiRef]);
|
|
171
|
-
const
|
|
181
|
+
const handleCellMouseDown = React.useCallback(params => {
|
|
172
182
|
lastClickedCell.current = params;
|
|
173
183
|
}, []);
|
|
174
184
|
const handleDocumentClick = React.useCallback(event => {
|
|
@@ -251,7 +261,7 @@ export const useGridFocus = (apiRef, props) => {
|
|
|
251
261
|
}, [apiRef, handleDocumentClick]);
|
|
252
262
|
useGridApiEventHandler(apiRef, 'columnHeaderBlur', handleBlur);
|
|
253
263
|
useGridApiEventHandler(apiRef, 'cellDoubleClick', handleCellDoubleClick);
|
|
254
|
-
useGridApiEventHandler(apiRef, '
|
|
264
|
+
useGridApiEventHandler(apiRef, 'cellMouseDown', handleCellMouseDown);
|
|
255
265
|
useGridApiEventHandler(apiRef, 'cellKeyDown', handleCellKeyDown);
|
|
256
266
|
useGridApiEventHandler(apiRef, 'cellModeChange', handleCellModeChange);
|
|
257
267
|
useGridApiEventHandler(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus);
|
|
@@ -34,6 +34,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
34
34
|
* @param {number} colIndex Index of the column to focus
|
|
35
35
|
* @param {number} rowIndex index of the row to focus
|
|
36
36
|
* @param {string} closestColumnToUse Which closest column cell to use when the cell is spanned by `colSpan`.
|
|
37
|
+
* TODO replace with apiRef.current.unstable_moveFocusToRelativeCell()
|
|
37
38
|
*/
|
|
38
39
|
|
|
39
40
|
const goToCell = React.useCallback((colIndex, rowId, closestColumnToUse = 'left') => {
|
|
@@ -90,6 +91,7 @@ export const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
90
91
|
case 'ArrowDown':
|
|
91
92
|
case 'Enter':
|
|
92
93
|
{
|
|
94
|
+
// TODO v6: Remove Enter case because `cellNavigationKeyDown` is not fired by the new editing API
|
|
93
95
|
// "Enter" is only triggered by the row / cell editing feature
|
|
94
96
|
if (rowIndexBefore < lastRowIndexInPage) {
|
|
95
97
|
goToCell(colIndexBefore, getRowIdFromIndex(rowIndexBefore + 1));
|
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
4
4
|
import { useGridLogger } from '../../utils/useGridLogger';
|
|
5
|
-
import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowIdsSelector, gridRowGroupingNameSelector } from './gridRowsSelector';
|
|
5
|
+
import { gridRowCountSelector, gridRowsLookupSelector, gridRowTreeSelector, gridRowIdsSelector, gridRowGroupingNameSelector, gridRowsIdToIdLookupSelector } from './gridRowsSelector';
|
|
6
6
|
import { GridSignature, useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
|
|
7
7
|
import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
|
|
8
8
|
import { gridSortedRowIdsSelector } from '../sorting/gridSortingSelector';
|
|
@@ -100,14 +100,14 @@ export const useGridRows = (apiRef, props) => {
|
|
|
100
100
|
} // we remove duplicate updates. A server can batch updates, and send several updates for the same row in one fn call.
|
|
101
101
|
|
|
102
102
|
|
|
103
|
-
const
|
|
103
|
+
const uniqueUpdates = new Map();
|
|
104
104
|
updates.forEach(update => {
|
|
105
105
|
const id = getRowIdFromRowModel(update, props.getRowId, 'A row was provided without id when calling updateRows():');
|
|
106
106
|
|
|
107
|
-
if (
|
|
108
|
-
|
|
107
|
+
if (uniqueUpdates.has(id)) {
|
|
108
|
+
uniqueUpdates.set(id, _extends({}, uniqueUpdates.get(id), update));
|
|
109
109
|
} else {
|
|
110
|
-
|
|
110
|
+
uniqueUpdates.set(id, update);
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
113
|
const deletedRowIds = [];
|
|
@@ -119,7 +119,7 @@ export const useGridRows = (apiRef, props) => {
|
|
|
119
119
|
idToIdLookup: _extends({}, prevCache.idToIdLookup),
|
|
120
120
|
ids: [...prevCache.ids]
|
|
121
121
|
};
|
|
122
|
-
|
|
122
|
+
uniqueUpdates.forEach((partialRow, id) => {
|
|
123
123
|
// eslint-disable-next-line no-underscore-dangle
|
|
124
124
|
if (partialRow._action === 'delete') {
|
|
125
125
|
delete newCache.idRowsLookup[id];
|
|
@@ -233,8 +233,64 @@ export const useGridRows = (apiRef, props) => {
|
|
|
233
233
|
ids: updatedRows
|
|
234
234
|
})
|
|
235
235
|
}));
|
|
236
|
-
apiRef.current.
|
|
236
|
+
apiRef.current.publishEvent('rowsSet');
|
|
237
237
|
}, [apiRef, logger]);
|
|
238
|
+
const replaceRows = React.useCallback((firstRowToRender, newRows) => {
|
|
239
|
+
if (props.signature === GridSignature.DataGrid && newRows.length > 1) {
|
|
240
|
+
throw new Error(["MUI: You can't replace rows using `apiRef.current.unstable_replaceRows` on the DataGrid.", 'You need to upgrade to DataGridPro or DataGridPremium component to unlock this feature.'].join('\n'));
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (newRows.length === 0) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const allRows = gridRowIdsSelector(apiRef);
|
|
248
|
+
const updatedRows = [...allRows];
|
|
249
|
+
const idRowsLookup = gridRowsLookupSelector(apiRef);
|
|
250
|
+
const idToIdLookup = gridRowsIdToIdLookupSelector(apiRef);
|
|
251
|
+
const tree = gridRowTreeSelector(apiRef);
|
|
252
|
+
|
|
253
|
+
const updatedIdRowsLookup = _extends({}, idRowsLookup);
|
|
254
|
+
|
|
255
|
+
const updatedIdToIdLookup = _extends({}, idToIdLookup);
|
|
256
|
+
|
|
257
|
+
const updatedTree = _extends({}, tree);
|
|
258
|
+
|
|
259
|
+
const newRowEntries = newRows.map(newRowModel => {
|
|
260
|
+
const rowId = getRowIdFromRowModel(newRowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
|
|
261
|
+
return {
|
|
262
|
+
id: rowId,
|
|
263
|
+
model: newRowModel
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
newRowEntries.forEach((row, index) => {
|
|
267
|
+
const [replacedRowId] = updatedRows.splice(firstRowToRender + index, 1, row.id);
|
|
268
|
+
delete updatedIdRowsLookup[replacedRowId];
|
|
269
|
+
delete updatedIdToIdLookup[replacedRowId];
|
|
270
|
+
delete updatedTree[replacedRowId];
|
|
271
|
+
});
|
|
272
|
+
newRowEntries.forEach(row => {
|
|
273
|
+
const rowTreeNodeConfig = {
|
|
274
|
+
id: row.id,
|
|
275
|
+
parent: null,
|
|
276
|
+
depth: 0,
|
|
277
|
+
groupingKey: null,
|
|
278
|
+
groupingField: null
|
|
279
|
+
};
|
|
280
|
+
updatedIdRowsLookup[row.id] = row.model;
|
|
281
|
+
updatedIdToIdLookup[row.id] = row.id;
|
|
282
|
+
updatedTree[row.id] = rowTreeNodeConfig;
|
|
283
|
+
});
|
|
284
|
+
apiRef.current.setState(state => _extends({}, state, {
|
|
285
|
+
rows: _extends({}, state.rows, {
|
|
286
|
+
idRowsLookup: updatedIdRowsLookup,
|
|
287
|
+
idToIdLookup: updatedIdToIdLookup,
|
|
288
|
+
tree: updatedTree,
|
|
289
|
+
ids: updatedRows
|
|
290
|
+
})
|
|
291
|
+
}));
|
|
292
|
+
apiRef.current.publishEvent('rowsSet');
|
|
293
|
+
}, [apiRef, props.signature, props.getRowId]);
|
|
238
294
|
const rowApi = {
|
|
239
295
|
getRow,
|
|
240
296
|
getRowModels,
|
|
@@ -246,7 +302,8 @@ export const useGridRows = (apiRef, props) => {
|
|
|
246
302
|
setRowChildrenExpansion,
|
|
247
303
|
getRowNode,
|
|
248
304
|
getRowIndexRelativeToVisibleRows,
|
|
249
|
-
getRowGroupChildren
|
|
305
|
+
getRowGroupChildren,
|
|
306
|
+
unstable_replaceRows: replaceRows
|
|
250
307
|
};
|
|
251
308
|
/**
|
|
252
309
|
* EVENTS
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { debounce } from '@mui/material/utils';
|
|
3
|
+
import { debounce, capitalize } from '@mui/material/utils';
|
|
4
4
|
import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
|
|
5
5
|
import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
6
6
|
import { useGridSelector } from '../../utils/useGridSelector';
|
|
@@ -45,7 +45,7 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
45
45
|
if (!rowsHeightLookup.current[row.id]) {
|
|
46
46
|
rowsHeightLookup.current[row.id] = {
|
|
47
47
|
sizes: {
|
|
48
|
-
|
|
48
|
+
baseCenter: rowHeightFromDensity
|
|
49
49
|
},
|
|
50
50
|
isResized: false,
|
|
51
51
|
autoHeight: false,
|
|
@@ -60,7 +60,7 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
60
60
|
sizes
|
|
61
61
|
} = rowsHeightLookup.current[row.id];
|
|
62
62
|
let baseRowHeight = rowHeightFromDensity;
|
|
63
|
-
const existingBaseRowHeight = sizes.
|
|
63
|
+
const existingBaseRowHeight = sizes.baseCenter;
|
|
64
64
|
|
|
65
65
|
if (isResized) {
|
|
66
66
|
// Do not recalculate resized row height and use the value from the lookup
|
|
@@ -91,12 +91,19 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
91
91
|
}
|
|
92
92
|
} else {
|
|
93
93
|
rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
|
|
94
|
-
}
|
|
94
|
+
}
|
|
95
95
|
|
|
96
|
+
const existingBaseSizes = Object.entries(sizes).reduce((acc, [key, size]) => {
|
|
97
|
+
if (/^base[A-Z]/.test(key)) {
|
|
98
|
+
acc[key] = size;
|
|
99
|
+
}
|
|
96
100
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
101
|
+
return acc;
|
|
102
|
+
}, {}); // We use an object to make simple to check if a height is already added or not
|
|
103
|
+
|
|
104
|
+
const initialHeights = _extends({}, existingBaseSizes, {
|
|
105
|
+
baseCenter: baseRowHeight
|
|
106
|
+
});
|
|
100
107
|
|
|
101
108
|
if (getRowSpacing) {
|
|
102
109
|
const indexRelativeToCurrentPage = apiRef.current.getRowIndexRelativeToVisibleRows(row.id);
|
|
@@ -117,9 +124,17 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
117
124
|
const positions = [];
|
|
118
125
|
const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => {
|
|
119
126
|
positions.push(acc);
|
|
127
|
+
let maximumBaseSize = 0;
|
|
128
|
+
let otherSizes = 0;
|
|
120
129
|
const processedSizes = calculateRowProcessedSizes(row);
|
|
121
|
-
|
|
122
|
-
|
|
130
|
+
Object.entries(processedSizes).forEach(([size, value]) => {
|
|
131
|
+
if (/^base[A-Z]/.test(size)) {
|
|
132
|
+
maximumBaseSize = value > maximumBaseSize ? value : maximumBaseSize;
|
|
133
|
+
} else {
|
|
134
|
+
otherSizes += value;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return acc + maximumBaseSize + otherSizes;
|
|
123
138
|
}, 0);
|
|
124
139
|
pinnedRows?.top?.forEach(row => {
|
|
125
140
|
calculateRowProcessedSizes(row);
|
|
@@ -145,27 +160,27 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
145
160
|
}, [apiRef, currentPage.rows, rowHeightFromDensity, getRowHeightProp, getRowSpacing, getEstimatedRowHeight, pinnedRows]);
|
|
146
161
|
const getRowHeight = React.useCallback(rowId => {
|
|
147
162
|
const height = rowsHeightLookup.current[rowId];
|
|
148
|
-
return height ? height.sizes.
|
|
163
|
+
return height ? height.sizes.baseCenter : rowHeightFromDensity;
|
|
149
164
|
}, [rowHeightFromDensity]);
|
|
150
165
|
|
|
151
166
|
const getRowInternalSizes = rowId => rowsHeightLookup.current[rowId]?.sizes;
|
|
152
167
|
|
|
153
168
|
const setRowHeight = React.useCallback((id, height) => {
|
|
154
|
-
rowsHeightLookup.current[id].sizes.
|
|
169
|
+
rowsHeightLookup.current[id].sizes.baseCenter = height;
|
|
155
170
|
rowsHeightLookup.current[id].isResized = true;
|
|
156
171
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
157
172
|
hydrateRowsMeta();
|
|
158
173
|
}, [hydrateRowsMeta]);
|
|
159
174
|
const debouncedHydrateRowsMeta = React.useMemo(() => debounce(hydrateRowsMeta), [hydrateRowsMeta]);
|
|
160
|
-
const storeMeasuredRowHeight = React.useCallback((id, height) => {
|
|
175
|
+
const storeMeasuredRowHeight = React.useCallback((id, height, position) => {
|
|
161
176
|
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
|
|
162
177
|
return;
|
|
163
178
|
} // Only trigger hydration if the value is different, otherwise we trigger a loop
|
|
164
179
|
|
|
165
180
|
|
|
166
|
-
const needsHydration = rowsHeightLookup.current[id].sizes
|
|
181
|
+
const needsHydration = rowsHeightLookup.current[id].sizes[`base${capitalize(position)}`] !== height;
|
|
167
182
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
168
|
-
rowsHeightLookup.current[id].sizes
|
|
183
|
+
rowsHeightLookup.current[id].sizes[`base${capitalize(position)}`] = height;
|
|
169
184
|
|
|
170
185
|
if (needsHydration) {
|
|
171
186
|
debouncedHydrateRowsMeta();
|
|
@@ -181,7 +196,11 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
181
196
|
if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) {
|
|
182
197
|
lastMeasuredRowIndex.current = index;
|
|
183
198
|
}
|
|
184
|
-
}, []);
|
|
199
|
+
}, []);
|
|
200
|
+
const resetRowHeights = React.useCallback(() => {
|
|
201
|
+
rowsHeightLookup.current = {};
|
|
202
|
+
hydrateRowsMeta();
|
|
203
|
+
}, [hydrateRowsMeta]); // The effect is used to build the rows meta data - currentPageTotalHeight and positions.
|
|
185
204
|
// Because of variable row height this is needed for the virtualization
|
|
186
205
|
|
|
187
206
|
React.useEffect(() => {
|
|
@@ -195,7 +214,8 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
195
214
|
unstable_getRowHeight: getRowHeight,
|
|
196
215
|
unstable_getRowInternalSizes: getRowInternalSizes,
|
|
197
216
|
unstable_setRowHeight: setRowHeight,
|
|
198
|
-
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight
|
|
217
|
+
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight,
|
|
218
|
+
resetRowHeights
|
|
199
219
|
};
|
|
200
220
|
useGridApiMethod(apiRef, rowsMetaApi, 'GridRowsMetaApi');
|
|
201
221
|
};
|
|
@@ -211,8 +211,19 @@ export const useGridVirtualScroller = props => {
|
|
|
211
211
|
}, [renderContext, updateRenderZonePosition]);
|
|
212
212
|
const updateRenderContext = React.useCallback(nextRenderContext => {
|
|
213
213
|
setRenderContext(nextRenderContext);
|
|
214
|
+
const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
|
|
215
|
+
firstIndex: nextRenderContext.firstRowIndex,
|
|
216
|
+
lastIndex: nextRenderContext.lastRowIndex,
|
|
217
|
+
minFirstIndex: 0,
|
|
218
|
+
maxLastIndex: currentPage.rows.length,
|
|
219
|
+
buffer: rootProps.rowBuffer
|
|
220
|
+
});
|
|
221
|
+
apiRef.current.publishEvent('renderedRowsIntervalChange', {
|
|
222
|
+
firstRowToRender,
|
|
223
|
+
lastRowToRender
|
|
224
|
+
});
|
|
214
225
|
prevRenderContext.current = nextRenderContext;
|
|
215
|
-
}, [setRenderContext, prevRenderContext]);
|
|
226
|
+
}, [apiRef, setRenderContext, prevRenderContext, currentPage.rows.length, rootProps.rowBuffer]);
|
|
216
227
|
React.useEffect(() => {
|
|
217
228
|
if (containerWidth == null) {
|
|
218
229
|
return;
|
|
@@ -283,8 +294,8 @@ export const useGridVirtualScroller = props => {
|
|
|
283
294
|
minFirstColumn = renderZoneMinColumnIndex,
|
|
284
295
|
maxLastColumn = renderZoneMaxColumnIndex,
|
|
285
296
|
availableSpace = containerWidth,
|
|
286
|
-
|
|
287
|
-
|
|
297
|
+
rowIndexOffset = 0,
|
|
298
|
+
position = 'center'
|
|
288
299
|
} = params;
|
|
289
300
|
|
|
290
301
|
if (!nextRenderContext || availableSpace == null) {
|
|
@@ -352,7 +363,7 @@ export const useGridVirtualScroller = props => {
|
|
|
352
363
|
model
|
|
353
364
|
} = renderedRows[i];
|
|
354
365
|
const lastVisibleRowIndex = firstRowToRender + i === currentPage.rows.length - 1;
|
|
355
|
-
const baseRowHeight = !apiRef.current.unstable_rowHasAutoHeight(id)
|
|
366
|
+
const baseRowHeight = !apiRef.current.unstable_rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
|
|
356
367
|
let isSelected;
|
|
357
368
|
|
|
358
369
|
if (selectedRowsLookup[id] == null) {
|
|
@@ -378,7 +389,8 @@ export const useGridVirtualScroller = props => {
|
|
|
378
389
|
selected: isSelected,
|
|
379
390
|
index: rowIndexOffset + (currentPage?.range?.firstRowIndex || 0) + firstRowToRender + i,
|
|
380
391
|
containerWidth: availableSpace,
|
|
381
|
-
isLastVisible: lastVisibleRowIndex
|
|
392
|
+
isLastVisible: lastVisibleRowIndex,
|
|
393
|
+
position: position
|
|
382
394
|
}, typeof getRowProps === 'function' ? getRowProps(id, model) : {}, rootProps.componentsProps?.row), id));
|
|
383
395
|
}
|
|
384
396
|
|
package/modern/index.js
CHANGED
|
@@ -38,7 +38,7 @@ export { useGridScroll } from '../hooks/features/scroll/useGridScroll';
|
|
|
38
38
|
export { useGridEvents } from '../hooks/features/events/useGridEvents';
|
|
39
39
|
export { useGridDimensions } from '../hooks/features/dimensions/useGridDimensions';
|
|
40
40
|
export { useGridStatePersistence } from '../hooks/features/statePersistence/useGridStatePersistence';
|
|
41
|
-
export { useGridVirtualScroller } from '../hooks/features/virtualization/useGridVirtualScroller';
|
|
41
|
+
export { useGridVirtualScroller, getRenderableIndexes } from '../hooks/features/virtualization/useGridVirtualScroller';
|
|
42
42
|
export { useGridVisibleRows } from '../hooks/utils/useGridVisibleRows';
|
|
43
43
|
export { useGridInitializeState } from '../hooks/utils/useGridInitializeState';
|
|
44
44
|
export { getColumnsToExport, defaultGetRowsToExport } from '../hooks/features/export/utils';
|
|
@@ -85,6 +85,8 @@ var GridEvents;
|
|
|
85
85
|
GridEvents["preferencePanelOpen"] = "preferencePanelOpen";
|
|
86
86
|
GridEvents["menuOpen"] = "menuOpen";
|
|
87
87
|
GridEvents["menuClose"] = "menuClose";
|
|
88
|
+
GridEvents["renderedRowsIntervalChange"] = "renderedRowsIntervalChange";
|
|
89
|
+
GridEvents["fetchRows"] = "fetchRows";
|
|
88
90
|
})(GridEvents || (GridEvents = {}));
|
|
89
91
|
|
|
90
92
|
export { GridEvents };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,4 +11,5 @@ export * from './gridValueOptionsParams';
|
|
|
11
11
|
export * from './gridCellParams';
|
|
12
12
|
export * from './gridSortModelParams';
|
|
13
13
|
export * from './gridPreferencePanelParams';
|
|
14
|
-
export * from './gridMenuParams';
|
|
14
|
+
export * from './gridMenuParams';
|
|
15
|
+
export * from './gridRenderedRowsIntervalChangeParams';
|
package/modern/utils/utils.js
CHANGED
|
@@ -177,4 +177,27 @@ export function isDeepEqual(a, b) {
|
|
|
177
177
|
|
|
178
178
|
|
|
179
179
|
return a !== a && b !== b;
|
|
180
|
+
} // Pseudo random number. See https://stackoverflow.com/a/47593316
|
|
181
|
+
|
|
182
|
+
function mulberry32(a) {
|
|
183
|
+
return () => {
|
|
184
|
+
/* eslint-disable */
|
|
185
|
+
let t = a += 0x6d2b79f5;
|
|
186
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
187
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
188
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
189
|
+
/* eslint-enable */
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function randomNumberBetween(seed, min, max) {
|
|
194
|
+
const random = mulberry32(seed);
|
|
195
|
+
return () => min + (max - min) * random();
|
|
196
|
+
}
|
|
197
|
+
export function deepClone(obj) {
|
|
198
|
+
if (typeof structuredClone === 'function') {
|
|
199
|
+
return structuredClone(obj);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return JSON.parse(JSON.stringify(obj));
|
|
180
203
|
}
|