@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.
Files changed (47) hide show
  1. package/CHANGELOG.md +174 -0
  2. package/DataGridPremium/DataGridPremium.d.ts +1 -1
  3. package/DataGridPremium/DataGridPremium.js +27 -1
  4. package/DataGridPremium/useDataGridPremiumComponent.d.ts +1 -1
  5. package/esm/DataGridPremium/DataGridPremium.d.ts +1 -1
  6. package/esm/DataGridPremium/DataGridPremium.js +27 -1
  7. package/esm/DataGridPremium/useDataGridPremiumComponent.d.ts +1 -1
  8. package/esm/hooks/features/clipboard/useGridClipboardImport.js +6 -0
  9. package/esm/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
  10. package/esm/hooks/features/rowGrouping/useGridRowGrouping.js +21 -17
  11. package/esm/hooks/features/rowReorder/operations.d.ts +7 -27
  12. package/esm/hooks/features/rowReorder/operations.js +133 -274
  13. package/esm/hooks/features/rowReorder/rowGroupingReorderExecutor.d.ts +2 -0
  14. package/esm/hooks/features/rowReorder/rowGroupingReorderExecutor.js +3 -0
  15. package/esm/hooks/features/rowReorder/rowGroupingReorderValidator.d.ts +2 -0
  16. package/esm/hooks/features/rowReorder/{reorderValidator.js → rowGroupingReorderValidator.js} +2 -22
  17. package/esm/hooks/features/rows/useGridRowsOverridableMethods.d.ts +3 -3
  18. package/esm/hooks/features/rows/useGridRowsOverridableMethods.js +61 -7
  19. package/esm/index.js +1 -1
  20. package/hooks/features/clipboard/useGridClipboardImport.js +6 -0
  21. package/hooks/features/rowGrouping/useGridRowGrouping.d.ts +1 -1
  22. package/hooks/features/rowGrouping/useGridRowGrouping.js +20 -16
  23. package/hooks/features/rowReorder/operations.d.ts +7 -27
  24. package/hooks/features/rowReorder/operations.js +136 -279
  25. package/hooks/features/rowReorder/rowGroupingReorderExecutor.d.ts +2 -0
  26. package/hooks/features/rowReorder/rowGroupingReorderExecutor.js +9 -0
  27. package/hooks/features/rowReorder/rowGroupingReorderValidator.d.ts +2 -0
  28. package/hooks/features/rowReorder/rowGroupingReorderValidator.js +102 -0
  29. package/hooks/features/rows/useGridRowsOverridableMethods.d.ts +3 -3
  30. package/hooks/features/rows/useGridRowsOverridableMethods.js +61 -7
  31. package/index.js +1 -1
  32. package/package.json +5 -5
  33. package/esm/hooks/features/rowReorder/reorderExecutor.d.ts +0 -15
  34. package/esm/hooks/features/rowReorder/reorderExecutor.js +0 -25
  35. package/esm/hooks/features/rowReorder/reorderValidator.d.ts +0 -16
  36. package/esm/hooks/features/rowReorder/types.d.ts +0 -42
  37. package/esm/hooks/features/rowReorder/types.js +0 -1
  38. package/esm/hooks/features/rowReorder/utils.d.ts +0 -127
  39. package/esm/hooks/features/rowReorder/utils.js +0 -343
  40. package/hooks/features/rowReorder/reorderExecutor.d.ts +0 -15
  41. package/hooks/features/rowReorder/reorderExecutor.js +0 -31
  42. package/hooks/features/rowReorder/reorderValidator.d.ts +0 -16
  43. package/hooks/features/rowReorder/reorderValidator.js +0 -122
  44. package/hooks/features/rowReorder/types.d.ts +0 -42
  45. package/hooks/features/rowReorder/types.js +0 -5
  46. package/hooks/features/rowReorder/utils.d.ts +0 -127
  47. 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 { warnOnce } from '@mui/x-internals/warning';
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 commitStateUpdate = finalSourceRow => {
250
- apiRef.current.setState(state => {
251
- const updatedSourceChildren = sourceChildren.filter(rowId => rowId !== sourceRowId);
252
- const updatedTree = _extends({}, state.rows.tree);
253
- const removedGroups = new Set();
254
- let rootLevelRemovals = 0;
255
- if (updatedSourceChildren.length === 0) {
256
- removedGroups.add(sourceGroup.id);
257
- rootLevelRemovals = removeEmptyAncestors(sourceGroup.parent, updatedTree, removedGroups);
258
- }
259
- removedGroups.forEach(groupId => {
260
- const group = updatedTree[groupId];
261
- if (group && group.parent && updatedTree[group.parent]) {
262
- const parent = updatedTree[group.parent];
263
- updatedTree[group.parent] = _extends({}, parent, {
264
- children: parent.children.filter(childId => childId !== groupId)
265
- });
266
- }
267
- delete updatedTree[groupId];
268
- });
269
- if (!removedGroups.has(sourceGroup.id)) {
270
- updatedTree[sourceNode.parent] = _extends({}, sourceGroup, {
271
- children: updatedSourceChildren
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
- const updatedTargetChildren = isLastChild ? [...targetChildren, sourceRowId] : [...targetChildren.slice(0, targetIndex), sourceRowId, ...targetChildren.slice(targetIndex)];
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
- apiRef.current.updateRows([finalSourceRow]);
289
- apiRef.current.publishEvent('rowsSet');
290
- };
291
- if (processRowUpdate && !isDeepEqual(originalSourceRow, updatedSourceRow)) {
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
- } else {
313
- commitStateUpdate(updatedSourceRow);
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
- apiRef.current.setLoading(true);
434
- try {
435
- const {
436
- successful,
437
- failed,
438
- updates
439
- } = await updater.executeAll();
440
- if (successful.length > 0) {
441
- apiRef.current.setState(state => {
442
- const updatedTree = _extends({}, state.rows.tree);
443
- const treeDepths = _extends({}, state.rows.treeDepths);
444
- let rootLevelRemovals = 0;
445
- if (failed.length === 0) {
446
- const sourceParentNode = updatedTree[sourceNode.parent];
447
- if (!sourceParentNode) {
448
- const targetParentNode = updatedTree[targetNode.parent];
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
- return _extends({}, state, {
521
- rows: _extends({}, state.rows, {
522
- totalTopLevelRowCount: state.rows.totalTopLevelRowCount - rootLevelRemovals,
523
- tree: updatedTree,
524
- treeDepths
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
- apiRef.current.updateRows(updates);
529
- apiRef.current.publishEvent('rowsSet');
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,2 @@
1
+ import { RowReorderExecutor } from '@mui/x-data-grid-pro/internals';
2
+ export declare const rowGroupingReorderExecutor: RowReorderExecutor;
@@ -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()]);
@@ -0,0 +1,2 @@
1
+ import { RowReorderValidator } from '@mui/x-data-grid-pro/internals';
2
+ export declare const rowGroupingReorderValidator: RowReorderValidator;
@@ -1,9 +1,9 @@
1
- import { conditions } from "./utils.js";
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.sourceRowIndex === ctx.targetRowIndex,
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 { gridExpandedSortedRowIndexLookupSelector, useGridRowsOverridableMethods as useGridRowsOverridableMethodsCommunity, useGridSelector } from '@mui/x-data-grid-pro/internals';
4
- import { rowGroupingReorderExecutor } from "../rowReorder/reorderExecutor.js";
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 setRowIndex = React.useCallback(async (sourceRowId, targetOriginalIndex) => {
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
- await rowGroupingReorderExecutor.execute(executionContext);
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: flatTree ? setRowIndexPlain : setRowIndex
107
+ setRowIndex,
108
+ setRowPosition
55
109
  };
56
110
  };
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-premium v8.19.0
2
+ * @mui/x-data-grid-premium v8.21.0
3
3
  *
4
4
  * @license SEE LICENSE IN LICENSE
5
5
  * This source code is licensed under the SEE LICENSE IN LICENSE license found in the
@@ -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);