@headless-tree/core 0.0.0-20260107220200 → 0.0.0-20260108010329
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 +3 -1
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +64 -45
- package/dist/index.mjs +64 -45
- package/package.json +1 -1
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +48 -0
- package/src/features/drag-and-drop/feature.ts +68 -59
- package/src/features/drag-and-drop/types.ts +7 -0
- 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/tree/feature.ts +6 -2
- package/src/utils.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# @headless-tree/core
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-20260108010329
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
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)
|
|
8
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.
|
|
9
11
|
|
|
10
12
|
## 1.6.1
|
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
|
};
|
|
@@ -422,6 +427,7 @@ interface PropMemoizationDataRef {
|
|
|
422
427
|
memo?: {
|
|
423
428
|
tree?: Record<string, any>;
|
|
424
429
|
item?: Record<string, any>;
|
|
430
|
+
drag?: Record<string, any>;
|
|
425
431
|
search?: Record<string, any>;
|
|
426
432
|
rename?: Record<string, any>;
|
|
427
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
|
};
|
|
@@ -422,6 +427,7 @@ interface PropMemoizationDataRef {
|
|
|
422
427
|
memo?: {
|
|
423
428
|
tree?: Record<string, any>;
|
|
424
429
|
item?: Record<string, any>;
|
|
430
|
+
drag?: Record<string, any>;
|
|
425
431
|
search?: Record<string, any>;
|
|
426
432
|
rename?: Record<string, any>;
|
|
427
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
|
},
|
|
@@ -1615,36 +1620,8 @@ var dragAndDropFeature = {
|
|
|
1615
1620
|
}
|
|
1616
1621
|
},
|
|
1617
1622
|
itemInstance: {
|
|
1618
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1619
|
-
draggable: true,
|
|
1623
|
+
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues(__spreadValues({}, prev == null ? void 0 : prev()), tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()), {
|
|
1620
1624
|
onDragEnter: (e) => e.preventDefault(),
|
|
1621
|
-
onDragStart: (e) => {
|
|
1622
|
-
var _a, _b, _c, _d;
|
|
1623
|
-
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1624
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1625
|
-
const config = tree.getConfig();
|
|
1626
|
-
if (!selectedItems.includes(item)) {
|
|
1627
|
-
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1628
|
-
}
|
|
1629
|
-
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1630
|
-
e.preventDefault();
|
|
1631
|
-
return;
|
|
1632
|
-
}
|
|
1633
|
-
if (config.setDragImage) {
|
|
1634
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1635
|
-
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1636
|
-
}
|
|
1637
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1638
|
-
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1639
|
-
e.dataTransfer.setData(format, data);
|
|
1640
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1641
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1642
|
-
}
|
|
1643
|
-
tree.applySubStateUpdate("dnd", {
|
|
1644
|
-
draggedItems: items,
|
|
1645
|
-
draggingOverItem: tree.getFocusedItem()
|
|
1646
|
-
});
|
|
1647
|
-
},
|
|
1648
1625
|
onDragOver: (e) => {
|
|
1649
1626
|
var _a, _b, _c;
|
|
1650
1627
|
e.stopPropagation();
|
|
@@ -1688,19 +1665,6 @@ var dragAndDropFeature = {
|
|
|
1688
1665
|
}));
|
|
1689
1666
|
}, 100);
|
|
1690
1667
|
},
|
|
1691
|
-
onDragEnd: (e) => {
|
|
1692
|
-
var _a, _b;
|
|
1693
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1694
|
-
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1695
|
-
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1696
|
-
return;
|
|
1697
|
-
}
|
|
1698
|
-
const target = getDragTarget(e, item, tree, false);
|
|
1699
|
-
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1700
|
-
return;
|
|
1701
|
-
}
|
|
1702
|
-
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1703
|
-
},
|
|
1704
1668
|
onDrop: (e) => __async(null, null, function* () {
|
|
1705
1669
|
var _a, _b, _c;
|
|
1706
1670
|
e.stopPropagation();
|
|
@@ -1721,11 +1685,57 @@ var dragAndDropFeature = {
|
|
|
1721
1685
|
dataRef.current.lastDragCode = void 0;
|
|
1722
1686
|
if (draggedItems) {
|
|
1723
1687
|
yield (_b = config.onDrop) == null ? void 0 : _b.call(config, draggedItems, target);
|
|
1688
|
+
draggedItems[0].setFocused();
|
|
1724
1689
|
} else if (e.dataTransfer) {
|
|
1725
1690
|
yield (_c = config.onDropForeignDragObject) == null ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
1726
1691
|
}
|
|
1692
|
+
tree.applySubStateUpdate("dnd", null);
|
|
1693
|
+
tree.updateDomFocus();
|
|
1727
1694
|
})
|
|
1728
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
|
+
}),
|
|
1729
1739
|
isDragTarget: ({ tree, item }) => {
|
|
1730
1740
|
const target = tree.getDragTarget();
|
|
1731
1741
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -1949,6 +1959,7 @@ var keyboardDragAndDropFeature = {
|
|
|
1949
1959
|
} else if (dataTransfer) {
|
|
1950
1960
|
yield (_d = config.onDropForeignDragObject) == null ? void 0 : _d.call(config, dataTransfer, target);
|
|
1951
1961
|
}
|
|
1962
|
+
tree.updateDomFocus();
|
|
1952
1963
|
tree.applySubStateUpdate(
|
|
1953
1964
|
"assistiveDndState",
|
|
1954
1965
|
3 /* Completed */
|
|
@@ -2299,6 +2310,14 @@ var propMemoizationFeature = {
|
|
|
2299
2310
|
(_e = (_d = dataRef.current.memo).item) != null ? _e : _d.item = {};
|
|
2300
2311
|
return memoize(props, dataRef.current.memo.item);
|
|
2301
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
|
+
},
|
|
2302
2321
|
getRenameInputProps: ({ item, prev }) => {
|
|
2303
2322
|
var _a, _b, _c, _d, _e;
|
|
2304
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
|
},
|
|
@@ -1571,36 +1576,8 @@ var dragAndDropFeature = {
|
|
|
1571
1576
|
}
|
|
1572
1577
|
},
|
|
1573
1578
|
itemInstance: {
|
|
1574
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1575
|
-
draggable: true,
|
|
1579
|
+
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues(__spreadValues({}, prev == null ? void 0 : prev()), tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()), {
|
|
1576
1580
|
onDragEnter: (e) => e.preventDefault(),
|
|
1577
|
-
onDragStart: (e) => {
|
|
1578
|
-
var _a, _b, _c, _d;
|
|
1579
|
-
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1580
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1581
|
-
const config = tree.getConfig();
|
|
1582
|
-
if (!selectedItems.includes(item)) {
|
|
1583
|
-
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1584
|
-
}
|
|
1585
|
-
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1586
|
-
e.preventDefault();
|
|
1587
|
-
return;
|
|
1588
|
-
}
|
|
1589
|
-
if (config.setDragImage) {
|
|
1590
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1591
|
-
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1592
|
-
}
|
|
1593
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1594
|
-
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1595
|
-
e.dataTransfer.setData(format, data);
|
|
1596
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1597
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1598
|
-
}
|
|
1599
|
-
tree.applySubStateUpdate("dnd", {
|
|
1600
|
-
draggedItems: items,
|
|
1601
|
-
draggingOverItem: tree.getFocusedItem()
|
|
1602
|
-
});
|
|
1603
|
-
},
|
|
1604
1581
|
onDragOver: (e) => {
|
|
1605
1582
|
var _a, _b, _c;
|
|
1606
1583
|
e.stopPropagation();
|
|
@@ -1644,19 +1621,6 @@ var dragAndDropFeature = {
|
|
|
1644
1621
|
}));
|
|
1645
1622
|
}, 100);
|
|
1646
1623
|
},
|
|
1647
|
-
onDragEnd: (e) => {
|
|
1648
|
-
var _a, _b;
|
|
1649
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1650
|
-
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1651
|
-
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1652
|
-
return;
|
|
1653
|
-
}
|
|
1654
|
-
const target = getDragTarget(e, item, tree, false);
|
|
1655
|
-
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1656
|
-
return;
|
|
1657
|
-
}
|
|
1658
|
-
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1659
|
-
},
|
|
1660
1624
|
onDrop: (e) => __async(null, null, function* () {
|
|
1661
1625
|
var _a, _b, _c;
|
|
1662
1626
|
e.stopPropagation();
|
|
@@ -1677,11 +1641,57 @@ var dragAndDropFeature = {
|
|
|
1677
1641
|
dataRef.current.lastDragCode = void 0;
|
|
1678
1642
|
if (draggedItems) {
|
|
1679
1643
|
yield (_b = config.onDrop) == null ? void 0 : _b.call(config, draggedItems, target);
|
|
1644
|
+
draggedItems[0].setFocused();
|
|
1680
1645
|
} else if (e.dataTransfer) {
|
|
1681
1646
|
yield (_c = config.onDropForeignDragObject) == null ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
1682
1647
|
}
|
|
1648
|
+
tree.applySubStateUpdate("dnd", null);
|
|
1649
|
+
tree.updateDomFocus();
|
|
1683
1650
|
})
|
|
1684
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
|
+
}),
|
|
1685
1695
|
isDragTarget: ({ tree, item }) => {
|
|
1686
1696
|
const target = tree.getDragTarget();
|
|
1687
1697
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -1905,6 +1915,7 @@ var keyboardDragAndDropFeature = {
|
|
|
1905
1915
|
} else if (dataTransfer) {
|
|
1906
1916
|
yield (_d = config.onDropForeignDragObject) == null ? void 0 : _d.call(config, dataTransfer, target);
|
|
1907
1917
|
}
|
|
1918
|
+
tree.updateDomFocus();
|
|
1908
1919
|
tree.applySubStateUpdate(
|
|
1909
1920
|
"assistiveDndState",
|
|
1910
1921
|
3 /* Completed */
|
|
@@ -2255,6 +2266,14 @@ var propMemoizationFeature = {
|
|
|
2255
2266
|
(_e = (_d = dataRef.current.memo).item) != null ? _e : _d.item = {};
|
|
2256
2267
|
return memoize(props, dataRef.current.memo.item);
|
|
2257
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
|
+
},
|
|
2258
2277
|
getRenameInputProps: ({ item, prev }) => {
|
|
2259
2278
|
var _a, _b, _c, _d, _e;
|
|
2260
2279
|
const dataRef = item.getDataRef();
|
package/package.json
CHANGED
|
@@ -729,6 +729,54 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
729
729
|
});
|
|
730
730
|
});
|
|
731
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
|
+
|
|
732
780
|
describe("retains last drag state with dragcode", () => {
|
|
733
781
|
it("uses constant number of calls to canDrop", () => {
|
|
734
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>();
|
|
@@ -277,27 +240,6 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
277
240
|
}, 100);
|
|
278
241
|
},
|
|
279
242
|
|
|
280
|
-
onDragEnd: (e: DragEvent) => {
|
|
281
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } =
|
|
282
|
-
tree.getConfig();
|
|
283
|
-
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
284
|
-
|
|
285
|
-
if (e.dataTransfer?.dropEffect === "none" || !draggedItems) {
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const target = getDragTarget(e, item, tree, false);
|
|
290
|
-
if (
|
|
291
|
-
canDragForeignDragObjectOver &&
|
|
292
|
-
e.dataTransfer &&
|
|
293
|
-
!canDragForeignDragObjectOver(e.dataTransfer, target)
|
|
294
|
-
) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
onCompleteForeignDrop?.(draggedItems);
|
|
299
|
-
},
|
|
300
|
-
|
|
301
243
|
onDrop: async (e: DragEvent) => {
|
|
302
244
|
e.stopPropagation();
|
|
303
245
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
@@ -322,9 +264,76 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
322
264
|
|
|
323
265
|
if (draggedItems) {
|
|
324
266
|
await config.onDrop?.(draggedItems, target);
|
|
267
|
+
draggedItems[0].setFocused();
|
|
325
268
|
} else if (e.dataTransfer) {
|
|
326
269
|
await config.onDropForeignDragObject?.(e.dataTransfer, target);
|
|
327
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);
|
|
328
337
|
},
|
|
329
338
|
}),
|
|
330
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
|
};
|
|
@@ -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?.() ?? {};
|
|
@@ -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
|
},
|