@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
|
@@ -31,6 +31,8 @@ var _warning = require("../../../utils/warning");
|
|
|
31
31
|
|
|
32
32
|
var _gridRowsSelector = require("../rows/gridRowsSelector");
|
|
33
33
|
|
|
34
|
+
var _utils = require("../../../utils/utils");
|
|
35
|
+
|
|
34
36
|
var _gridRowParams = require("../../../models/params/gridRowParams");
|
|
35
37
|
|
|
36
38
|
const _excluded = ["id"],
|
|
@@ -421,7 +423,11 @@ const useGridRowEditing = (apiRef, props) => {
|
|
|
421
423
|
const hasSomeFieldWithError = Object.values(editingState[id]).some(fieldProps => fieldProps.error);
|
|
422
424
|
|
|
423
425
|
if (hasSomeFieldWithError) {
|
|
424
|
-
prevRowModesModel.current[id].mode = _gridEditRowModel.GridRowModes.Edit;
|
|
426
|
+
prevRowModesModel.current[id].mode = _gridEditRowModel.GridRowModes.Edit; // Revert the mode in the rowModesModel prop back to "edit"
|
|
427
|
+
|
|
428
|
+
updateRowInRowModesModel(id, {
|
|
429
|
+
mode: _gridEditRowModel.GridRowModes.Edit
|
|
430
|
+
});
|
|
425
431
|
return;
|
|
426
432
|
}
|
|
427
433
|
|
|
@@ -597,7 +603,8 @@ const useGridRowEditing = (apiRef, props) => {
|
|
|
597
603
|
const idToIdLookup = (0, _gridRowsSelector.gridRowsIdToIdLookupSelector)(apiRef); // Update the ref here because updateStateToStopRowEditMode may change it later
|
|
598
604
|
|
|
599
605
|
const copyOfPrevRowModesModel = prevRowModesModel.current;
|
|
600
|
-
prevRowModesModel.current = rowModesModel;
|
|
606
|
+
prevRowModesModel.current = (0, _utils.deepClone)(rowModesModel); // Do a deep-clone because the attributes might be changed later
|
|
607
|
+
|
|
601
608
|
Object.entries(rowModesModel).forEach(([id, params]) => {
|
|
602
609
|
var _copyOfPrevRowModesMo, _idToIdLookup$id;
|
|
603
610
|
|
|
@@ -88,76 +88,75 @@ exports.sanitizeFilterModel = sanitizeFilterModel;
|
|
|
88
88
|
const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => filteringState => (0, _extends2.default)({}, filteringState, {
|
|
89
89
|
filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
|
|
90
90
|
});
|
|
91
|
-
/**
|
|
92
|
-
* Generates a method to easily check if a row is matching the current filter model.
|
|
93
|
-
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
94
|
-
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
|
|
95
|
-
* @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.
|
|
96
|
-
*/
|
|
97
|
-
|
|
98
91
|
|
|
99
92
|
exports.mergeStateWithFilterModel = mergeStateWithFilterModel;
|
|
100
93
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const getFilterCallbackFromItem = filterItem => {
|
|
107
|
-
if (!filterItem.columnField || !filterItem.operatorValue) {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
94
|
+
const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
95
|
+
if (!filterItem.columnField || !filterItem.operatorValue) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
110
98
|
|
|
111
|
-
|
|
99
|
+
const column = apiRef.current.getColumn(filterItem.columnField);
|
|
112
100
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
101
|
+
if (!column) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
116
104
|
|
|
117
|
-
|
|
105
|
+
let parsedValue;
|
|
118
106
|
|
|
119
|
-
|
|
120
|
-
|
|
107
|
+
if (column.valueParser) {
|
|
108
|
+
var _filterItem$value;
|
|
121
109
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
110
|
+
const parser = column.valueParser;
|
|
111
|
+
parsedValue = Array.isArray(filterItem.value) ? (_filterItem$value = filterItem.value) == null ? void 0 : _filterItem$value.map(x => parser(x)) : parser(filterItem.value);
|
|
112
|
+
} else {
|
|
113
|
+
parsedValue = filterItem.value;
|
|
114
|
+
}
|
|
127
115
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
116
|
+
const newFilterItem = (0, _extends2.default)({}, filterItem, {
|
|
117
|
+
value: parsedValue
|
|
118
|
+
});
|
|
119
|
+
const filterOperators = column.filterOperators;
|
|
132
120
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
if (!(filterOperators != null && filterOperators.length)) {
|
|
122
|
+
throw new Error(`MUI: No filter operators found for column '${column.field}'.`);
|
|
123
|
+
}
|
|
136
124
|
|
|
137
|
-
|
|
125
|
+
const filterOperator = filterOperators.find(operator => operator.value === newFilterItem.operatorValue);
|
|
138
126
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
127
|
+
if (!filterOperator) {
|
|
128
|
+
throw new Error(`MUI: No filter operator found for column '${column.field}' and operator value '${newFilterItem.operatorValue}'.`);
|
|
129
|
+
}
|
|
142
130
|
|
|
143
|
-
|
|
131
|
+
const applyFilterOnRow = filterOperator.getApplyFilterFn(newFilterItem, column);
|
|
144
132
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
133
|
+
if (typeof applyFilterOnRow !== 'function') {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
148
136
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
137
|
+
const fn = rowId => {
|
|
138
|
+
const cellParams = apiRef.current.getCellParams(rowId, newFilterItem.columnField);
|
|
139
|
+
return applyFilterOnRow(cellParams);
|
|
140
|
+
};
|
|
153
141
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
};
|
|
142
|
+
return {
|
|
143
|
+
fn,
|
|
144
|
+
item: newFilterItem
|
|
158
145
|
};
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Generates a method to easily check if a row is matching the current filter model.
|
|
149
|
+
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
150
|
+
* @param {React.MutableRefObject<GridApiCommunity>} apiRef The API of the grid.
|
|
151
|
+
* @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.
|
|
152
|
+
*/
|
|
159
153
|
|
|
160
|
-
|
|
154
|
+
|
|
155
|
+
const buildAggregatedFilterItemsApplier = (filterModel, apiRef) => {
|
|
156
|
+
const {
|
|
157
|
+
items
|
|
158
|
+
} = filterModel;
|
|
159
|
+
const appliers = items.map(item => getFilterCallbackFromItem(item, apiRef)).filter(callback => !!callback);
|
|
161
160
|
|
|
162
161
|
if (appliers.length === 0) {
|
|
163
162
|
return null;
|
|
@@ -249,9 +248,10 @@ const buildAggregatedFilterApplier = (filterModel, apiRef) => {
|
|
|
249
248
|
|
|
250
249
|
exports.buildAggregatedFilterApplier = buildAggregatedFilterApplier;
|
|
251
250
|
|
|
252
|
-
const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel) => {
|
|
251
|
+
const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel, apiRef) => {
|
|
253
252
|
var _filterModel$quickFil, _filterModel$linkOper;
|
|
254
253
|
|
|
254
|
+
const cleanedFilterItems = filterModel.items.filter(item => getFilterCallbackFromItem(item, apiRef) !== null);
|
|
255
255
|
const cleanedAllFilterItemResults = allFilterItemResults.filter(result => result != null);
|
|
256
256
|
const cleanedAllQuickFilterResults = allQuickFilterResults.filter(result => result != null); // Defaultize operators
|
|
257
257
|
|
|
@@ -265,13 +265,13 @@ const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterMode
|
|
|
265
265
|
};
|
|
266
266
|
|
|
267
267
|
if (linkOperator === _models.GridLinkOperator.And) {
|
|
268
|
-
const passesAllFilters =
|
|
268
|
+
const passesAllFilters = cleanedFilterItems.every(filterItemPredicate);
|
|
269
269
|
|
|
270
270
|
if (!passesAllFilters) {
|
|
271
271
|
return false;
|
|
272
272
|
}
|
|
273
273
|
} else {
|
|
274
|
-
const passesSomeFilters =
|
|
274
|
+
const passesSomeFilters = cleanedFilterItems.some(filterItemPredicate);
|
|
275
275
|
|
|
276
276
|
if (!passesSomeFilters) {
|
|
277
277
|
return false;
|
|
@@ -304,7 +304,7 @@ const useGridFilter = (apiRef, props) => {
|
|
|
304
304
|
passingFilterItems,
|
|
305
305
|
passingQuickFilterValues
|
|
306
306
|
} = params.isRowMatchingFilters(rowId);
|
|
307
|
-
isRowPassing = (0, _gridFilterUtils.passFilterLogic)([passingFilterItems], [passingQuickFilterValues], params.filterModel);
|
|
307
|
+
isRowPassing = (0, _gridFilterUtils.passFilterLogic)([passingFilterItems], [passingQuickFilterValues], params.filterModel, apiRef);
|
|
308
308
|
}
|
|
309
309
|
|
|
310
310
|
filteredRowsLookup[rowId] = isRowPassing;
|
|
@@ -158,8 +158,18 @@ const useGridFocus = (apiRef, props) => {
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
rowIndexToFocus = (0, _utils2.clamp)(rowIndexToFocus, 0, currentPage.rows.length - 1);
|
|
161
|
-
columnIndexToFocus = (0, _utils2.clamp)(columnIndexToFocus, 0, visibleColumns.length - 1);
|
|
162
161
|
const rowToFocus = currentPage.rows[rowIndexToFocus];
|
|
162
|
+
const colSpanInfo = apiRef.current.unstable_getCellColSpanInfo(rowToFocus.id, columnIndexToFocus);
|
|
163
|
+
|
|
164
|
+
if (colSpanInfo && colSpanInfo.spannedByColSpan) {
|
|
165
|
+
if (direction === 'left' || direction === 'below') {
|
|
166
|
+
columnIndexToFocus = colSpanInfo.leftVisibleCellIndex;
|
|
167
|
+
} else if (direction === 'right') {
|
|
168
|
+
columnIndexToFocus = colSpanInfo.rightVisibleCellIndex;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
columnIndexToFocus = (0, _utils2.clamp)(columnIndexToFocus, 0, visibleColumns.length - 1);
|
|
163
173
|
const columnToFocus = visibleColumns[columnIndexToFocus];
|
|
164
174
|
apiRef.current.setCellFocus(rowToFocus.id, columnToFocus.field);
|
|
165
175
|
}, [apiRef, props.pagination, props.paginationMode]);
|
|
@@ -195,7 +205,7 @@ const useGridFocus = (apiRef, props) => {
|
|
|
195
205
|
}
|
|
196
206
|
}));
|
|
197
207
|
}, [logger, apiRef]);
|
|
198
|
-
const
|
|
208
|
+
const handleCellMouseDown = React.useCallback(params => {
|
|
199
209
|
lastClickedCell.current = params;
|
|
200
210
|
}, []);
|
|
201
211
|
const handleDocumentClick = React.useCallback(event => {
|
|
@@ -278,7 +288,7 @@ const useGridFocus = (apiRef, props) => {
|
|
|
278
288
|
}, [apiRef, handleDocumentClick]);
|
|
279
289
|
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderBlur', handleBlur);
|
|
280
290
|
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', handleCellDoubleClick);
|
|
281
|
-
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, '
|
|
291
|
+
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellMouseDown', handleCellMouseDown);
|
|
282
292
|
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', handleCellKeyDown);
|
|
283
293
|
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellModeChange', handleCellModeChange);
|
|
284
294
|
(0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus);
|
|
@@ -56,6 +56,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
56
56
|
* @param {number} colIndex Index of the column to focus
|
|
57
57
|
* @param {number} rowIndex index of the row to focus
|
|
58
58
|
* @param {string} closestColumnToUse Which closest column cell to use when the cell is spanned by `colSpan`.
|
|
59
|
+
* TODO replace with apiRef.current.unstable_moveFocusToRelativeCell()
|
|
59
60
|
*/
|
|
60
61
|
|
|
61
62
|
const goToCell = React.useCallback((colIndex, rowId, closestColumnToUse = 'left') => {
|
|
@@ -112,6 +113,7 @@ const useGridKeyboardNavigation = (apiRef, props) => {
|
|
|
112
113
|
case 'ArrowDown':
|
|
113
114
|
case 'Enter':
|
|
114
115
|
{
|
|
116
|
+
// TODO v6: Remove Enter case because `cellNavigationKeyDown` is not fired by the new editing API
|
|
115
117
|
// "Enter" is only triggered by the row / cell editing feature
|
|
116
118
|
if (rowIndexBefore < lastRowIndexInPage) {
|
|
117
119
|
goToCell(colIndexBefore, getRowIdFromIndex(rowIndexBefore + 1));
|
|
@@ -131,14 +131,14 @@ const useGridRows = (apiRef, props) => {
|
|
|
131
131
|
} // we remove duplicate updates. A server can batch updates, and send several updates for the same row in one fn call.
|
|
132
132
|
|
|
133
133
|
|
|
134
|
-
const
|
|
134
|
+
const uniqueUpdates = new Map();
|
|
135
135
|
updates.forEach(update => {
|
|
136
136
|
const id = (0, _gridRowsUtils.getRowIdFromRowModel)(update, props.getRowId, 'A row was provided without id when calling updateRows():');
|
|
137
137
|
|
|
138
|
-
if (
|
|
139
|
-
|
|
138
|
+
if (uniqueUpdates.has(id)) {
|
|
139
|
+
uniqueUpdates.set(id, (0, _extends2.default)({}, uniqueUpdates.get(id), update));
|
|
140
140
|
} else {
|
|
141
|
-
|
|
141
|
+
uniqueUpdates.set(id, update);
|
|
142
142
|
}
|
|
143
143
|
});
|
|
144
144
|
const deletedRowIds = [];
|
|
@@ -150,7 +150,7 @@ const useGridRows = (apiRef, props) => {
|
|
|
150
150
|
idToIdLookup: (0, _extends2.default)({}, prevCache.idToIdLookup),
|
|
151
151
|
ids: [...prevCache.ids]
|
|
152
152
|
};
|
|
153
|
-
|
|
153
|
+
uniqueUpdates.forEach((partialRow, id) => {
|
|
154
154
|
// eslint-disable-next-line no-underscore-dangle
|
|
155
155
|
if (partialRow._action === 'delete') {
|
|
156
156
|
delete newCache.idRowsLookup[id];
|
|
@@ -267,8 +267,60 @@ const useGridRows = (apiRef, props) => {
|
|
|
267
267
|
ids: updatedRows
|
|
268
268
|
})
|
|
269
269
|
}));
|
|
270
|
-
apiRef.current.
|
|
270
|
+
apiRef.current.publishEvent('rowsSet');
|
|
271
271
|
}, [apiRef, logger]);
|
|
272
|
+
const replaceRows = React.useCallback((firstRowToRender, newRows) => {
|
|
273
|
+
if (props.signature === _useGridApiEventHandler.GridSignature.DataGrid && newRows.length > 1) {
|
|
274
|
+
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'));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (newRows.length === 0) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const allRows = (0, _gridRowsSelector.gridRowIdsSelector)(apiRef);
|
|
282
|
+
const updatedRows = [...allRows];
|
|
283
|
+
const idRowsLookup = (0, _gridRowsSelector.gridRowsLookupSelector)(apiRef);
|
|
284
|
+
const idToIdLookup = (0, _gridRowsSelector.gridRowsIdToIdLookupSelector)(apiRef);
|
|
285
|
+
const tree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
|
|
286
|
+
const updatedIdRowsLookup = (0, _extends2.default)({}, idRowsLookup);
|
|
287
|
+
const updatedIdToIdLookup = (0, _extends2.default)({}, idToIdLookup);
|
|
288
|
+
const updatedTree = (0, _extends2.default)({}, tree);
|
|
289
|
+
const newRowEntries = newRows.map(newRowModel => {
|
|
290
|
+
const rowId = (0, _gridRowsUtils.getRowIdFromRowModel)(newRowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
|
|
291
|
+
return {
|
|
292
|
+
id: rowId,
|
|
293
|
+
model: newRowModel
|
|
294
|
+
};
|
|
295
|
+
});
|
|
296
|
+
newRowEntries.forEach((row, index) => {
|
|
297
|
+
const [replacedRowId] = updatedRows.splice(firstRowToRender + index, 1, row.id);
|
|
298
|
+
delete updatedIdRowsLookup[replacedRowId];
|
|
299
|
+
delete updatedIdToIdLookup[replacedRowId];
|
|
300
|
+
delete updatedTree[replacedRowId];
|
|
301
|
+
});
|
|
302
|
+
newRowEntries.forEach(row => {
|
|
303
|
+
const rowTreeNodeConfig = {
|
|
304
|
+
id: row.id,
|
|
305
|
+
parent: null,
|
|
306
|
+
depth: 0,
|
|
307
|
+
groupingKey: null,
|
|
308
|
+
groupingField: null
|
|
309
|
+
};
|
|
310
|
+
updatedIdRowsLookup[row.id] = row.model;
|
|
311
|
+
updatedIdToIdLookup[row.id] = row.id;
|
|
312
|
+
updatedTree[row.id] = rowTreeNodeConfig;
|
|
313
|
+
});
|
|
314
|
+
apiRef.current.setState(state => (0, _extends2.default)({}, state, {
|
|
315
|
+
rows: (0, _extends2.default)({}, state.rows, {
|
|
316
|
+
idRowsLookup: updatedIdRowsLookup,
|
|
317
|
+
idToIdLookup: updatedIdToIdLookup,
|
|
318
|
+
tree: updatedTree,
|
|
319
|
+
ids: updatedRows
|
|
320
|
+
})
|
|
321
|
+
}));
|
|
322
|
+
apiRef.current.publishEvent('rowsSet');
|
|
323
|
+
}, [apiRef, props.signature, props.getRowId]);
|
|
272
324
|
const rowApi = {
|
|
273
325
|
getRow,
|
|
274
326
|
getRowModels,
|
|
@@ -280,7 +332,8 @@ const useGridRows = (apiRef, props) => {
|
|
|
280
332
|
setRowChildrenExpansion,
|
|
281
333
|
getRowNode,
|
|
282
334
|
getRowIndexRelativeToVisibleRows,
|
|
283
|
-
getRowGroupChildren
|
|
335
|
+
getRowGroupChildren,
|
|
336
|
+
unstable_replaceRows: replaceRows
|
|
284
337
|
};
|
|
285
338
|
/**
|
|
286
339
|
* EVENTS
|
|
@@ -75,7 +75,7 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
75
75
|
if (!rowsHeightLookup.current[row.id]) {
|
|
76
76
|
rowsHeightLookup.current[row.id] = {
|
|
77
77
|
sizes: {
|
|
78
|
-
|
|
78
|
+
baseCenter: rowHeightFromDensity
|
|
79
79
|
},
|
|
80
80
|
isResized: false,
|
|
81
81
|
autoHeight: false,
|
|
@@ -90,7 +90,7 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
90
90
|
sizes
|
|
91
91
|
} = rowsHeightLookup.current[row.id];
|
|
92
92
|
let baseRowHeight = rowHeightFromDensity;
|
|
93
|
-
const existingBaseRowHeight = sizes.
|
|
93
|
+
const existingBaseRowHeight = sizes.baseCenter;
|
|
94
94
|
|
|
95
95
|
if (isResized) {
|
|
96
96
|
// Do not recalculate resized row height and use the value from the lookup
|
|
@@ -121,12 +121,19 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
121
121
|
}
|
|
122
122
|
} else {
|
|
123
123
|
rowsHeightLookup.current[row.id].needsFirstMeasurement = false;
|
|
124
|
-
}
|
|
124
|
+
}
|
|
125
125
|
|
|
126
|
+
const existingBaseSizes = Object.entries(sizes).reduce((acc, [key, size]) => {
|
|
127
|
+
if (/^base[A-Z]/.test(key)) {
|
|
128
|
+
acc[key] = size;
|
|
129
|
+
}
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
131
|
+
return acc;
|
|
132
|
+
}, {}); // We use an object to make simple to check if a height is already added or not
|
|
133
|
+
|
|
134
|
+
const initialHeights = (0, _extends2.default)({}, existingBaseSizes, {
|
|
135
|
+
baseCenter: baseRowHeight
|
|
136
|
+
});
|
|
130
137
|
|
|
131
138
|
if (getRowSpacing) {
|
|
132
139
|
var _spacing$top, _spacing$bottom;
|
|
@@ -149,9 +156,17 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
149
156
|
const positions = [];
|
|
150
157
|
const currentPageTotalHeight = currentPage.rows.reduce((acc, row) => {
|
|
151
158
|
positions.push(acc);
|
|
159
|
+
let maximumBaseSize = 0;
|
|
160
|
+
let otherSizes = 0;
|
|
152
161
|
const processedSizes = calculateRowProcessedSizes(row);
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
Object.entries(processedSizes).forEach(([size, value]) => {
|
|
163
|
+
if (/^base[A-Z]/.test(size)) {
|
|
164
|
+
maximumBaseSize = value > maximumBaseSize ? value : maximumBaseSize;
|
|
165
|
+
} else {
|
|
166
|
+
otherSizes += value;
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
return acc + maximumBaseSize + otherSizes;
|
|
155
170
|
}, 0);
|
|
156
171
|
pinnedRows == null ? void 0 : (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.forEach(row => {
|
|
157
172
|
calculateRowProcessedSizes(row);
|
|
@@ -177,7 +192,7 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
177
192
|
}, [apiRef, currentPage.rows, rowHeightFromDensity, getRowHeightProp, getRowSpacing, getEstimatedRowHeight, pinnedRows]);
|
|
178
193
|
const getRowHeight = React.useCallback(rowId => {
|
|
179
194
|
const height = rowsHeightLookup.current[rowId];
|
|
180
|
-
return height ? height.sizes.
|
|
195
|
+
return height ? height.sizes.baseCenter : rowHeightFromDensity;
|
|
181
196
|
}, [rowHeightFromDensity]);
|
|
182
197
|
|
|
183
198
|
const getRowInternalSizes = rowId => {
|
|
@@ -187,21 +202,21 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
187
202
|
};
|
|
188
203
|
|
|
189
204
|
const setRowHeight = React.useCallback((id, height) => {
|
|
190
|
-
rowsHeightLookup.current[id].sizes.
|
|
205
|
+
rowsHeightLookup.current[id].sizes.baseCenter = height;
|
|
191
206
|
rowsHeightLookup.current[id].isResized = true;
|
|
192
207
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
193
208
|
hydrateRowsMeta();
|
|
194
209
|
}, [hydrateRowsMeta]);
|
|
195
210
|
const debouncedHydrateRowsMeta = React.useMemo(() => (0, _utils.debounce)(hydrateRowsMeta), [hydrateRowsMeta]);
|
|
196
|
-
const storeMeasuredRowHeight = React.useCallback((id, height) => {
|
|
211
|
+
const storeMeasuredRowHeight = React.useCallback((id, height, position) => {
|
|
197
212
|
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
|
|
198
213
|
return;
|
|
199
214
|
} // Only trigger hydration if the value is different, otherwise we trigger a loop
|
|
200
215
|
|
|
201
216
|
|
|
202
|
-
const needsHydration = rowsHeightLookup.current[id].sizes
|
|
217
|
+
const needsHydration = rowsHeightLookup.current[id].sizes[`base${(0, _utils.capitalize)(position)}`] !== height;
|
|
203
218
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
204
|
-
rowsHeightLookup.current[id].sizes
|
|
219
|
+
rowsHeightLookup.current[id].sizes[`base${(0, _utils.capitalize)(position)}`] = height;
|
|
205
220
|
|
|
206
221
|
if (needsHydration) {
|
|
207
222
|
debouncedHydrateRowsMeta();
|
|
@@ -219,7 +234,11 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
219
234
|
if (hasRowWithAutoHeight.current && index > lastMeasuredRowIndex.current) {
|
|
220
235
|
lastMeasuredRowIndex.current = index;
|
|
221
236
|
}
|
|
222
|
-
}, []);
|
|
237
|
+
}, []);
|
|
238
|
+
const resetRowHeights = React.useCallback(() => {
|
|
239
|
+
rowsHeightLookup.current = {};
|
|
240
|
+
hydrateRowsMeta();
|
|
241
|
+
}, [hydrateRowsMeta]); // The effect is used to build the rows meta data - currentPageTotalHeight and positions.
|
|
223
242
|
// Because of variable row height this is needed for the virtualization
|
|
224
243
|
|
|
225
244
|
React.useEffect(() => {
|
|
@@ -233,7 +252,8 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
233
252
|
unstable_getRowHeight: getRowHeight,
|
|
234
253
|
unstable_getRowInternalSizes: getRowInternalSizes,
|
|
235
254
|
unstable_setRowHeight: setRowHeight,
|
|
236
|
-
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight
|
|
255
|
+
unstable_storeRowHeightMeasurement: storeMeasuredRowHeight,
|
|
256
|
+
resetRowHeights
|
|
237
257
|
};
|
|
238
258
|
(0, _useGridApiMethod.useGridApiMethod)(apiRef, rowsMetaApi, 'GridRowsMetaApi');
|
|
239
259
|
};
|
|
@@ -252,8 +252,19 @@ const useGridVirtualScroller = props => {
|
|
|
252
252
|
}, [renderContext, updateRenderZonePosition]);
|
|
253
253
|
const updateRenderContext = React.useCallback(nextRenderContext => {
|
|
254
254
|
setRenderContext(nextRenderContext);
|
|
255
|
+
const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
|
|
256
|
+
firstIndex: nextRenderContext.firstRowIndex,
|
|
257
|
+
lastIndex: nextRenderContext.lastRowIndex,
|
|
258
|
+
minFirstIndex: 0,
|
|
259
|
+
maxLastIndex: currentPage.rows.length,
|
|
260
|
+
buffer: rootProps.rowBuffer
|
|
261
|
+
});
|
|
262
|
+
apiRef.current.publishEvent('renderedRowsIntervalChange', {
|
|
263
|
+
firstRowToRender,
|
|
264
|
+
lastRowToRender
|
|
265
|
+
});
|
|
255
266
|
prevRenderContext.current = nextRenderContext;
|
|
256
|
-
}, [setRenderContext, prevRenderContext]);
|
|
267
|
+
}, [apiRef, setRenderContext, prevRenderContext, currentPage.rows.length, rootProps.rowBuffer]);
|
|
257
268
|
React.useEffect(() => {
|
|
258
269
|
if (containerWidth == null) {
|
|
259
270
|
return;
|
|
@@ -324,8 +335,8 @@ const useGridVirtualScroller = props => {
|
|
|
324
335
|
minFirstColumn = renderZoneMinColumnIndex,
|
|
325
336
|
maxLastColumn = renderZoneMaxColumnIndex,
|
|
326
337
|
availableSpace = containerWidth,
|
|
327
|
-
|
|
328
|
-
|
|
338
|
+
rowIndexOffset = 0,
|
|
339
|
+
position = 'center'
|
|
329
340
|
} = params;
|
|
330
341
|
|
|
331
342
|
if (!nextRenderContext || availableSpace == null) {
|
|
@@ -395,7 +406,7 @@ const useGridVirtualScroller = props => {
|
|
|
395
406
|
model
|
|
396
407
|
} = renderedRows[i];
|
|
397
408
|
const lastVisibleRowIndex = firstRowToRender + i === currentPage.rows.length - 1;
|
|
398
|
-
const baseRowHeight = !apiRef.current.unstable_rowHasAutoHeight(id)
|
|
409
|
+
const baseRowHeight = !apiRef.current.unstable_rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
|
|
399
410
|
let isSelected;
|
|
400
411
|
|
|
401
412
|
if (selectedRowsLookup[id] == null) {
|
|
@@ -421,7 +432,8 @@ const useGridVirtualScroller = props => {
|
|
|
421
432
|
selected: isSelected,
|
|
422
433
|
index: rowIndexOffset + ((currentPage == null ? void 0 : (_currentPage$range5 = currentPage.range) == null ? void 0 : _currentPage$range5.firstRowIndex) || 0) + firstRowToRender + i,
|
|
423
434
|
containerWidth: availableSpace,
|
|
424
|
-
isLastVisible: lastVisibleRowIndex
|
|
435
|
+
isLastVisible: lastVisibleRowIndex,
|
|
436
|
+
position: position
|
|
425
437
|
}, typeof getRowProps === 'function' ? getRowProps(id, model) : {}, (_rootProps$components = rootProps.componentsProps) == null ? void 0 : _rootProps$components.row), id));
|
|
426
438
|
}
|
|
427
439
|
|
package/node/index.js
CHANGED
package/node/internals/index.js
CHANGED
|
@@ -135,6 +135,12 @@ Object.defineProperty(exports, "getColumnsToExport", {
|
|
|
135
135
|
return _utils.getColumnsToExport;
|
|
136
136
|
}
|
|
137
137
|
});
|
|
138
|
+
Object.defineProperty(exports, "getRenderableIndexes", {
|
|
139
|
+
enumerable: true,
|
|
140
|
+
get: function () {
|
|
141
|
+
return _useGridVirtualScroller.getRenderableIndexes;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
138
144
|
Object.defineProperty(exports, "getRowIdFromRowModel", {
|
|
139
145
|
enumerable: true,
|
|
140
146
|
get: function () {
|
|
@@ -92,4 +92,6 @@ exports.GridEvents = GridEvents;
|
|
|
92
92
|
GridEvents["preferencePanelOpen"] = "preferencePanelOpen";
|
|
93
93
|
GridEvents["menuOpen"] = "menuOpen";
|
|
94
94
|
GridEvents["menuClose"] = "menuClose";
|
|
95
|
+
GridEvents["renderedRowsIntervalChange"] = "renderedRowsIntervalChange";
|
|
96
|
+
GridEvents["fetchRows"] = "fetchRows";
|
|
95
97
|
})(GridEvents || (exports.GridEvents = GridEvents = {}));
|
|
@@ -184,4 +184,17 @@ Object.keys(_gridMenuParams).forEach(function (key) {
|
|
|
184
184
|
return _gridMenuParams[key];
|
|
185
185
|
}
|
|
186
186
|
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
var _gridRenderedRowsIntervalChangeParams = require("./gridRenderedRowsIntervalChangeParams");
|
|
190
|
+
|
|
191
|
+
Object.keys(_gridRenderedRowsIntervalChangeParams).forEach(function (key) {
|
|
192
|
+
if (key === "default" || key === "__esModule") return;
|
|
193
|
+
if (key in exports && exports[key] === _gridRenderedRowsIntervalChangeParams[key]) return;
|
|
194
|
+
Object.defineProperty(exports, key, {
|
|
195
|
+
enumerable: true,
|
|
196
|
+
get: function () {
|
|
197
|
+
return _gridRenderedRowsIntervalChangeParams[key];
|
|
198
|
+
}
|
|
199
|
+
});
|
|
187
200
|
});
|
package/node/utils/utils.js
CHANGED
|
@@ -4,12 +4,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.clamp = void 0;
|
|
7
|
+
exports.deepClone = deepClone;
|
|
7
8
|
exports.escapeRegExp = escapeRegExp;
|
|
8
9
|
exports.isDeepEqual = isDeepEqual;
|
|
9
10
|
exports.isFunction = isFunction;
|
|
10
11
|
exports.isNumber = isNumber;
|
|
11
12
|
exports.isObject = isObject;
|
|
12
13
|
exports.localStorageAvailable = localStorageAvailable;
|
|
14
|
+
exports.randomNumberBetween = randomNumberBetween;
|
|
13
15
|
|
|
14
16
|
function isNumber(value) {
|
|
15
17
|
return typeof value === 'number';
|
|
@@ -198,4 +200,29 @@ function isDeepEqual(a, b) {
|
|
|
198
200
|
|
|
199
201
|
|
|
200
202
|
return a !== a && b !== b;
|
|
203
|
+
} // Pseudo random number. See https://stackoverflow.com/a/47593316
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
function mulberry32(a) {
|
|
207
|
+
return () => {
|
|
208
|
+
/* eslint-disable */
|
|
209
|
+
let t = a += 0x6d2b79f5;
|
|
210
|
+
t = Math.imul(t ^ t >>> 15, t | 1);
|
|
211
|
+
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
|
|
212
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
213
|
+
/* eslint-enable */
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function randomNumberBetween(seed, min, max) {
|
|
218
|
+
const random = mulberry32(seed);
|
|
219
|
+
return () => min + (max - min) * random();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function deepClone(obj) {
|
|
223
|
+
if (typeof structuredClone === 'function') {
|
|
224
|
+
return structuredClone(obj);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return JSON.parse(JSON.stringify(obj));
|
|
201
228
|
}
|
package/package.json
CHANGED
package/utils/utils.d.ts
CHANGED
|
@@ -35,3 +35,5 @@ export declare const clamp: (value: number, min: number, max: number) => number;
|
|
|
35
35
|
* We only type the public interface to avoid dozens of `as` in the function.
|
|
36
36
|
*/
|
|
37
37
|
export declare function isDeepEqual<T>(actual: any, expected: T): actual is T;
|
|
38
|
+
export declare function randomNumberBetween(seed: number, min: number, max: number): () => number;
|
|
39
|
+
export declare function deepClone(obj: Record<string, any>): any;
|