@mui/x-data-grid-premium 8.19.0 → 8.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 +174 -0
- package/DataGridPremium/DataGridPremium.d.ts +1 -1
- package/DataGridPremium/DataGridPremium.js +27 -1
- package/DataGridPremium/useDataGridPremiumComponent.d.ts +1 -1
- package/esm/DataGridPremium/DataGridPremium.d.ts +1 -1
- package/esm/DataGridPremium/DataGridPremium.js +27 -1
- package/esm/DataGridPremium/useDataGridPremiumComponent.d.ts +1 -1
- package/esm/hooks/features/clipboard/useGridClipboardImport.js +6 -0
- package/esm/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
- package/esm/hooks/features/rowGrouping/useGridRowGrouping.js +21 -17
- package/esm/hooks/features/rowReorder/operations.d.ts +7 -27
- package/esm/hooks/features/rowReorder/operations.js +133 -274
- package/esm/hooks/features/rowReorder/rowGroupingReorderExecutor.d.ts +2 -0
- package/esm/hooks/features/rowReorder/rowGroupingReorderExecutor.js +3 -0
- package/esm/hooks/features/rowReorder/rowGroupingReorderValidator.d.ts +2 -0
- package/esm/hooks/features/rowReorder/{reorderValidator.js → rowGroupingReorderValidator.js} +2 -22
- package/esm/hooks/features/rows/useGridRowsOverridableMethods.d.ts +3 -3
- package/esm/hooks/features/rows/useGridRowsOverridableMethods.js +61 -7
- package/esm/index.js +1 -1
- package/hooks/features/clipboard/useGridClipboardImport.js +6 -0
- package/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
- package/hooks/features/rowGrouping/useGridRowGrouping.js +20 -16
- package/hooks/features/rowReorder/operations.d.ts +7 -27
- package/hooks/features/rowReorder/operations.js +136 -279
- package/hooks/features/rowReorder/rowGroupingReorderExecutor.d.ts +2 -0
- package/hooks/features/rowReorder/rowGroupingReorderExecutor.js +9 -0
- package/hooks/features/rowReorder/rowGroupingReorderValidator.d.ts +2 -0
- package/hooks/features/rowReorder/rowGroupingReorderValidator.js +102 -0
- package/hooks/features/rows/useGridRowsOverridableMethods.d.ts +3 -3
- package/hooks/features/rows/useGridRowsOverridableMethods.js +61 -7
- package/index.js +1 -1
- package/package.json +5 -5
- package/esm/hooks/features/rowReorder/reorderExecutor.d.ts +0 -15
- package/esm/hooks/features/rowReorder/reorderExecutor.js +0 -25
- package/esm/hooks/features/rowReorder/reorderValidator.d.ts +0 -16
- package/esm/hooks/features/rowReorder/types.d.ts +0 -42
- package/esm/hooks/features/rowReorder/types.js +0 -1
- package/esm/hooks/features/rowReorder/utils.d.ts +0 -127
- package/esm/hooks/features/rowReorder/utils.js +0 -343
- package/hooks/features/rowReorder/reorderExecutor.d.ts +0 -15
- package/hooks/features/rowReorder/reorderExecutor.js +0 -31
- package/hooks/features/rowReorder/reorderValidator.d.ts +0 -16
- package/hooks/features/rowReorder/reorderValidator.js +0 -122
- package/hooks/features/rowReorder/types.d.ts +0 -42
- package/hooks/features/rowReorder/types.js +0 -5
- package/hooks/features/rowReorder/utils.d.ts +0 -127
- package/hooks/features/rowReorder/utils.js +0 -360
|
@@ -1,128 +1,8 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import { gridRowNodeSelector, gridRowTreeSelector, gridRowsLookupSelector, gridColumnLookupSelector } from '@mui/x-data-grid-pro';
|
|
3
|
-
import {
|
|
4
|
-
import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
|
|
3
|
+
import { BaseReorderOperation, rowReorderUtils } from '@mui/x-data-grid-pro/internals';
|
|
5
4
|
import { gridRowGroupingSanitizedModelSelector } from "../rowGrouping/index.js";
|
|
6
5
|
import { getGroupingRules, getCellGroupingCriteria } from "../rowGrouping/gridRowGroupingUtils.js";
|
|
7
|
-
import { determineOperationType, calculateTargetIndex, collectAllLeafDescendants, getNodePathInTree, removeEmptyAncestors, findExistingGroupWithSameKey, BatchRowUpdater } from "./utils.js";
|
|
8
|
-
/**
|
|
9
|
-
* Base class for all reorder operations.
|
|
10
|
-
* Provides abstract methods for operation detection and execution.
|
|
11
|
-
*/
|
|
12
|
-
export class BaseReorderOperation {}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Handles reordering of items within the same parent group.
|
|
16
|
-
*/
|
|
17
|
-
export class SameParentSwapOperation extends BaseReorderOperation {
|
|
18
|
-
operationType = 'same-parent-swap';
|
|
19
|
-
detectOperation(ctx) {
|
|
20
|
-
const {
|
|
21
|
-
sourceRowId,
|
|
22
|
-
placeholderIndex,
|
|
23
|
-
sortedFilteredRowIds,
|
|
24
|
-
sortedFilteredRowIndexLookup,
|
|
25
|
-
rowTree,
|
|
26
|
-
apiRef
|
|
27
|
-
} = ctx;
|
|
28
|
-
const sourceNode = gridRowNodeSelector(apiRef, sourceRowId);
|
|
29
|
-
if (!sourceNode || sourceNode.type === 'footer') {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
let targetIndex = placeholderIndex;
|
|
33
|
-
const sourceIndex = sortedFilteredRowIndexLookup[sourceRowId];
|
|
34
|
-
if (targetIndex === sortedFilteredRowIds.length && sortedFilteredRowIds.length > 0) {
|
|
35
|
-
targetIndex -= 1;
|
|
36
|
-
}
|
|
37
|
-
let targetNode = gridRowNodeSelector(apiRef, sortedFilteredRowIds[targetIndex]);
|
|
38
|
-
if (placeholderIndex > sourceIndex && sourceNode.parent === targetNode.parent) {
|
|
39
|
-
targetIndex = placeholderIndex - 1;
|
|
40
|
-
targetNode = gridRowNodeSelector(apiRef, sortedFilteredRowIds[targetIndex]);
|
|
41
|
-
if (targetNode && targetNode.depth !== sourceNode.depth) {
|
|
42
|
-
while (targetNode.depth > sourceNode.depth && targetIndex >= 0) {
|
|
43
|
-
targetIndex -= 1;
|
|
44
|
-
targetNode = gridRowNodeSelector(apiRef, sortedFilteredRowIds[targetIndex]);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
if (targetIndex === -1) {
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
let isLastChild = false;
|
|
52
|
-
if (!targetNode) {
|
|
53
|
-
if (placeholderIndex >= sortedFilteredRowIds.length && sortedFilteredRowIds.length > 0) {
|
|
54
|
-
targetNode = gridRowNodeSelector(apiRef, sortedFilteredRowIds[sortedFilteredRowIds.length - 1]);
|
|
55
|
-
isLastChild = true;
|
|
56
|
-
} else {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
let adjustedTargetNode = targetNode;
|
|
61
|
-
|
|
62
|
-
// Case A and B adjustment
|
|
63
|
-
if (targetNode.type === 'group' && sourceNode.parent !== targetNode.parent && sourceNode.depth > targetNode.depth) {
|
|
64
|
-
let i = targetIndex - 1;
|
|
65
|
-
while (i >= 0) {
|
|
66
|
-
const node = gridRowNodeSelector(apiRef, sortedFilteredRowIds[i]);
|
|
67
|
-
if (node && node.depth < sourceNode.depth) {
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
if (node && node.depth === sourceNode.depth) {
|
|
71
|
-
targetIndex = i;
|
|
72
|
-
adjustedTargetNode = node;
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
i -= 1;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
const operationType = determineOperationType(sourceNode, adjustedTargetNode);
|
|
79
|
-
if (operationType !== 'same-parent-swap') {
|
|
80
|
-
return null;
|
|
81
|
-
}
|
|
82
|
-
const actualTargetIndex = calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree);
|
|
83
|
-
targetNode = adjustedTargetNode;
|
|
84
|
-
if (sourceNode.type !== targetNode.type) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
return {
|
|
88
|
-
sourceNode,
|
|
89
|
-
targetNode,
|
|
90
|
-
actualTargetIndex,
|
|
91
|
-
isLastChild,
|
|
92
|
-
operationType
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
executeOperation(operation, ctx) {
|
|
96
|
-
const {
|
|
97
|
-
sourceNode,
|
|
98
|
-
actualTargetIndex
|
|
99
|
-
} = operation;
|
|
100
|
-
const {
|
|
101
|
-
apiRef,
|
|
102
|
-
sourceRowId
|
|
103
|
-
} = ctx;
|
|
104
|
-
apiRef.current.setState(state => {
|
|
105
|
-
const group = gridRowTreeSelector(apiRef)[sourceNode.parent];
|
|
106
|
-
const currentChildren = [...group.children];
|
|
107
|
-
const oldIndex = currentChildren.findIndex(row => row === sourceRowId);
|
|
108
|
-
if (oldIndex === -1 || actualTargetIndex === -1 || oldIndex === actualTargetIndex) {
|
|
109
|
-
return state;
|
|
110
|
-
}
|
|
111
|
-
currentChildren.splice(actualTargetIndex, 0, currentChildren.splice(oldIndex, 1)[0]);
|
|
112
|
-
return _extends({}, state, {
|
|
113
|
-
rows: _extends({}, state.rows, {
|
|
114
|
-
tree: _extends({}, state.rows.tree, {
|
|
115
|
-
[sourceNode.parent]: _extends({}, group, {
|
|
116
|
-
children: currentChildren
|
|
117
|
-
})
|
|
118
|
-
})
|
|
119
|
-
})
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
apiRef.current.publishEvent('rowsSet');
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
6
|
/**
|
|
127
7
|
* Handles moving leaf nodes between different parent groups.
|
|
128
8
|
*/
|
|
@@ -164,11 +44,11 @@ export class CrossParentLeafOperation extends BaseReorderOperation {
|
|
|
164
44
|
}
|
|
165
45
|
}
|
|
166
46
|
}
|
|
167
|
-
const operationType = determineOperationType(sourceNode, adjustedTargetNode);
|
|
47
|
+
const operationType = rowReorderUtils.determineOperationType(sourceNode, adjustedTargetNode);
|
|
168
48
|
if (operationType !== 'cross-parent-leaf') {
|
|
169
49
|
return null;
|
|
170
50
|
}
|
|
171
|
-
const actualTargetIndex = calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree);
|
|
51
|
+
const actualTargetIndex = rowReorderUtils.calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree);
|
|
172
52
|
targetNode = adjustedTargetNode;
|
|
173
53
|
|
|
174
54
|
// Validate depth constraints
|
|
@@ -246,72 +126,56 @@ export class CrossParentLeafOperation extends BaseReorderOperation {
|
|
|
246
126
|
updatedSourceRow[groupingRule.field] = targetRow[groupingRule.field];
|
|
247
127
|
}
|
|
248
128
|
}
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
129
|
+
const updater = new rowReorderUtils.BatchRowUpdater(apiRef, processRowUpdate, onProcessRowUpdateError);
|
|
130
|
+
updater.queueUpdate(sourceRowId, originalSourceRow, updatedSourceRow);
|
|
131
|
+
const {
|
|
132
|
+
successful,
|
|
133
|
+
updates
|
|
134
|
+
} = await updater.executeAll();
|
|
135
|
+
if (successful.length === 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const finalSourceRow = updates[0];
|
|
139
|
+
apiRef.current.setState(state => {
|
|
140
|
+
const updatedSourceChildren = sourceChildren.filter(rowId => rowId !== sourceRowId);
|
|
141
|
+
const updatedTree = _extends({}, state.rows.tree);
|
|
142
|
+
const removedGroups = new Set();
|
|
143
|
+
let rootLevelRemovals = 0;
|
|
144
|
+
if (updatedSourceChildren.length === 0) {
|
|
145
|
+
removedGroups.add(sourceGroup.id);
|
|
146
|
+
rootLevelRemovals = rowReorderUtils.removeEmptyAncestors(sourceGroup.parent, updatedTree, removedGroups);
|
|
147
|
+
}
|
|
148
|
+
removedGroups.forEach(groupId => {
|
|
149
|
+
const group = updatedTree[groupId];
|
|
150
|
+
if (group && group.parent && updatedTree[group.parent]) {
|
|
151
|
+
const parent = updatedTree[group.parent];
|
|
152
|
+
updatedTree[group.parent] = _extends({}, parent, {
|
|
153
|
+
children: parent.children.filter(childId => childId !== groupId)
|
|
272
154
|
});
|
|
273
155
|
}
|
|
274
|
-
|
|
275
|
-
updatedTree[target.parent] = _extends({}, targetGroup, {
|
|
276
|
-
children: updatedTargetChildren
|
|
277
|
-
});
|
|
278
|
-
updatedTree[sourceNode.id] = _extends({}, sourceNode, {
|
|
279
|
-
parent: target.parent
|
|
280
|
-
});
|
|
281
|
-
return _extends({}, state, {
|
|
282
|
-
rows: _extends({}, state.rows, {
|
|
283
|
-
totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals,
|
|
284
|
-
tree: updatedTree
|
|
285
|
-
})
|
|
286
|
-
});
|
|
156
|
+
delete updatedTree[groupId];
|
|
287
157
|
});
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const params = {
|
|
293
|
-
rowId: sourceRowId,
|
|
294
|
-
previousRow: originalSourceRow,
|
|
295
|
-
updatedRow: updatedSourceRow
|
|
296
|
-
};
|
|
297
|
-
apiRef.current.setLoading(true);
|
|
298
|
-
try {
|
|
299
|
-
const processedRow = await processRowUpdate(updatedSourceRow, originalSourceRow, params);
|
|
300
|
-
const finalRow = processedRow || updatedSourceRow;
|
|
301
|
-
commitStateUpdate(finalRow);
|
|
302
|
-
} catch (error) {
|
|
303
|
-
apiRef.current.setLoading(false);
|
|
304
|
-
if (onProcessRowUpdateError) {
|
|
305
|
-
onProcessRowUpdateError(error);
|
|
306
|
-
} else if (process.env.NODE_ENV !== 'production') {
|
|
307
|
-
warnOnce(['MUI X: A call to `processRowUpdate()` threw an error which was not handled because `onProcessRowUpdateError()` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError()` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/persistence/.'], 'error');
|
|
308
|
-
}
|
|
309
|
-
} finally {
|
|
310
|
-
apiRef.current.setLoading(false);
|
|
158
|
+
if (!removedGroups.has(sourceGroup.id)) {
|
|
159
|
+
updatedTree[sourceNode.parent] = _extends({}, sourceGroup, {
|
|
160
|
+
children: updatedSourceChildren
|
|
161
|
+
});
|
|
311
162
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
163
|
+
const updatedTargetChildren = isLastChild ? [...targetChildren, sourceRowId] : [...targetChildren.slice(0, targetIndex), sourceRowId, ...targetChildren.slice(targetIndex)];
|
|
164
|
+
updatedTree[target.parent] = _extends({}, targetGroup, {
|
|
165
|
+
children: updatedTargetChildren
|
|
166
|
+
});
|
|
167
|
+
updatedTree[sourceNode.id] = _extends({}, sourceNode, {
|
|
168
|
+
parent: target.parent
|
|
169
|
+
});
|
|
170
|
+
return _extends({}, state, {
|
|
171
|
+
rows: _extends({}, state.rows, {
|
|
172
|
+
totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals,
|
|
173
|
+
tree: updatedTree
|
|
174
|
+
})
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
apiRef.current.updateRows([finalSourceRow]);
|
|
178
|
+
apiRef.current.publishEvent('rowsSet');
|
|
315
179
|
}
|
|
316
180
|
}
|
|
317
181
|
|
|
@@ -365,11 +229,11 @@ export class CrossParentGroupOperation extends BaseReorderOperation {
|
|
|
365
229
|
isLastChild = true;
|
|
366
230
|
adjustedTargetNode = prevNode;
|
|
367
231
|
}
|
|
368
|
-
const operationType = determineOperationType(sourceNode, adjustedTargetNode);
|
|
232
|
+
const operationType = rowReorderUtils.determineOperationType(sourceNode, adjustedTargetNode);
|
|
369
233
|
if (operationType !== 'cross-parent-group') {
|
|
370
234
|
return null;
|
|
371
235
|
}
|
|
372
|
-
const actualTargetIndex = calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree);
|
|
236
|
+
const actualTargetIndex = rowReorderUtils.calculateTargetIndex(sourceNode, adjustedTargetNode, isLastChild, rowTree);
|
|
373
237
|
const operation = {
|
|
374
238
|
sourceNode,
|
|
375
239
|
targetNode: adjustedTargetNode,
|
|
@@ -398,16 +262,16 @@ export class CrossParentGroupOperation extends BaseReorderOperation {
|
|
|
398
262
|
const dataRowIdToModelLookup = gridRowsLookupSelector(apiRef);
|
|
399
263
|
const columnsLookup = gridColumnLookupSelector(apiRef);
|
|
400
264
|
const sanitizedRowGroupingModel = gridRowGroupingSanitizedModelSelector(apiRef);
|
|
401
|
-
const allLeafIds = collectAllLeafDescendants(sourceNode, tree);
|
|
265
|
+
const allLeafIds = rowReorderUtils.collectAllLeafDescendants(sourceNode, tree);
|
|
402
266
|
if (allLeafIds.length === 0) {
|
|
403
267
|
return;
|
|
404
268
|
}
|
|
405
|
-
const updater = new BatchRowUpdater(processRowUpdate, onProcessRowUpdateError);
|
|
269
|
+
const updater = new rowReorderUtils.BatchRowUpdater(apiRef, processRowUpdate, onProcessRowUpdateError);
|
|
406
270
|
const groupingRules = getGroupingRules({
|
|
407
271
|
sanitizedRowGroupingModel,
|
|
408
272
|
columnsLookup
|
|
409
273
|
});
|
|
410
|
-
const targetParentPath = getNodePathInTree({
|
|
274
|
+
const targetParentPath = rowReorderUtils.getNodePathInTree({
|
|
411
275
|
id: targetNode.parent,
|
|
412
276
|
tree
|
|
413
277
|
});
|
|
@@ -430,22 +294,75 @@ export class CrossParentGroupOperation extends BaseReorderOperation {
|
|
|
430
294
|
}
|
|
431
295
|
updater.queueUpdate(leafId, originalRow, updatedRow);
|
|
432
296
|
}
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if (
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
|
|
297
|
+
const {
|
|
298
|
+
successful,
|
|
299
|
+
failed,
|
|
300
|
+
updates
|
|
301
|
+
} = await updater.executeAll();
|
|
302
|
+
if (successful.length > 0) {
|
|
303
|
+
apiRef.current.setState(state => {
|
|
304
|
+
const updatedTree = _extends({}, state.rows.tree);
|
|
305
|
+
const treeDepths = _extends({}, state.rows.treeDepths);
|
|
306
|
+
let rootLevelRemovals = 0;
|
|
307
|
+
if (failed.length === 0) {
|
|
308
|
+
const sourceParentNode = updatedTree[sourceNode.parent];
|
|
309
|
+
if (!sourceParentNode) {
|
|
310
|
+
const targetParentNode = updatedTree[targetNode.parent];
|
|
311
|
+
const targetIndex = targetParentNode.children.indexOf(targetNode.id);
|
|
312
|
+
const newTargetChildren = [...targetParentNode.children];
|
|
313
|
+
if (isLastChild) {
|
|
314
|
+
newTargetChildren.push(sourceNode.id);
|
|
315
|
+
} else {
|
|
316
|
+
newTargetChildren.splice(targetIndex, 0, sourceNode.id);
|
|
317
|
+
}
|
|
318
|
+
updatedTree[targetNode.parent] = _extends({}, targetParentNode, {
|
|
319
|
+
children: newTargetChildren
|
|
320
|
+
});
|
|
321
|
+
updatedTree[sourceNode.id] = _extends({}, sourceNode, {
|
|
322
|
+
parent: targetNode.parent
|
|
323
|
+
});
|
|
324
|
+
} else {
|
|
325
|
+
const updatedSourceParentChildren = sourceParentNode.children.filter(id => id !== sourceNode.id);
|
|
326
|
+
if (updatedSourceParentChildren.length === 0) {
|
|
327
|
+
const removedGroups = new Set();
|
|
328
|
+
removedGroups.add(sourceNode.parent);
|
|
329
|
+
const parentOfSourceParent = updatedTree[sourceNode.parent].parent;
|
|
330
|
+
if (parentOfSourceParent) {
|
|
331
|
+
rootLevelRemovals = rowReorderUtils.removeEmptyAncestors(parentOfSourceParent, updatedTree, removedGroups);
|
|
332
|
+
}
|
|
333
|
+
removedGroups.forEach(groupId => {
|
|
334
|
+
const group = updatedTree[groupId];
|
|
335
|
+
if (group && group.parent && updatedTree[group.parent]) {
|
|
336
|
+
const parent = updatedTree[group.parent];
|
|
337
|
+
updatedTree[group.parent] = _extends({}, parent, {
|
|
338
|
+
children: parent.children.filter(childId => childId !== groupId)
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
delete updatedTree[groupId];
|
|
342
|
+
});
|
|
343
|
+
} else {
|
|
344
|
+
updatedTree[sourceNode.parent] = _extends({}, sourceParentNode, {
|
|
345
|
+
children: updatedSourceParentChildren
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
const targetParentNode = updatedTree[targetNode.parent];
|
|
349
|
+
const sourceGroupNode = sourceNode;
|
|
350
|
+
const existingGroup = sourceGroupNode.groupingKey !== null && sourceGroupNode.groupingField !== null ? rowReorderUtils.findExistingGroupWithSameKey(targetParentNode, sourceGroupNode.groupingKey, sourceGroupNode.groupingField, updatedTree) : null;
|
|
351
|
+
if (existingGroup) {
|
|
352
|
+
const updatedExistingGroup = _extends({}, existingGroup, {
|
|
353
|
+
children: [...existingGroup.children, ...sourceGroupNode.children]
|
|
354
|
+
});
|
|
355
|
+
updatedTree[existingGroup.id] = updatedExistingGroup;
|
|
356
|
+
sourceGroupNode.children.forEach(childId => {
|
|
357
|
+
const childNode = updatedTree[childId];
|
|
358
|
+
if (childNode) {
|
|
359
|
+
updatedTree[childId] = _extends({}, childNode, {
|
|
360
|
+
parent: existingGroup.id
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
delete updatedTree[sourceNode.id];
|
|
365
|
+
} else {
|
|
449
366
|
const targetIndex = targetParentNode.children.indexOf(targetNode.id);
|
|
450
367
|
const newTargetChildren = [...targetParentNode.children];
|
|
451
368
|
if (isLastChild) {
|
|
@@ -459,77 +376,19 @@ export class CrossParentGroupOperation extends BaseReorderOperation {
|
|
|
459
376
|
updatedTree[sourceNode.id] = _extends({}, sourceNode, {
|
|
460
377
|
parent: targetNode.parent
|
|
461
378
|
});
|
|
462
|
-
} else {
|
|
463
|
-
const updatedSourceParentChildren = sourceParentNode.children.filter(id => id !== sourceNode.id);
|
|
464
|
-
if (updatedSourceParentChildren.length === 0) {
|
|
465
|
-
const removedGroups = new Set();
|
|
466
|
-
removedGroups.add(sourceNode.parent);
|
|
467
|
-
const parentOfSourceParent = updatedTree[sourceNode.parent].parent;
|
|
468
|
-
if (parentOfSourceParent) {
|
|
469
|
-
rootLevelRemovals = removeEmptyAncestors(parentOfSourceParent, updatedTree, removedGroups);
|
|
470
|
-
}
|
|
471
|
-
removedGroups.forEach(groupId => {
|
|
472
|
-
const group = updatedTree[groupId];
|
|
473
|
-
if (group && group.parent && updatedTree[group.parent]) {
|
|
474
|
-
const parent = updatedTree[group.parent];
|
|
475
|
-
updatedTree[group.parent] = _extends({}, parent, {
|
|
476
|
-
children: parent.children.filter(childId => childId !== groupId)
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
delete updatedTree[groupId];
|
|
480
|
-
});
|
|
481
|
-
} else {
|
|
482
|
-
updatedTree[sourceNode.parent] = _extends({}, sourceParentNode, {
|
|
483
|
-
children: updatedSourceParentChildren
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
const targetParentNode = updatedTree[targetNode.parent];
|
|
487
|
-
const sourceGroupNode = sourceNode;
|
|
488
|
-
const existingGroup = sourceGroupNode.groupingKey !== null && sourceGroupNode.groupingField !== null ? findExistingGroupWithSameKey(targetParentNode, sourceGroupNode.groupingKey, sourceGroupNode.groupingField, updatedTree) : null;
|
|
489
|
-
if (existingGroup) {
|
|
490
|
-
const updatedExistingGroup = _extends({}, existingGroup, {
|
|
491
|
-
children: [...existingGroup.children, ...sourceGroupNode.children]
|
|
492
|
-
});
|
|
493
|
-
updatedTree[existingGroup.id] = updatedExistingGroup;
|
|
494
|
-
sourceGroupNode.children.forEach(childId => {
|
|
495
|
-
const childNode = updatedTree[childId];
|
|
496
|
-
if (childNode) {
|
|
497
|
-
updatedTree[childId] = _extends({}, childNode, {
|
|
498
|
-
parent: existingGroup.id
|
|
499
|
-
});
|
|
500
|
-
}
|
|
501
|
-
});
|
|
502
|
-
delete updatedTree[sourceNode.id];
|
|
503
|
-
} else {
|
|
504
|
-
const targetIndex = targetParentNode.children.indexOf(targetNode.id);
|
|
505
|
-
const newTargetChildren = [...targetParentNode.children];
|
|
506
|
-
if (isLastChild) {
|
|
507
|
-
newTargetChildren.push(sourceNode.id);
|
|
508
|
-
} else {
|
|
509
|
-
newTargetChildren.splice(targetIndex, 0, sourceNode.id);
|
|
510
|
-
}
|
|
511
|
-
updatedTree[targetNode.parent] = _extends({}, targetParentNode, {
|
|
512
|
-
children: newTargetChildren
|
|
513
|
-
});
|
|
514
|
-
updatedTree[sourceNode.id] = _extends({}, sourceNode, {
|
|
515
|
-
parent: targetNode.parent
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
379
|
}
|
|
519
380
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
})
|
|
381
|
+
}
|
|
382
|
+
return _extends({}, state, {
|
|
383
|
+
rows: _extends({}, state.rows, {
|
|
384
|
+
totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals,
|
|
385
|
+
tree: updatedTree,
|
|
386
|
+
treeDepths
|
|
387
|
+
})
|
|
527
388
|
});
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
} finally {
|
|
532
|
-
apiRef.current.setLoading(false);
|
|
389
|
+
});
|
|
390
|
+
apiRef.current.updateRows(updates);
|
|
391
|
+
apiRef.current.publishEvent('rowsSet');
|
|
533
392
|
}
|
|
534
393
|
}
|
|
535
394
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { RowReorderExecutor, SameParentSwapOperation } from '@mui/x-data-grid-pro/internals';
|
|
2
|
+
import { CrossParentLeafOperation, CrossParentGroupOperation } from "./operations.js";
|
|
3
|
+
export const rowGroupingReorderExecutor = new RowReorderExecutor([new SameParentSwapOperation(), new CrossParentLeafOperation(), new CrossParentGroupOperation()]);
|
package/esm/hooks/features/rowReorder/{reorderValidator.js → rowGroupingReorderValidator.js}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { conditions } from
|
|
1
|
+
import { commonReorderConditions as conditions, RowReorderValidator } from '@mui/x-data-grid-pro/internals';
|
|
2
2
|
const validationRules = [
|
|
3
3
|
// ===== Basic invalid cases =====
|
|
4
4
|
{
|
|
5
5
|
name: 'same-position',
|
|
6
|
-
applies: ctx => ctx.
|
|
6
|
+
applies: ctx => ctx.sourceNode.id === ctx.targetNode.id,
|
|
7
7
|
isInvalid: () => true,
|
|
8
8
|
message: 'Source and target are the same'
|
|
9
9
|
}, {
|
|
@@ -93,24 +93,4 @@ const validationRules = [
|
|
|
93
93
|
},
|
|
94
94
|
message: 'Invalid depth configuration for leaf below group'
|
|
95
95
|
}];
|
|
96
|
-
class RowReorderValidator {
|
|
97
|
-
constructor(rules = validationRules) {
|
|
98
|
-
this.rules = rules;
|
|
99
|
-
}
|
|
100
|
-
addRule(rule) {
|
|
101
|
-
this.rules.push(rule);
|
|
102
|
-
}
|
|
103
|
-
removeRule(ruleName) {
|
|
104
|
-
this.rules = this.rules.filter(r => r.name !== ruleName);
|
|
105
|
-
}
|
|
106
|
-
validate(context) {
|
|
107
|
-
// Check all validation rules
|
|
108
|
-
for (const rule of this.rules) {
|
|
109
|
-
if (rule.applies(context) && rule.isInvalid(context)) {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
96
|
export const rowGroupingReorderValidator = new RowReorderValidator(validationRules);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { GridRowId } from '@mui/x-data-grid-pro';
|
|
2
1
|
import type { RefObject } from '@mui/x-internals/types';
|
|
3
2
|
import type { GridPrivateApiPremium } from "../../../models/gridApiPremium.js";
|
|
4
3
|
import type { DataGridPremiumProcessedProps } from "../../../models/dataGridPremiumProps.js";
|
|
5
|
-
export declare const useGridRowsOverridableMethods: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "processRowUpdate" | "onProcessRowUpdateError">) => {
|
|
6
|
-
setRowIndex: (rowId: GridRowId, targetIndex: number) => void;
|
|
4
|
+
export declare const useGridRowsOverridableMethods: (apiRef: RefObject<GridPrivateApiPremium>, props: Pick<DataGridPremiumProcessedProps, "processRowUpdate" | "onProcessRowUpdateError" | "treeData">) => {
|
|
5
|
+
setRowIndex: (rowId: import("@mui/x-data-grid").GridRowId, targetIndex: number) => void;
|
|
6
|
+
setRowPosition: (sourceRowId: import("@mui/x-data-grid").GridRowId, targetRowId: import("@mui/x-data-grid").GridRowId, position: import("@mui/x-data-grid/internals").RowReorderDropPosition) => void | Promise<void>;
|
|
7
7
|
};
|
|
@@ -1,28 +1,44 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { gridRowTreeSelector, gridExpandedSortedRowIdsSelector, gridRowNodeSelector, gridRowMaximumTreeDepthSelector } from '@mui/x-data-grid-pro';
|
|
3
|
-
import {
|
|
4
|
-
import { rowGroupingReorderExecutor } from "../rowReorder/
|
|
2
|
+
import { gridRowTreeSelector, gridExpandedSortedRowIdsSelector, gridRowNodeSelector, gridRowMaximumTreeDepthSelector, gridExpandedSortedRowIndexLookupSelector } from '@mui/x-data-grid-pro';
|
|
3
|
+
import { useGridRowsOverridableMethodsCommunity, useGridRowsOverridableMethodsPro, useGridSelector } from '@mui/x-data-grid-pro/internals';
|
|
4
|
+
import { rowGroupingReorderExecutor } from "../rowReorder/rowGroupingReorderExecutor.js";
|
|
5
5
|
export const useGridRowsOverridableMethods = (apiRef, props) => {
|
|
6
6
|
const {
|
|
7
7
|
processRowUpdate,
|
|
8
8
|
onProcessRowUpdateError
|
|
9
9
|
} = props;
|
|
10
10
|
const {
|
|
11
|
-
setRowIndex: setRowIndexPlain
|
|
11
|
+
setRowIndex: setRowIndexPlain,
|
|
12
|
+
setRowPosition: setRowPositionPlain
|
|
12
13
|
} = useGridRowsOverridableMethodsCommunity(apiRef);
|
|
14
|
+
const {
|
|
15
|
+
setRowIndex: setRowIndexTreeData,
|
|
16
|
+
setRowPosition: setRowPositionTreeData
|
|
17
|
+
} = useGridRowsOverridableMethodsPro(apiRef, props);
|
|
13
18
|
const flatTree = useGridSelector(apiRef, gridRowMaximumTreeDepthSelector) === 1;
|
|
14
|
-
const
|
|
19
|
+
const setRowPosition = React.useCallback(async (sourceRowId, targetRowId, position) => {
|
|
15
20
|
const sortedFilteredRowIds = gridExpandedSortedRowIdsSelector(apiRef);
|
|
16
21
|
const sortedFilteredRowIndexLookup = gridExpandedSortedRowIndexLookupSelector(apiRef);
|
|
17
22
|
const rowTree = gridRowTreeSelector(apiRef);
|
|
18
23
|
const sourceNode = gridRowNodeSelector(apiRef, sourceRowId);
|
|
24
|
+
const targetNode = gridRowNodeSelector(apiRef, targetRowId);
|
|
19
25
|
if (!sourceNode) {
|
|
20
26
|
throw new Error(`MUI X: No row with id #${sourceRowId} found.`);
|
|
21
27
|
}
|
|
28
|
+
if (!targetNode) {
|
|
29
|
+
throw new Error(`MUI X: No row with id #${targetRowId} found.`);
|
|
30
|
+
}
|
|
22
31
|
if (sourceNode.type === 'footer') {
|
|
23
32
|
throw new Error(`MUI X: The row reordering do not support reordering of footer rows.`);
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
// Get the target index from the targetRowId using the lookup selector
|
|
36
|
+
const targetIndexUnadjusted = sortedFilteredRowIndexLookup[targetRowId];
|
|
37
|
+
if (targetIndexUnadjusted === undefined) {
|
|
38
|
+
throw new Error(`MUI X: Target row with id #${targetRowId} not found in current view.`);
|
|
39
|
+
}
|
|
40
|
+
const targetIndex = position === 'below' ? targetIndexUnadjusted + 1 : targetIndexUnadjusted;
|
|
41
|
+
|
|
26
42
|
/**
|
|
27
43
|
* Row Grouping Reordering Use Cases
|
|
28
44
|
* =================================
|
|
@@ -40,6 +56,31 @@ export const useGridRowsOverridableMethods = (apiRef, props) => {
|
|
|
40
56
|
|
|
41
57
|
const executionContext = {
|
|
42
58
|
sourceRowId,
|
|
59
|
+
dropPosition: position,
|
|
60
|
+
placeholderIndex: targetIndex,
|
|
61
|
+
sortedFilteredRowIds,
|
|
62
|
+
sortedFilteredRowIndexLookup,
|
|
63
|
+
rowTree,
|
|
64
|
+
apiRef,
|
|
65
|
+
processRowUpdate,
|
|
66
|
+
onProcessRowUpdateError
|
|
67
|
+
};
|
|
68
|
+
return rowGroupingReorderExecutor.execute(executionContext);
|
|
69
|
+
}, [apiRef, processRowUpdate, onProcessRowUpdateError]);
|
|
70
|
+
const setRowIndex = React.useCallback(async (sourceRowId, targetOriginalIndex) => {
|
|
71
|
+
const sortedFilteredRowIds = gridExpandedSortedRowIdsSelector(apiRef);
|
|
72
|
+
const sortedFilteredRowIndexLookup = gridExpandedSortedRowIndexLookupSelector(apiRef);
|
|
73
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
74
|
+
const sourceNode = gridRowNodeSelector(apiRef, sourceRowId);
|
|
75
|
+
if (!sourceNode) {
|
|
76
|
+
throw new Error(`MUI X: No row with id #${sourceRowId} found.`);
|
|
77
|
+
}
|
|
78
|
+
if (sourceNode.type === 'footer') {
|
|
79
|
+
throw new Error(`MUI X: The row reordering do not support reordering of footer rows.`);
|
|
80
|
+
}
|
|
81
|
+
const executionContext = {
|
|
82
|
+
sourceRowId,
|
|
83
|
+
dropPosition: 'below',
|
|
43
84
|
placeholderIndex: targetOriginalIndex,
|
|
44
85
|
sortedFilteredRowIds,
|
|
45
86
|
sortedFilteredRowIndexLookup,
|
|
@@ -48,9 +89,22 @@ export const useGridRowsOverridableMethods = (apiRef, props) => {
|
|
|
48
89
|
processRowUpdate,
|
|
49
90
|
onProcessRowUpdateError
|
|
50
91
|
};
|
|
51
|
-
|
|
92
|
+
return rowGroupingReorderExecutor.execute(executionContext);
|
|
52
93
|
}, [apiRef, processRowUpdate, onProcessRowUpdateError]);
|
|
94
|
+
if (flatTree) {
|
|
95
|
+
return {
|
|
96
|
+
setRowIndex: setRowIndexPlain,
|
|
97
|
+
setRowPosition: setRowPositionPlain
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (props.treeData) {
|
|
101
|
+
return {
|
|
102
|
+
setRowIndex: setRowIndexTreeData,
|
|
103
|
+
setRowPosition: setRowPositionTreeData
|
|
104
|
+
};
|
|
105
|
+
}
|
|
53
106
|
return {
|
|
54
|
-
setRowIndex
|
|
107
|
+
setRowIndex,
|
|
108
|
+
setRowPosition
|
|
55
109
|
};
|
|
56
110
|
};
|
package/esm/index.js
CHANGED
|
@@ -86,6 +86,12 @@ class CellValueUpdater {
|
|
|
86
86
|
if (!row) {
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
// Check if the cell is editable using the API method, which respects the isCellEditable prop
|
|
91
|
+
const cellParams = apiRef.current.getCellParams(rowId, field);
|
|
92
|
+
if (!apiRef.current.isCellEditable(cellParams)) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
89
95
|
let parsedValue = pastedCellValue;
|
|
90
96
|
if (colDef.pastedValueParser) {
|
|
91
97
|
parsedValue = colDef.pastedValueParser(pastedCellValue, row, colDef, apiRef);
|