@headless-tree/core 1.6.0 → 1.6.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 +15 -0
- package/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +94 -67
- package/dist/index.mjs +94 -67
- package/package.json +1 -1
- package/src/features/async-data-loader/feature.ts +14 -8
- package/src/features/async-data-loader/types.ts +11 -3
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +81 -2
- package/src/features/drag-and-drop/feature.ts +72 -62
- package/src/features/drag-and-drop/types.ts +7 -0
- package/src/features/drag-and-drop/utils.ts +10 -4
- package/src/features/keyboard-drag-and-drop/feature.ts +1 -0
- package/src/features/prop-memoization/feature.ts +8 -0
- package/src/features/prop-memoization/types.ts +1 -0
- package/src/features/selection/feature.ts +13 -9
- package/src/features/selection/selection.spec.ts +4 -6
- package/src/features/tree/feature.ts +6 -2
- package/src/utils.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @headless-tree/core
|
|
2
2
|
|
|
3
|
+
## 1.6.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 39a8b44: Add skipUpdateTree parameter to `updateCachedChildrenIds` and `updateCachedData` in async tree loader
|
|
8
|
+
- 26ecc1b: Fixed an issue where dropping items inside a collapsed folder will make the tree become un-focusable until a new item is clicked with mouse again. This could break usage with keyboard-only drag operations.
|
|
9
|
+
- 0108b7a: Fixed a bug where some hotkeys (like up/down navigation, search and renaming) doesn't work after items are dragged within the tree (#179)
|
|
10
|
+
- ffd2619: Fixed an issue where `canDropForeignDragObject` was being called in `onDragOver` events without payload. `canDropForeignDragObject` should never be called in `onDragOver` events since there, browsers do not allow access to the data transfer payload. Now, `canDropForeignDragObject` is only called in onDrop events, and `canDragForeignDragObjectOver` is always called in `onDragOver` events.
|
|
11
|
+
|
|
12
|
+
## 1.6.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 4ddeaf3: Fixed behavior where shift-selecting an item with no previously selected or focused item would multiselect all items from the top to the clicked item. Now, shift-selecting an item with no previously clicked items will only select the clicked item (#176)
|
|
17
|
+
|
|
3
18
|
## 1.6.0
|
|
4
19
|
|
|
5
20
|
### Minor Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -68,6 +68,8 @@ type DragAndDropFeatureDef<T> = {
|
|
|
68
68
|
onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
|
|
69
69
|
/** When dragging for this many ms on a closed folder, the folder will automatically open. Set to zero to disable. */
|
|
70
70
|
openOnDropDelay?: number;
|
|
71
|
+
/** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
|
|
72
|
+
seperateDragHandle?: boolean;
|
|
71
73
|
};
|
|
72
74
|
treeInstance: {
|
|
73
75
|
getDragTarget: () => DragTarget<T> | null;
|
|
@@ -84,6 +86,9 @@ type DragAndDropFeatureDef<T> = {
|
|
|
84
86
|
isDragTargetAbove: () => boolean;
|
|
85
87
|
isDragTargetBelow: () => boolean;
|
|
86
88
|
isDraggingOver: () => boolean;
|
|
89
|
+
/** Note that `item.getProps()` already passes in all drag event handlers by default. Set `seperateDragHandle` to true to
|
|
90
|
+
* disable the default behavior and use this on the handler element instead. */
|
|
91
|
+
getDragHandleProps: () => Record<string, any>;
|
|
87
92
|
};
|
|
88
93
|
hotkeys: never;
|
|
89
94
|
};
|
|
@@ -329,9 +334,11 @@ type AsyncDataLoaderFeatureDef<T> = {
|
|
|
329
334
|
* @param optimistic If true, the item will not trigger a state update on `loadingItemChildrens`, and
|
|
330
335
|
* the tree will continue to display the old data until the new data has loaded. */
|
|
331
336
|
invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
|
|
332
|
-
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
338
|
+
* @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
339
|
+
updateCachedData: (data: T | undefined, skipUpdateTree?: boolean) => void;
|
|
340
|
+
/** @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
341
|
+
updateCachedChildrenIds: (childrenIds: string[], skipUpdateTree?: boolean) => void;
|
|
335
342
|
hasLoadedData: () => boolean;
|
|
336
343
|
isLoading: () => boolean;
|
|
337
344
|
};
|
|
@@ -420,6 +427,7 @@ interface PropMemoizationDataRef {
|
|
|
420
427
|
memo?: {
|
|
421
428
|
tree?: Record<string, any>;
|
|
422
429
|
item?: Record<string, any>;
|
|
430
|
+
drag?: Record<string, any>;
|
|
423
431
|
search?: Record<string, any>;
|
|
424
432
|
rename?: Record<string, any>;
|
|
425
433
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -68,6 +68,8 @@ type DragAndDropFeatureDef<T> = {
|
|
|
68
68
|
onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
|
|
69
69
|
/** When dragging for this many ms on a closed folder, the folder will automatically open. Set to zero to disable. */
|
|
70
70
|
openOnDropDelay?: number;
|
|
71
|
+
/** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
|
|
72
|
+
seperateDragHandle?: boolean;
|
|
71
73
|
};
|
|
72
74
|
treeInstance: {
|
|
73
75
|
getDragTarget: () => DragTarget<T> | null;
|
|
@@ -84,6 +86,9 @@ type DragAndDropFeatureDef<T> = {
|
|
|
84
86
|
isDragTargetAbove: () => boolean;
|
|
85
87
|
isDragTargetBelow: () => boolean;
|
|
86
88
|
isDraggingOver: () => boolean;
|
|
89
|
+
/** Note that `item.getProps()` already passes in all drag event handlers by default. Set `seperateDragHandle` to true to
|
|
90
|
+
* disable the default behavior and use this on the handler element instead. */
|
|
91
|
+
getDragHandleProps: () => Record<string, any>;
|
|
87
92
|
};
|
|
88
93
|
hotkeys: never;
|
|
89
94
|
};
|
|
@@ -329,9 +334,11 @@ type AsyncDataLoaderFeatureDef<T> = {
|
|
|
329
334
|
* @param optimistic If true, the item will not trigger a state update on `loadingItemChildrens`, and
|
|
330
335
|
* the tree will continue to display the old data until the new data has loaded. */
|
|
331
336
|
invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
|
|
332
|
-
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
338
|
+
* @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
339
|
+
updateCachedData: (data: T | undefined, skipUpdateTree?: boolean) => void;
|
|
340
|
+
/** @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
341
|
+
updateCachedChildrenIds: (childrenIds: string[], skipUpdateTree?: boolean) => void;
|
|
335
342
|
hasLoadedData: () => boolean;
|
|
336
343
|
isLoading: () => boolean;
|
|
337
344
|
};
|
|
@@ -420,6 +427,7 @@ interface PropMemoizationDataRef {
|
|
|
420
427
|
memo?: {
|
|
421
428
|
tree?: Record<string, any>;
|
|
422
429
|
item?: Record<string, any>;
|
|
430
|
+
drag?: Record<string, any>;
|
|
423
431
|
search?: Record<string, any>;
|
|
424
432
|
rename?: Record<string, any>;
|
|
425
433
|
};
|
package/dist/index.js
CHANGED
|
@@ -125,6 +125,7 @@ var poll = (fn, interval = 100, timeout = 1e3) => new Promise((resolve) => {
|
|
|
125
125
|
}, interval);
|
|
126
126
|
clear = setTimeout(() => {
|
|
127
127
|
clearInterval(i);
|
|
128
|
+
resolve();
|
|
128
129
|
}, timeout);
|
|
129
130
|
});
|
|
130
131
|
|
|
@@ -214,12 +215,16 @@ var treeFeature = {
|
|
|
214
215
|
},
|
|
215
216
|
updateDomFocus: ({ tree }) => {
|
|
216
217
|
setTimeout(() => __async(null, null, function* () {
|
|
217
|
-
var _a, _b;
|
|
218
|
+
var _a, _b, _c, _d, _e;
|
|
218
219
|
const focusedItem = tree.getFocusedItem();
|
|
219
220
|
(_b = (_a = tree.getConfig()).scrollToItem) == null ? void 0 : _b.call(_a, focusedItem);
|
|
220
|
-
yield poll(() => focusedItem.getElement() !== null, 20);
|
|
221
|
+
yield poll(() => focusedItem.getElement() !== null, 20, 500);
|
|
221
222
|
const focusedElement = focusedItem.getElement();
|
|
222
|
-
if (!focusedElement)
|
|
223
|
+
if (!focusedElement) {
|
|
224
|
+
(_c = tree.getItems()[0]) == null ? void 0 : _c.setFocused();
|
|
225
|
+
(_e = (_d = tree.getItems()[0]) == null ? void 0 : _d.getElement()) == null ? void 0 : _e.focus();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
223
228
|
focusedElement.focus();
|
|
224
229
|
}));
|
|
225
230
|
},
|
|
@@ -759,10 +764,15 @@ var selectionFeature = {
|
|
|
759
764
|
const { selectedItems } = tree.getState();
|
|
760
765
|
return selectedItems.includes(itemId);
|
|
761
766
|
},
|
|
762
|
-
selectUpTo: ({ tree, item }, ctrl) => {
|
|
767
|
+
selectUpTo: ({ tree, item, itemId }, ctrl) => {
|
|
763
768
|
const indexA = item.getItemMeta().index;
|
|
764
|
-
const
|
|
765
|
-
|
|
769
|
+
const dataRef = tree.getDataRef();
|
|
770
|
+
if (!dataRef.current.selectUpToAnchorId) {
|
|
771
|
+
dataRef.current.selectUpToAnchorId = itemId;
|
|
772
|
+
tree.setSelectedItems([itemId]);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
const itemB = tree.getItemInstance(dataRef.current.selectUpToAnchorId);
|
|
766
776
|
const indexB = itemB.getItemMeta().index;
|
|
767
777
|
const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA];
|
|
768
778
|
const newSelectedItems = tree.getItems().slice(a, b + 1).map((treeItem) => treeItem.getItemMeta().itemId);
|
|
@@ -783,7 +793,7 @@ var selectionFeature = {
|
|
|
783
793
|
item.select();
|
|
784
794
|
}
|
|
785
795
|
},
|
|
786
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
796
|
+
getProps: ({ tree, item, itemId, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
787
797
|
"aria-selected": item.isSelected() ? "true" : "false",
|
|
788
798
|
onClick: (e) => {
|
|
789
799
|
var _a, _b;
|
|
@@ -792,10 +802,10 @@ var selectionFeature = {
|
|
|
792
802
|
} else if (e.ctrlKey || e.metaKey) {
|
|
793
803
|
item.toggleSelect();
|
|
794
804
|
} else {
|
|
795
|
-
tree.setSelectedItems([
|
|
805
|
+
tree.setSelectedItems([itemId]);
|
|
796
806
|
}
|
|
797
807
|
if (!e.shiftKey) {
|
|
798
|
-
tree.getDataRef().current.selectUpToAnchorId =
|
|
808
|
+
tree.getDataRef().current.selectUpToAnchorId = itemId;
|
|
799
809
|
}
|
|
800
810
|
(_b = (_a = prev == null ? void 0 : prev()) == null ? void 0 : _a.onClick) == null ? void 0 : _b.call(_a, e);
|
|
801
811
|
}
|
|
@@ -1269,15 +1279,17 @@ var asyncDataLoaderFeature = {
|
|
|
1269
1279
|
}
|
|
1270
1280
|
yield loadChildrenIds(tree, itemId);
|
|
1271
1281
|
}),
|
|
1272
|
-
updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1282
|
+
updateCachedChildrenIds: ({ tree, itemId }, childrenIds, skipUpdateTree) => {
|
|
1283
|
+
getDataRef(tree).current.childrenIds[itemId] = childrenIds;
|
|
1284
|
+
if (!skipUpdateTree) {
|
|
1285
|
+
tree.rebuildTree();
|
|
1286
|
+
}
|
|
1276
1287
|
},
|
|
1277
|
-
updateCachedData: ({ tree, itemId }, data) => {
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1288
|
+
updateCachedData: ({ tree, itemId }, data, skipUpdateTree) => {
|
|
1289
|
+
getDataRef(tree).current.itemData[itemId] = data;
|
|
1290
|
+
if (!skipUpdateTree) {
|
|
1291
|
+
tree.rebuildTree();
|
|
1292
|
+
}
|
|
1281
1293
|
},
|
|
1282
1294
|
hasLoadedData: ({ tree, itemId }) => {
|
|
1283
1295
|
const dataRef = tree.getDataRef();
|
|
@@ -1444,15 +1456,16 @@ var getReparentTarget = (item, reparentLevel, draggedItems) => {
|
|
|
1444
1456
|
dragLineLevel: reparentLevel
|
|
1445
1457
|
};
|
|
1446
1458
|
};
|
|
1447
|
-
var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) => {
|
|
1459
|
+
var getDragTarget = (e, item, tree, hasDataTransferPayload, canReorder = tree.getConfig().canReorder) => {
|
|
1448
1460
|
var _a;
|
|
1461
|
+
const dataTransfer = hasDataTransferPayload ? e.dataTransfer : null;
|
|
1449
1462
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1450
1463
|
const itemMeta = item.getItemMeta();
|
|
1451
1464
|
const parent = item.getParent();
|
|
1452
1465
|
const itemTarget = { item };
|
|
1453
1466
|
const parentTarget = parent ? { item: parent } : null;
|
|
1454
|
-
const canBecomeSibling = parentTarget && canDrop(
|
|
1455
|
-
const canMakeChild = canDrop(
|
|
1467
|
+
const canBecomeSibling = parentTarget && canDrop(dataTransfer, parentTarget, tree);
|
|
1468
|
+
const canMakeChild = canDrop(dataTransfer, itemTarget, tree);
|
|
1456
1469
|
const placement = getTargetPlacement(e, item, tree, canMakeChild);
|
|
1457
1470
|
if (!canReorder && parent && canBecomeSibling && placement.type !== 2 /* MakeChild */) {
|
|
1458
1471
|
if (draggedItems == null ? void 0 : draggedItems.some((item2) => item2.isDescendentOf(parent.getId()))) {
|
|
@@ -1461,7 +1474,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1461
1474
|
return parentTarget;
|
|
1462
1475
|
}
|
|
1463
1476
|
if (!canReorder && parent && !canBecomeSibling) {
|
|
1464
|
-
return getDragTarget(e, parent, tree, false);
|
|
1477
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1465
1478
|
}
|
|
1466
1479
|
if (!parent) {
|
|
1467
1480
|
return itemTarget;
|
|
@@ -1470,7 +1483,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1470
1483
|
return itemTarget;
|
|
1471
1484
|
}
|
|
1472
1485
|
if (!canBecomeSibling) {
|
|
1473
|
-
return getDragTarget(e, parent, tree, false);
|
|
1486
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1474
1487
|
}
|
|
1475
1488
|
if (placement.type === 3 /* Reparent */) {
|
|
1476
1489
|
return getReparentTarget(item, placement.reparentLevel, draggedItems);
|
|
@@ -1607,36 +1620,8 @@ var dragAndDropFeature = {
|
|
|
1607
1620
|
}
|
|
1608
1621
|
},
|
|
1609
1622
|
itemInstance: {
|
|
1610
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1611
|
-
draggable: true,
|
|
1623
|
+
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues(__spreadValues({}, prev == null ? void 0 : prev()), tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()), {
|
|
1612
1624
|
onDragEnter: (e) => e.preventDefault(),
|
|
1613
|
-
onDragStart: (e) => {
|
|
1614
|
-
var _a, _b, _c, _d;
|
|
1615
|
-
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1616
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1617
|
-
const config = tree.getConfig();
|
|
1618
|
-
if (!selectedItems.includes(item)) {
|
|
1619
|
-
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1620
|
-
}
|
|
1621
|
-
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1622
|
-
e.preventDefault();
|
|
1623
|
-
return;
|
|
1624
|
-
}
|
|
1625
|
-
if (config.setDragImage) {
|
|
1626
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1627
|
-
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1628
|
-
}
|
|
1629
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1630
|
-
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1631
|
-
e.dataTransfer.setData(format, data);
|
|
1632
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1633
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1634
|
-
}
|
|
1635
|
-
tree.applySubStateUpdate("dnd", {
|
|
1636
|
-
draggedItems: items,
|
|
1637
|
-
draggingOverItem: tree.getFocusedItem()
|
|
1638
|
-
});
|
|
1639
|
-
},
|
|
1640
1625
|
onDragOver: (e) => {
|
|
1641
1626
|
var _a, _b, _c;
|
|
1642
1627
|
e.stopPropagation();
|
|
@@ -1652,12 +1637,12 @@ var dragAndDropFeature = {
|
|
|
1652
1637
|
dataRef.current.lastDragCode = nextDragCode;
|
|
1653
1638
|
dataRef.current.lastDragEnter = Date.now();
|
|
1654
1639
|
handleAutoOpenFolder(dataRef, tree, item, placement);
|
|
1655
|
-
const target = getDragTarget(e, item, tree);
|
|
1640
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1656
1641
|
if (!((_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems) && (!e.dataTransfer || !((_c = (_b = tree.getConfig()).canDragForeignDragObjectOver) == null ? void 0 : _c.call(_b, e.dataTransfer, target)))) {
|
|
1657
1642
|
dataRef.current.lastAllowDrop = false;
|
|
1658
1643
|
return;
|
|
1659
1644
|
}
|
|
1660
|
-
if (!canDrop(
|
|
1645
|
+
if (!canDrop(null, target, tree)) {
|
|
1661
1646
|
dataRef.current.lastAllowDrop = false;
|
|
1662
1647
|
return;
|
|
1663
1648
|
}
|
|
@@ -1680,24 +1665,11 @@ var dragAndDropFeature = {
|
|
|
1680
1665
|
}));
|
|
1681
1666
|
}, 100);
|
|
1682
1667
|
},
|
|
1683
|
-
onDragEnd: (e) => {
|
|
1684
|
-
var _a, _b;
|
|
1685
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1686
|
-
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1687
|
-
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1688
|
-
return;
|
|
1689
|
-
}
|
|
1690
|
-
const target = getDragTarget(e, item, tree);
|
|
1691
|
-
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1692
|
-
return;
|
|
1693
|
-
}
|
|
1694
|
-
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1695
|
-
},
|
|
1696
1668
|
onDrop: (e) => __async(null, null, function* () {
|
|
1697
1669
|
var _a, _b, _c;
|
|
1698
1670
|
e.stopPropagation();
|
|
1699
1671
|
const dataRef = tree.getDataRef();
|
|
1700
|
-
const target = getDragTarget(e, item, tree);
|
|
1672
|
+
const target = getDragTarget(e, item, tree, true);
|
|
1701
1673
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1702
1674
|
const isValidDrop = canDrop(e.dataTransfer, target, tree);
|
|
1703
1675
|
tree.applySubStateUpdate("dnd", {
|
|
@@ -1713,11 +1685,57 @@ var dragAndDropFeature = {
|
|
|
1713
1685
|
dataRef.current.lastDragCode = void 0;
|
|
1714
1686
|
if (draggedItems) {
|
|
1715
1687
|
yield (_b = config.onDrop) == null ? void 0 : _b.call(config, draggedItems, target);
|
|
1688
|
+
draggedItems[0].setFocused();
|
|
1716
1689
|
} else if (e.dataTransfer) {
|
|
1717
1690
|
yield (_c = config.onDropForeignDragObject) == null ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
1718
1691
|
}
|
|
1692
|
+
tree.applySubStateUpdate("dnd", null);
|
|
1693
|
+
tree.updateDomFocus();
|
|
1719
1694
|
})
|
|
1720
1695
|
}),
|
|
1696
|
+
getDragHandleProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1697
|
+
draggable: true,
|
|
1698
|
+
onDragStart: (e) => {
|
|
1699
|
+
var _a, _b, _c, _d;
|
|
1700
|
+
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1701
|
+
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1702
|
+
const config = tree.getConfig();
|
|
1703
|
+
if (!selectedItems.includes(item)) {
|
|
1704
|
+
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1705
|
+
}
|
|
1706
|
+
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1707
|
+
e.preventDefault();
|
|
1708
|
+
return;
|
|
1709
|
+
}
|
|
1710
|
+
if (config.setDragImage) {
|
|
1711
|
+
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1712
|
+
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1713
|
+
}
|
|
1714
|
+
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1715
|
+
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1716
|
+
e.dataTransfer.setData(format, data);
|
|
1717
|
+
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1718
|
+
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1719
|
+
}
|
|
1720
|
+
tree.applySubStateUpdate("dnd", {
|
|
1721
|
+
draggedItems: items,
|
|
1722
|
+
draggingOverItem: tree.getFocusedItem()
|
|
1723
|
+
});
|
|
1724
|
+
},
|
|
1725
|
+
onDragEnd: (e) => {
|
|
1726
|
+
var _a, _b;
|
|
1727
|
+
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1728
|
+
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1729
|
+
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1730
|
+
return;
|
|
1731
|
+
}
|
|
1732
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1733
|
+
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1737
|
+
}
|
|
1738
|
+
}),
|
|
1721
1739
|
isDragTarget: ({ tree, item }) => {
|
|
1722
1740
|
const target = tree.getDragTarget();
|
|
1723
1741
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -1941,6 +1959,7 @@ var keyboardDragAndDropFeature = {
|
|
|
1941
1959
|
} else if (dataTransfer) {
|
|
1942
1960
|
yield (_d = config.onDropForeignDragObject) == null ? void 0 : _d.call(config, dataTransfer, target);
|
|
1943
1961
|
}
|
|
1962
|
+
tree.updateDomFocus();
|
|
1944
1963
|
tree.applySubStateUpdate(
|
|
1945
1964
|
"assistiveDndState",
|
|
1946
1965
|
3 /* Completed */
|
|
@@ -2291,6 +2310,14 @@ var propMemoizationFeature = {
|
|
|
2291
2310
|
(_e = (_d = dataRef.current.memo).item) != null ? _e : _d.item = {};
|
|
2292
2311
|
return memoize(props, dataRef.current.memo.item);
|
|
2293
2312
|
},
|
|
2313
|
+
getDragHandleProps: ({ item, prev }) => {
|
|
2314
|
+
var _a, _b, _c, _d, _e;
|
|
2315
|
+
const dataRef = item.getDataRef();
|
|
2316
|
+
const props = (_a = prev == null ? void 0 : prev()) != null ? _a : {};
|
|
2317
|
+
(_c = (_b = dataRef.current).memo) != null ? _c : _b.memo = {};
|
|
2318
|
+
(_e = (_d = dataRef.current.memo).drag) != null ? _e : _d.drag = {};
|
|
2319
|
+
return memoize(props, dataRef.current.memo.drag);
|
|
2320
|
+
},
|
|
2294
2321
|
getRenameInputProps: ({ item, prev }) => {
|
|
2295
2322
|
var _a, _b, _c, _d, _e;
|
|
2296
2323
|
const dataRef = item.getDataRef();
|
package/dist/index.mjs
CHANGED
|
@@ -81,6 +81,7 @@ var poll = (fn, interval = 100, timeout = 1e3) => new Promise((resolve) => {
|
|
|
81
81
|
}, interval);
|
|
82
82
|
clear = setTimeout(() => {
|
|
83
83
|
clearInterval(i);
|
|
84
|
+
resolve();
|
|
84
85
|
}, timeout);
|
|
85
86
|
});
|
|
86
87
|
|
|
@@ -170,12 +171,16 @@ var treeFeature = {
|
|
|
170
171
|
},
|
|
171
172
|
updateDomFocus: ({ tree }) => {
|
|
172
173
|
setTimeout(() => __async(null, null, function* () {
|
|
173
|
-
var _a, _b;
|
|
174
|
+
var _a, _b, _c, _d, _e;
|
|
174
175
|
const focusedItem = tree.getFocusedItem();
|
|
175
176
|
(_b = (_a = tree.getConfig()).scrollToItem) == null ? void 0 : _b.call(_a, focusedItem);
|
|
176
|
-
yield poll(() => focusedItem.getElement() !== null, 20);
|
|
177
|
+
yield poll(() => focusedItem.getElement() !== null, 20, 500);
|
|
177
178
|
const focusedElement = focusedItem.getElement();
|
|
178
|
-
if (!focusedElement)
|
|
179
|
+
if (!focusedElement) {
|
|
180
|
+
(_c = tree.getItems()[0]) == null ? void 0 : _c.setFocused();
|
|
181
|
+
(_e = (_d = tree.getItems()[0]) == null ? void 0 : _d.getElement()) == null ? void 0 : _e.focus();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
179
184
|
focusedElement.focus();
|
|
180
185
|
}));
|
|
181
186
|
},
|
|
@@ -715,10 +720,15 @@ var selectionFeature = {
|
|
|
715
720
|
const { selectedItems } = tree.getState();
|
|
716
721
|
return selectedItems.includes(itemId);
|
|
717
722
|
},
|
|
718
|
-
selectUpTo: ({ tree, item }, ctrl) => {
|
|
723
|
+
selectUpTo: ({ tree, item, itemId }, ctrl) => {
|
|
719
724
|
const indexA = item.getItemMeta().index;
|
|
720
|
-
const
|
|
721
|
-
|
|
725
|
+
const dataRef = tree.getDataRef();
|
|
726
|
+
if (!dataRef.current.selectUpToAnchorId) {
|
|
727
|
+
dataRef.current.selectUpToAnchorId = itemId;
|
|
728
|
+
tree.setSelectedItems([itemId]);
|
|
729
|
+
return;
|
|
730
|
+
}
|
|
731
|
+
const itemB = tree.getItemInstance(dataRef.current.selectUpToAnchorId);
|
|
722
732
|
const indexB = itemB.getItemMeta().index;
|
|
723
733
|
const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA];
|
|
724
734
|
const newSelectedItems = tree.getItems().slice(a, b + 1).map((treeItem) => treeItem.getItemMeta().itemId);
|
|
@@ -739,7 +749,7 @@ var selectionFeature = {
|
|
|
739
749
|
item.select();
|
|
740
750
|
}
|
|
741
751
|
},
|
|
742
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
752
|
+
getProps: ({ tree, item, itemId, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
743
753
|
"aria-selected": item.isSelected() ? "true" : "false",
|
|
744
754
|
onClick: (e) => {
|
|
745
755
|
var _a, _b;
|
|
@@ -748,10 +758,10 @@ var selectionFeature = {
|
|
|
748
758
|
} else if (e.ctrlKey || e.metaKey) {
|
|
749
759
|
item.toggleSelect();
|
|
750
760
|
} else {
|
|
751
|
-
tree.setSelectedItems([
|
|
761
|
+
tree.setSelectedItems([itemId]);
|
|
752
762
|
}
|
|
753
763
|
if (!e.shiftKey) {
|
|
754
|
-
tree.getDataRef().current.selectUpToAnchorId =
|
|
764
|
+
tree.getDataRef().current.selectUpToAnchorId = itemId;
|
|
755
765
|
}
|
|
756
766
|
(_b = (_a = prev == null ? void 0 : prev()) == null ? void 0 : _a.onClick) == null ? void 0 : _b.call(_a, e);
|
|
757
767
|
}
|
|
@@ -1225,15 +1235,17 @@ var asyncDataLoaderFeature = {
|
|
|
1225
1235
|
}
|
|
1226
1236
|
yield loadChildrenIds(tree, itemId);
|
|
1227
1237
|
}),
|
|
1228
|
-
updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1238
|
+
updateCachedChildrenIds: ({ tree, itemId }, childrenIds, skipUpdateTree) => {
|
|
1239
|
+
getDataRef(tree).current.childrenIds[itemId] = childrenIds;
|
|
1240
|
+
if (!skipUpdateTree) {
|
|
1241
|
+
tree.rebuildTree();
|
|
1242
|
+
}
|
|
1232
1243
|
},
|
|
1233
|
-
updateCachedData: ({ tree, itemId }, data) => {
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1244
|
+
updateCachedData: ({ tree, itemId }, data, skipUpdateTree) => {
|
|
1245
|
+
getDataRef(tree).current.itemData[itemId] = data;
|
|
1246
|
+
if (!skipUpdateTree) {
|
|
1247
|
+
tree.rebuildTree();
|
|
1248
|
+
}
|
|
1237
1249
|
},
|
|
1238
1250
|
hasLoadedData: ({ tree, itemId }) => {
|
|
1239
1251
|
const dataRef = tree.getDataRef();
|
|
@@ -1400,15 +1412,16 @@ var getReparentTarget = (item, reparentLevel, draggedItems) => {
|
|
|
1400
1412
|
dragLineLevel: reparentLevel
|
|
1401
1413
|
};
|
|
1402
1414
|
};
|
|
1403
|
-
var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) => {
|
|
1415
|
+
var getDragTarget = (e, item, tree, hasDataTransferPayload, canReorder = tree.getConfig().canReorder) => {
|
|
1404
1416
|
var _a;
|
|
1417
|
+
const dataTransfer = hasDataTransferPayload ? e.dataTransfer : null;
|
|
1405
1418
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1406
1419
|
const itemMeta = item.getItemMeta();
|
|
1407
1420
|
const parent = item.getParent();
|
|
1408
1421
|
const itemTarget = { item };
|
|
1409
1422
|
const parentTarget = parent ? { item: parent } : null;
|
|
1410
|
-
const canBecomeSibling = parentTarget && canDrop(
|
|
1411
|
-
const canMakeChild = canDrop(
|
|
1423
|
+
const canBecomeSibling = parentTarget && canDrop(dataTransfer, parentTarget, tree);
|
|
1424
|
+
const canMakeChild = canDrop(dataTransfer, itemTarget, tree);
|
|
1412
1425
|
const placement = getTargetPlacement(e, item, tree, canMakeChild);
|
|
1413
1426
|
if (!canReorder && parent && canBecomeSibling && placement.type !== 2 /* MakeChild */) {
|
|
1414
1427
|
if (draggedItems == null ? void 0 : draggedItems.some((item2) => item2.isDescendentOf(parent.getId()))) {
|
|
@@ -1417,7 +1430,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1417
1430
|
return parentTarget;
|
|
1418
1431
|
}
|
|
1419
1432
|
if (!canReorder && parent && !canBecomeSibling) {
|
|
1420
|
-
return getDragTarget(e, parent, tree, false);
|
|
1433
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1421
1434
|
}
|
|
1422
1435
|
if (!parent) {
|
|
1423
1436
|
return itemTarget;
|
|
@@ -1426,7 +1439,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1426
1439
|
return itemTarget;
|
|
1427
1440
|
}
|
|
1428
1441
|
if (!canBecomeSibling) {
|
|
1429
|
-
return getDragTarget(e, parent, tree, false);
|
|
1442
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1430
1443
|
}
|
|
1431
1444
|
if (placement.type === 3 /* Reparent */) {
|
|
1432
1445
|
return getReparentTarget(item, placement.reparentLevel, draggedItems);
|
|
@@ -1563,36 +1576,8 @@ var dragAndDropFeature = {
|
|
|
1563
1576
|
}
|
|
1564
1577
|
},
|
|
1565
1578
|
itemInstance: {
|
|
1566
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1567
|
-
draggable: true,
|
|
1579
|
+
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues(__spreadValues({}, prev == null ? void 0 : prev()), tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()), {
|
|
1568
1580
|
onDragEnter: (e) => e.preventDefault(),
|
|
1569
|
-
onDragStart: (e) => {
|
|
1570
|
-
var _a, _b, _c, _d;
|
|
1571
|
-
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1572
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1573
|
-
const config = tree.getConfig();
|
|
1574
|
-
if (!selectedItems.includes(item)) {
|
|
1575
|
-
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1576
|
-
}
|
|
1577
|
-
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1578
|
-
e.preventDefault();
|
|
1579
|
-
return;
|
|
1580
|
-
}
|
|
1581
|
-
if (config.setDragImage) {
|
|
1582
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1583
|
-
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1584
|
-
}
|
|
1585
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1586
|
-
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1587
|
-
e.dataTransfer.setData(format, data);
|
|
1588
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1589
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1590
|
-
}
|
|
1591
|
-
tree.applySubStateUpdate("dnd", {
|
|
1592
|
-
draggedItems: items,
|
|
1593
|
-
draggingOverItem: tree.getFocusedItem()
|
|
1594
|
-
});
|
|
1595
|
-
},
|
|
1596
1581
|
onDragOver: (e) => {
|
|
1597
1582
|
var _a, _b, _c;
|
|
1598
1583
|
e.stopPropagation();
|
|
@@ -1608,12 +1593,12 @@ var dragAndDropFeature = {
|
|
|
1608
1593
|
dataRef.current.lastDragCode = nextDragCode;
|
|
1609
1594
|
dataRef.current.lastDragEnter = Date.now();
|
|
1610
1595
|
handleAutoOpenFolder(dataRef, tree, item, placement);
|
|
1611
|
-
const target = getDragTarget(e, item, tree);
|
|
1596
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1612
1597
|
if (!((_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems) && (!e.dataTransfer || !((_c = (_b = tree.getConfig()).canDragForeignDragObjectOver) == null ? void 0 : _c.call(_b, e.dataTransfer, target)))) {
|
|
1613
1598
|
dataRef.current.lastAllowDrop = false;
|
|
1614
1599
|
return;
|
|
1615
1600
|
}
|
|
1616
|
-
if (!canDrop(
|
|
1601
|
+
if (!canDrop(null, target, tree)) {
|
|
1617
1602
|
dataRef.current.lastAllowDrop = false;
|
|
1618
1603
|
return;
|
|
1619
1604
|
}
|
|
@@ -1636,24 +1621,11 @@ var dragAndDropFeature = {
|
|
|
1636
1621
|
}));
|
|
1637
1622
|
}, 100);
|
|
1638
1623
|
},
|
|
1639
|
-
onDragEnd: (e) => {
|
|
1640
|
-
var _a, _b;
|
|
1641
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1642
|
-
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1643
|
-
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1644
|
-
return;
|
|
1645
|
-
}
|
|
1646
|
-
const target = getDragTarget(e, item, tree);
|
|
1647
|
-
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1648
|
-
return;
|
|
1649
|
-
}
|
|
1650
|
-
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1651
|
-
},
|
|
1652
1624
|
onDrop: (e) => __async(null, null, function* () {
|
|
1653
1625
|
var _a, _b, _c;
|
|
1654
1626
|
e.stopPropagation();
|
|
1655
1627
|
const dataRef = tree.getDataRef();
|
|
1656
|
-
const target = getDragTarget(e, item, tree);
|
|
1628
|
+
const target = getDragTarget(e, item, tree, true);
|
|
1657
1629
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1658
1630
|
const isValidDrop = canDrop(e.dataTransfer, target, tree);
|
|
1659
1631
|
tree.applySubStateUpdate("dnd", {
|
|
@@ -1669,11 +1641,57 @@ var dragAndDropFeature = {
|
|
|
1669
1641
|
dataRef.current.lastDragCode = void 0;
|
|
1670
1642
|
if (draggedItems) {
|
|
1671
1643
|
yield (_b = config.onDrop) == null ? void 0 : _b.call(config, draggedItems, target);
|
|
1644
|
+
draggedItems[0].setFocused();
|
|
1672
1645
|
} else if (e.dataTransfer) {
|
|
1673
1646
|
yield (_c = config.onDropForeignDragObject) == null ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
1674
1647
|
}
|
|
1648
|
+
tree.applySubStateUpdate("dnd", null);
|
|
1649
|
+
tree.updateDomFocus();
|
|
1675
1650
|
})
|
|
1676
1651
|
}),
|
|
1652
|
+
getDragHandleProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1653
|
+
draggable: true,
|
|
1654
|
+
onDragStart: (e) => {
|
|
1655
|
+
var _a, _b, _c, _d;
|
|
1656
|
+
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1657
|
+
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1658
|
+
const config = tree.getConfig();
|
|
1659
|
+
if (!selectedItems.includes(item)) {
|
|
1660
|
+
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1661
|
+
}
|
|
1662
|
+
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1663
|
+
e.preventDefault();
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
if (config.setDragImage) {
|
|
1667
|
+
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1668
|
+
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1669
|
+
}
|
|
1670
|
+
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1671
|
+
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1672
|
+
e.dataTransfer.setData(format, data);
|
|
1673
|
+
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1674
|
+
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1675
|
+
}
|
|
1676
|
+
tree.applySubStateUpdate("dnd", {
|
|
1677
|
+
draggedItems: items,
|
|
1678
|
+
draggingOverItem: tree.getFocusedItem()
|
|
1679
|
+
});
|
|
1680
|
+
},
|
|
1681
|
+
onDragEnd: (e) => {
|
|
1682
|
+
var _a, _b;
|
|
1683
|
+
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1684
|
+
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1685
|
+
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1686
|
+
return;
|
|
1687
|
+
}
|
|
1688
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1689
|
+
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1692
|
+
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1693
|
+
}
|
|
1694
|
+
}),
|
|
1677
1695
|
isDragTarget: ({ tree, item }) => {
|
|
1678
1696
|
const target = tree.getDragTarget();
|
|
1679
1697
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -1897,6 +1915,7 @@ var keyboardDragAndDropFeature = {
|
|
|
1897
1915
|
} else if (dataTransfer) {
|
|
1898
1916
|
yield (_d = config.onDropForeignDragObject) == null ? void 0 : _d.call(config, dataTransfer, target);
|
|
1899
1917
|
}
|
|
1918
|
+
tree.updateDomFocus();
|
|
1900
1919
|
tree.applySubStateUpdate(
|
|
1901
1920
|
"assistiveDndState",
|
|
1902
1921
|
3 /* Completed */
|
|
@@ -2247,6 +2266,14 @@ var propMemoizationFeature = {
|
|
|
2247
2266
|
(_e = (_d = dataRef.current.memo).item) != null ? _e : _d.item = {};
|
|
2248
2267
|
return memoize(props, dataRef.current.memo.item);
|
|
2249
2268
|
},
|
|
2269
|
+
getDragHandleProps: ({ item, prev }) => {
|
|
2270
|
+
var _a, _b, _c, _d, _e;
|
|
2271
|
+
const dataRef = item.getDataRef();
|
|
2272
|
+
const props = (_a = prev == null ? void 0 : prev()) != null ? _a : {};
|
|
2273
|
+
(_c = (_b = dataRef.current).memo) != null ? _c : _b.memo = {};
|
|
2274
|
+
(_e = (_d = dataRef.current.memo).drag) != null ? _e : _d.drag = {};
|
|
2275
|
+
return memoize(props, dataRef.current.memo.drag);
|
|
2276
|
+
},
|
|
2250
2277
|
getRenameInputProps: ({ item, prev }) => {
|
|
2251
2278
|
var _a, _b, _c, _d, _e;
|
|
2252
2279
|
const dataRef = item.getDataRef();
|
package/package.json
CHANGED
|
@@ -180,15 +180,21 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
|
|
|
180
180
|
}
|
|
181
181
|
await loadChildrenIds(tree, itemId);
|
|
182
182
|
},
|
|
183
|
-
updateCachedChildrenIds: (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
updateCachedChildrenIds: (
|
|
184
|
+
{ tree, itemId },
|
|
185
|
+
childrenIds,
|
|
186
|
+
skipUpdateTree,
|
|
187
|
+
) => {
|
|
188
|
+
getDataRef(tree).current.childrenIds[itemId] = childrenIds;
|
|
189
|
+
if (!skipUpdateTree) {
|
|
190
|
+
tree.rebuildTree();
|
|
191
|
+
}
|
|
187
192
|
},
|
|
188
|
-
updateCachedData: ({ tree, itemId }, data) => {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
193
|
+
updateCachedData: ({ tree, itemId }, data, skipUpdateTree) => {
|
|
194
|
+
getDataRef(tree).current.itemData[itemId] = data;
|
|
195
|
+
if (!skipUpdateTree) {
|
|
196
|
+
tree.rebuildTree();
|
|
197
|
+
}
|
|
192
198
|
},
|
|
193
199
|
hasLoadedData: ({ tree, itemId }) => {
|
|
194
200
|
const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
|
|
@@ -39,6 +39,7 @@ export type AsyncDataLoaderFeatureDef<T> = {
|
|
|
39
39
|
waitForItemChildrenLoaded: (itemId: string) => Promise<void>;
|
|
40
40
|
loadItemData: (itemId: string) => Promise<T>;
|
|
41
41
|
loadChildrenIds: (itemId: string) => Promise<string[]>;
|
|
42
|
+
|
|
42
43
|
/* idea: recursiveLoadItems: (itemId: string, cancelToken?: { current: boolean }, onLoad: (itemIds: string[]) => void) => Promise<T[]> */
|
|
43
44
|
};
|
|
44
45
|
itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
|
|
@@ -52,9 +53,16 @@ export type AsyncDataLoaderFeatureDef<T> = {
|
|
|
52
53
|
* the tree will continue to display the old data until the new data has loaded. */
|
|
53
54
|
invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
|
|
54
55
|
|
|
55
|
-
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch.
|
|
57
|
+
* @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
58
|
+
updateCachedData: (data: T | undefined, skipUpdateTree?: boolean) => void;
|
|
59
|
+
|
|
60
|
+
/** @param skipUpdateTree If true, the tree will not rebuild the tree structure cache afterwards by calling `tree.rebuildTree()`. */
|
|
61
|
+
updateCachedChildrenIds: (
|
|
62
|
+
childrenIds: string[],
|
|
63
|
+
skipUpdateTree?: boolean,
|
|
64
|
+
) => void;
|
|
65
|
+
|
|
58
66
|
hasLoadedData: () => boolean;
|
|
59
67
|
isLoading: () => boolean;
|
|
60
68
|
};
|
|
@@ -328,8 +328,7 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
328
328
|
"onDropForeignDragObject",
|
|
329
329
|
);
|
|
330
330
|
const event = tree.createBottomDragEvent(2);
|
|
331
|
-
tree.setElementBoundingBox("
|
|
332
|
-
tree.setElementBoundingBox("x213");
|
|
331
|
+
tree.setElementBoundingBox("x112");
|
|
333
332
|
tree.do.dragOver("x112", event);
|
|
334
333
|
tree.do.drop("x112", event);
|
|
335
334
|
expect(onDropForeignDragObject).toHaveBeenCalledWith(
|
|
@@ -357,6 +356,38 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
357
356
|
tree.do.drop("x11", event);
|
|
358
357
|
expect(onDropForeignDragObject).not.toHaveBeenCalled();
|
|
359
358
|
});
|
|
359
|
+
|
|
360
|
+
it("calls canDragForeignDragObjectOver in drag over events, not canDropForeignDragObject", () => {
|
|
361
|
+
const canDropForeignDragObject = tree
|
|
362
|
+
.mockedHandler("canDropForeignDragObject")
|
|
363
|
+
.mockReturnValue(true);
|
|
364
|
+
const canDragForeignDragObjectOver = tree
|
|
365
|
+
.mockedHandler("canDragForeignDragObjectOver")
|
|
366
|
+
.mockReturnValue(true);
|
|
367
|
+
const event = TestTree.dragEvent();
|
|
368
|
+
tree.do.dragOver("x11", event);
|
|
369
|
+
expect(canDragForeignDragObjectOver).toHaveBeenCalledWith(
|
|
370
|
+
event.dataTransfer,
|
|
371
|
+
{ item: tree.item("x11") },
|
|
372
|
+
);
|
|
373
|
+
expect(canDropForeignDragObject).not.toHaveBeenCalled();
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
it("calls canDropForeignDragObject in drop events, not canDragForeignDragObjectOver", () => {
|
|
377
|
+
const canDropForeignDragObject = tree
|
|
378
|
+
.mockedHandler("canDropForeignDragObject")
|
|
379
|
+
.mockReturnValue(true);
|
|
380
|
+
const canDragForeignDragObjectOver = tree
|
|
381
|
+
.mockedHandler("canDragForeignDragObjectOver")
|
|
382
|
+
.mockReturnValue(true);
|
|
383
|
+
const event = TestTree.dragEvent();
|
|
384
|
+
tree.do.drop("x11", event);
|
|
385
|
+
expect(canDropForeignDragObject).toHaveBeenCalledWith(
|
|
386
|
+
event.dataTransfer,
|
|
387
|
+
{ item: tree.item("x11") },
|
|
388
|
+
);
|
|
389
|
+
expect(canDragForeignDragObjectOver).not.toHaveBeenCalled();
|
|
390
|
+
});
|
|
360
391
|
});
|
|
361
392
|
|
|
362
393
|
describe("with insertion handlers", () => {
|
|
@@ -698,6 +729,54 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
698
729
|
});
|
|
699
730
|
});
|
|
700
731
|
|
|
732
|
+
describe("seperateDragHandle", () => {
|
|
733
|
+
it("includes all drag handlers in getProps() when seperateDragHandle is false", () => {
|
|
734
|
+
const props = tree.instance.getItemInstance("x111").getProps();
|
|
735
|
+
expect(props.draggable).toBe(true);
|
|
736
|
+
expect(props.onDragStart).toBeDefined();
|
|
737
|
+
expect(props.onDragEnd).toBeDefined();
|
|
738
|
+
expect(props.onDragEnter).toBeDefined();
|
|
739
|
+
expect(props.onDragOver).toBeDefined();
|
|
740
|
+
expect(props.onDragLeave).toBeDefined();
|
|
741
|
+
expect(props.onDrop).toBeDefined();
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
it("includes drag handle handlers in getDragHandleProps() when seperateDragHandle is false", () => {
|
|
745
|
+
const props = tree.instance
|
|
746
|
+
.getItemInstance("x111")
|
|
747
|
+
.getDragHandleProps();
|
|
748
|
+
expect(props.draggable).toBe(true);
|
|
749
|
+
expect(props.onDragStart).toBeDefined();
|
|
750
|
+
expect(props.onDragEnd).toBeDefined();
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
it("excludes drag handle handlers from getProps() but includes drop handlers when seperateDragHandle is true", async () => {
|
|
754
|
+
const testTree = await tree
|
|
755
|
+
.with({ seperateDragHandle: true })
|
|
756
|
+
.createTestCaseTree();
|
|
757
|
+
const props = testTree.instance.getItemInstance("x111").getProps();
|
|
758
|
+
expect(props.draggable).toBeUndefined();
|
|
759
|
+
expect(props.onDragStart).toBeUndefined();
|
|
760
|
+
expect(props.onDragEnd).toBeUndefined();
|
|
761
|
+
expect(props.onDragEnter).toBeDefined();
|
|
762
|
+
expect(props.onDragOver).toBeDefined();
|
|
763
|
+
expect(props.onDragLeave).toBeDefined();
|
|
764
|
+
expect(props.onDrop).toBeDefined();
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
it("includes drag handle handlers in getDragHandleProps() when seperateDragHandle is true", async () => {
|
|
768
|
+
const testTree = await tree
|
|
769
|
+
.with({ seperateDragHandle: true })
|
|
770
|
+
.createTestCaseTree();
|
|
771
|
+
const props = testTree.instance
|
|
772
|
+
.getItemInstance("x111")
|
|
773
|
+
.getDragHandleProps();
|
|
774
|
+
expect(props.draggable).toBe(true);
|
|
775
|
+
expect(props.onDragStart).toBeDefined();
|
|
776
|
+
expect(props.onDragEnd).toBeDefined();
|
|
777
|
+
});
|
|
778
|
+
});
|
|
779
|
+
|
|
701
780
|
describe("retains last drag state with dragcode", () => {
|
|
702
781
|
it("uses constant number of calls to canDrop", () => {
|
|
703
782
|
const canDrop = tree.mockedHandler("canDrop").mockReturnValue(true);
|
|
@@ -178,47 +178,10 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
178
178
|
itemInstance: {
|
|
179
179
|
getProps: ({ tree, item, prev }) => ({
|
|
180
180
|
...prev?.(),
|
|
181
|
-
|
|
182
|
-
draggable: true,
|
|
181
|
+
...(tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()),
|
|
183
182
|
|
|
184
183
|
onDragEnter: (e: DragEvent) => e.preventDefault(),
|
|
185
184
|
|
|
186
|
-
onDragStart: (e: DragEvent) => {
|
|
187
|
-
const selectedItems = tree.getSelectedItems
|
|
188
|
-
? tree.getSelectedItems()
|
|
189
|
-
: [tree.getFocusedItem()];
|
|
190
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
191
|
-
const config = tree.getConfig();
|
|
192
|
-
|
|
193
|
-
if (!selectedItems.includes(item)) {
|
|
194
|
-
tree.setSelectedItems?.([item.getItemMeta().itemId]);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (!(config.canDrag?.(items) ?? true)) {
|
|
198
|
-
e.preventDefault();
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
if (config.setDragImage) {
|
|
203
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
204
|
-
e.dataTransfer?.setDragImage(imgElement, xOffset ?? 0, yOffset ?? 0);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
208
|
-
const { format, data, dropEffect, effectAllowed } =
|
|
209
|
-
config.createForeignDragObject(items);
|
|
210
|
-
e.dataTransfer.setData(format, data);
|
|
211
|
-
|
|
212
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
213
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
tree.applySubStateUpdate("dnd", {
|
|
217
|
-
draggedItems: items,
|
|
218
|
-
draggingOverItem: tree.getFocusedItem(),
|
|
219
|
-
});
|
|
220
|
-
},
|
|
221
|
-
|
|
222
185
|
onDragOver: (e: DragEvent) => {
|
|
223
186
|
e.stopPropagation(); // don't bubble up to container dragover
|
|
224
187
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
@@ -236,7 +199,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
236
199
|
|
|
237
200
|
handleAutoOpenFolder(dataRef, tree, item, placement);
|
|
238
201
|
|
|
239
|
-
const target = getDragTarget(e, item, tree);
|
|
202
|
+
const target = getDragTarget(e, item, tree, false);
|
|
240
203
|
|
|
241
204
|
if (
|
|
242
205
|
!tree.getState().dnd?.draggedItems &&
|
|
@@ -249,7 +212,8 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
249
212
|
return;
|
|
250
213
|
}
|
|
251
214
|
|
|
252
|
-
|
|
215
|
+
// dataTransfer.payload is not accessible in onDragOver, so just skip entirely here. It'll be checked again in onDrop
|
|
216
|
+
if (!canDrop(null, target, tree)) {
|
|
253
217
|
dataRef.current.lastAllowDrop = false;
|
|
254
218
|
return;
|
|
255
219
|
}
|
|
@@ -276,31 +240,10 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
276
240
|
}, 100);
|
|
277
241
|
},
|
|
278
242
|
|
|
279
|
-
onDragEnd: (e: DragEvent) => {
|
|
280
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } =
|
|
281
|
-
tree.getConfig();
|
|
282
|
-
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
283
|
-
|
|
284
|
-
if (e.dataTransfer?.dropEffect === "none" || !draggedItems) {
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const target = getDragTarget(e, item, tree);
|
|
289
|
-
if (
|
|
290
|
-
canDragForeignDragObjectOver &&
|
|
291
|
-
e.dataTransfer &&
|
|
292
|
-
!canDragForeignDragObjectOver(e.dataTransfer, target)
|
|
293
|
-
) {
|
|
294
|
-
return;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
onCompleteForeignDrop?.(draggedItems);
|
|
298
|
-
},
|
|
299
|
-
|
|
300
243
|
onDrop: async (e: DragEvent) => {
|
|
301
244
|
e.stopPropagation();
|
|
302
245
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
303
|
-
const target = getDragTarget(e, item, tree);
|
|
246
|
+
const target = getDragTarget(e, item, tree, true);
|
|
304
247
|
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
305
248
|
const isValidDrop = canDrop(e.dataTransfer, target, tree);
|
|
306
249
|
|
|
@@ -321,9 +264,76 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
321
264
|
|
|
322
265
|
if (draggedItems) {
|
|
323
266
|
await config.onDrop?.(draggedItems, target);
|
|
267
|
+
draggedItems[0].setFocused();
|
|
324
268
|
} else if (e.dataTransfer) {
|
|
325
269
|
await config.onDropForeignDragObject?.(e.dataTransfer, target);
|
|
326
270
|
}
|
|
271
|
+
|
|
272
|
+
tree.applySubStateUpdate("dnd", null);
|
|
273
|
+
tree.updateDomFocus();
|
|
274
|
+
},
|
|
275
|
+
}),
|
|
276
|
+
|
|
277
|
+
getDragHandleProps: ({ tree, item, prev }) => ({
|
|
278
|
+
...prev?.(),
|
|
279
|
+
|
|
280
|
+
draggable: true,
|
|
281
|
+
|
|
282
|
+
onDragStart: (e: DragEvent) => {
|
|
283
|
+
const selectedItems = tree.getSelectedItems
|
|
284
|
+
? tree.getSelectedItems()
|
|
285
|
+
: [tree.getFocusedItem()];
|
|
286
|
+
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
287
|
+
const config = tree.getConfig();
|
|
288
|
+
|
|
289
|
+
if (!selectedItems.includes(item)) {
|
|
290
|
+
tree.setSelectedItems?.([item.getItemMeta().itemId]);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!(config.canDrag?.(items) ?? true)) {
|
|
294
|
+
e.preventDefault();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (config.setDragImage) {
|
|
299
|
+
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
300
|
+
e.dataTransfer?.setDragImage(imgElement, xOffset ?? 0, yOffset ?? 0);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (config.createForeignDragObject && e.dataTransfer) {
|
|
304
|
+
const { format, data, dropEffect, effectAllowed } =
|
|
305
|
+
config.createForeignDragObject(items);
|
|
306
|
+
e.dataTransfer.setData(format, data);
|
|
307
|
+
|
|
308
|
+
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
309
|
+
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
tree.applySubStateUpdate("dnd", {
|
|
313
|
+
draggedItems: items,
|
|
314
|
+
draggingOverItem: tree.getFocusedItem(),
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
onDragEnd: (e: DragEvent) => {
|
|
319
|
+
const { onCompleteForeignDrop, canDragForeignDragObjectOver } =
|
|
320
|
+
tree.getConfig();
|
|
321
|
+
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
322
|
+
|
|
323
|
+
if (e.dataTransfer?.dropEffect === "none" || !draggedItems) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const target = getDragTarget(e, item, tree, false);
|
|
328
|
+
if (
|
|
329
|
+
canDragForeignDragObjectOver &&
|
|
330
|
+
e.dataTransfer &&
|
|
331
|
+
!canDragForeignDragObjectOver(e.dataTransfer, target)
|
|
332
|
+
) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
onCompleteForeignDrop?.(draggedItems);
|
|
327
337
|
},
|
|
328
338
|
}),
|
|
329
339
|
|
|
@@ -97,6 +97,9 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
97
97
|
|
|
98
98
|
/** When dragging for this many ms on a closed folder, the folder will automatically open. Set to zero to disable. */
|
|
99
99
|
openOnDropDelay?: number;
|
|
100
|
+
|
|
101
|
+
/** If true, `item.getProps()` will not include drag event handlers. Use `item.getDragHandleProps()` on the handler element. */
|
|
102
|
+
seperateDragHandle?: boolean;
|
|
100
103
|
};
|
|
101
104
|
treeInstance: {
|
|
102
105
|
getDragTarget: () => DragTarget<T> | null;
|
|
@@ -118,6 +121,10 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
118
121
|
isDragTargetAbove: () => boolean;
|
|
119
122
|
isDragTargetBelow: () => boolean;
|
|
120
123
|
isDraggingOver: () => boolean;
|
|
124
|
+
|
|
125
|
+
/** Note that `item.getProps()` already passes in all drag event handlers by default. Set `seperateDragHandle` to true to
|
|
126
|
+
* disable the default behavior and use this on the handler element instead. */
|
|
127
|
+
getDragHandleProps: () => Record<string, any>;
|
|
121
128
|
};
|
|
122
129
|
hotkeys: never;
|
|
123
130
|
};
|
|
@@ -29,6 +29,8 @@ export type TargetPlacement =
|
|
|
29
29
|
export const isOrderedDragTarget = <T>(dragTarget: DragTarget<T>) =>
|
|
30
30
|
"childIndex" in dragTarget;
|
|
31
31
|
|
|
32
|
+
/** @param dataTransfer - If the data transfer object should not be considered, e.g. because the event is
|
|
33
|
+
* onDragOver where the browser does not allow reading the payload, pass null */
|
|
32
34
|
export const canDrop = (
|
|
33
35
|
dataTransfer: DataTransfer | null,
|
|
34
36
|
target: DragTarget<any>,
|
|
@@ -197,21 +199,25 @@ export const getReparentTarget = <T>(
|
|
|
197
199
|
};
|
|
198
200
|
};
|
|
199
201
|
|
|
202
|
+
/** @param hasDataTransferPayload - If the data transfer object should not be considered, e.g. because the event is
|
|
203
|
+
* onDragOver where the browser does not allow reading the payload, pass false */
|
|
200
204
|
export const getDragTarget = (
|
|
201
205
|
e: any,
|
|
202
206
|
item: ItemInstance<any>,
|
|
203
207
|
tree: TreeInstance<any>,
|
|
208
|
+
hasDataTransferPayload: boolean,
|
|
204
209
|
canReorder = tree.getConfig().canReorder,
|
|
205
210
|
): DragTarget<any> => {
|
|
211
|
+
const dataTransfer = hasDataTransferPayload ? e.dataTransfer : null;
|
|
206
212
|
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
207
213
|
const itemMeta = item.getItemMeta();
|
|
208
214
|
const parent = item.getParent();
|
|
209
215
|
const itemTarget: DragTarget<any> = { item };
|
|
210
216
|
const parentTarget: DragTarget<any> | null = parent ? { item: parent } : null;
|
|
211
217
|
const canBecomeSibling =
|
|
212
|
-
parentTarget && canDrop(
|
|
218
|
+
parentTarget && canDrop(dataTransfer, parentTarget, tree);
|
|
213
219
|
|
|
214
|
-
const canMakeChild = canDrop(
|
|
220
|
+
const canMakeChild = canDrop(dataTransfer, itemTarget, tree);
|
|
215
221
|
const placement = getTargetPlacement(e, item, tree, canMakeChild);
|
|
216
222
|
|
|
217
223
|
if (
|
|
@@ -229,7 +235,7 @@ export const getDragTarget = (
|
|
|
229
235
|
|
|
230
236
|
if (!canReorder && parent && !canBecomeSibling) {
|
|
231
237
|
// TODO! this breaks in story DND/Can Drop. Maybe move this logic into a composable DragTargetStrategy[] ?
|
|
232
|
-
return getDragTarget(e, parent, tree, false);
|
|
238
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
233
239
|
}
|
|
234
240
|
|
|
235
241
|
if (!parent) {
|
|
@@ -242,7 +248,7 @@ export const getDragTarget = (
|
|
|
242
248
|
}
|
|
243
249
|
|
|
244
250
|
if (!canBecomeSibling) {
|
|
245
|
-
return getDragTarget(e, parent, tree, false);
|
|
251
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
246
252
|
}
|
|
247
253
|
|
|
248
254
|
if (placement.type === PlacementType.Reparent) {
|
|
@@ -254,6 +254,7 @@ export const keyboardDragAndDropFeature: FeatureImplementation = {
|
|
|
254
254
|
await config.onDropForeignDragObject?.(dataTransfer, target);
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
tree.updateDomFocus();
|
|
257
258
|
tree.applySubStateUpdate(
|
|
258
259
|
"assistiveDndState",
|
|
259
260
|
AssistiveDndState.Completed,
|
|
@@ -59,6 +59,14 @@ export const propMemoizationFeature: FeatureImplementation = {
|
|
|
59
59
|
return memoize(props, dataRef.current.memo.item);
|
|
60
60
|
},
|
|
61
61
|
|
|
62
|
+
getDragHandleProps: ({ item, prev }) => {
|
|
63
|
+
const dataRef = item.getDataRef<PropMemoizationDataRef>();
|
|
64
|
+
const props = prev?.() ?? {};
|
|
65
|
+
dataRef.current.memo ??= {};
|
|
66
|
+
dataRef.current.memo.drag ??= {};
|
|
67
|
+
return memoize(props, dataRef.current.memo.drag);
|
|
68
|
+
},
|
|
69
|
+
|
|
62
70
|
getRenameInputProps: ({ item, prev }) => {
|
|
63
71
|
const dataRef = item.getDataRef<PropMemoizationDataRef>();
|
|
64
72
|
const props = prev?.() ?? {};
|
|
@@ -49,13 +49,17 @@ export const selectionFeature: FeatureImplementation = {
|
|
|
49
49
|
return selectedItems.includes(itemId);
|
|
50
50
|
},
|
|
51
51
|
|
|
52
|
-
selectUpTo: ({ tree, item }, ctrl: boolean) => {
|
|
52
|
+
selectUpTo: ({ tree, item, itemId }, ctrl: boolean) => {
|
|
53
53
|
const indexA = item.getItemMeta().index;
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
const dataRef = tree.getDataRef<SelectionDataRef>();
|
|
55
|
+
|
|
56
|
+
if (!dataRef.current.selectUpToAnchorId) {
|
|
57
|
+
dataRef.current.selectUpToAnchorId = itemId;
|
|
58
|
+
tree.setSelectedItems([itemId]);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const itemB = tree.getItemInstance(dataRef.current.selectUpToAnchorId);
|
|
59
63
|
const indexB = itemB.getItemMeta().index;
|
|
60
64
|
const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA];
|
|
61
65
|
const newSelectedItems = tree
|
|
@@ -83,7 +87,7 @@ export const selectionFeature: FeatureImplementation = {
|
|
|
83
87
|
}
|
|
84
88
|
},
|
|
85
89
|
|
|
86
|
-
getProps: ({ tree, item, prev }) => ({
|
|
90
|
+
getProps: ({ tree, item, itemId, prev }) => ({
|
|
87
91
|
...prev?.(),
|
|
88
92
|
"aria-selected": item.isSelected() ? "true" : "false",
|
|
89
93
|
onClick: (e: MouseEvent) => {
|
|
@@ -92,12 +96,12 @@ export const selectionFeature: FeatureImplementation = {
|
|
|
92
96
|
} else if (e.ctrlKey || e.metaKey) {
|
|
93
97
|
item.toggleSelect();
|
|
94
98
|
} else {
|
|
95
|
-
tree.setSelectedItems([
|
|
99
|
+
tree.setSelectedItems([itemId]);
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
if (!e.shiftKey) {
|
|
99
103
|
tree.getDataRef<SelectionDataRef>().current.selectUpToAnchorId =
|
|
100
|
-
|
|
104
|
+
itemId;
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
prev?.()?.onClick?.(e);
|
|
@@ -176,9 +176,8 @@ describe("core-feature/selections", () => {
|
|
|
176
176
|
|
|
177
177
|
it("should handle selectUpTo without ctrl", () => {
|
|
178
178
|
const setSelectedItems = tree.mockedHandler("setSelectedItems");
|
|
179
|
-
tree.
|
|
180
|
-
tree.
|
|
181
|
-
tree.instance.getItemInstance("x112").setFocused();
|
|
179
|
+
tree.do.ctrlSelectItem("x111");
|
|
180
|
+
tree.do.ctrlSelectItem("x112");
|
|
182
181
|
tree.instance.getItemInstance("x114").selectUpTo(false);
|
|
183
182
|
expect(setSelectedItems).toHaveBeenCalledWith([
|
|
184
183
|
"x112",
|
|
@@ -190,9 +189,8 @@ describe("core-feature/selections", () => {
|
|
|
190
189
|
|
|
191
190
|
it("should handle selectUpTo with ctrl", () => {
|
|
192
191
|
const setSelectedItems = tree.mockedHandler("setSelectedItems");
|
|
193
|
-
tree.
|
|
194
|
-
tree.
|
|
195
|
-
tree.instance.getItemInstance("x112").setFocused();
|
|
192
|
+
tree.do.ctrlSelectItem("x111");
|
|
193
|
+
tree.do.ctrlSelectItem("x112");
|
|
196
194
|
tree.instance.getItemInstance("x114").selectUpTo(true);
|
|
197
195
|
expect(setSelectedItems).toHaveBeenCalledWith([
|
|
198
196
|
"x111",
|
|
@@ -107,9 +107,13 @@ export const treeFeature: FeatureImplementation<any> = {
|
|
|
107
107
|
setTimeout(async () => {
|
|
108
108
|
const focusedItem = tree.getFocusedItem();
|
|
109
109
|
tree.getConfig().scrollToItem?.(focusedItem);
|
|
110
|
-
await poll(() => focusedItem.getElement() !== null, 20);
|
|
110
|
+
await poll(() => focusedItem.getElement() !== null, 20, 500);
|
|
111
111
|
const focusedElement = focusedItem.getElement();
|
|
112
|
-
if (!focusedElement)
|
|
112
|
+
if (!focusedElement) {
|
|
113
|
+
tree.getItems()[0]?.setFocused();
|
|
114
|
+
tree.getItems()[0]?.getElement()?.focus();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
113
117
|
focusedElement.focus();
|
|
114
118
|
});
|
|
115
119
|
},
|