@headless-tree/core 1.6.1 → 1.6.3
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 +14 -3
- package/dist/index.d.ts +14 -3
- package/dist/index.js +93 -66
- package/dist/index.mjs +93 -66
- 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 +175 -2
- package/src/features/drag-and-drop/feature.ts +76 -62
- package/src/features/drag-and-drop/types.ts +11 -0
- package/src/features/drag-and-drop/utils.ts +10 -4
- package/src/features/hotkeys-core/feature.ts +11 -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/tree/feature.ts +6 -2
- package/src/utils.ts +1 -0
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
|
},
|
|
@@ -976,6 +981,7 @@ var checkboxesFeature = {
|
|
|
976
981
|
};
|
|
977
982
|
|
|
978
983
|
// src/features/hotkeys-core/feature.ts
|
|
984
|
+
var resolveKeyCode = (e) => e.code !== "" && e.code !== "Unidentified" ? e.code : e.key;
|
|
979
985
|
var specialKeys = {
|
|
980
986
|
// TODO:breaking deprecate auto-lowercase
|
|
981
987
|
letter: /^Key[A-Z]$/,
|
|
@@ -1024,9 +1030,10 @@ var hotkeysCoreFeature = {
|
|
|
1024
1030
|
if (e.target instanceof HTMLInputElement && ignoreHotkeysOnInputs) {
|
|
1025
1031
|
return;
|
|
1026
1032
|
}
|
|
1033
|
+
const resolvedCode = resolveKeyCode(e);
|
|
1027
1034
|
(_b = (_a = data.current).pressedKeys) != null ? _b : _a.pressedKeys = /* @__PURE__ */ new Set();
|
|
1028
|
-
const newMatch = !data.current.pressedKeys.has(
|
|
1029
|
-
data.current.pressedKeys.add(
|
|
1035
|
+
const newMatch = !data.current.pressedKeys.has(resolvedCode);
|
|
1036
|
+
data.current.pressedKeys.add(resolvedCode);
|
|
1030
1037
|
const hotkeyName = findHotkeyMatch(
|
|
1031
1038
|
data.current.pressedKeys,
|
|
1032
1039
|
tree,
|
|
@@ -1034,7 +1041,7 @@ var hotkeysCoreFeature = {
|
|
|
1034
1041
|
hotkeys
|
|
1035
1042
|
);
|
|
1036
1043
|
if (e.target instanceof HTMLInputElement) {
|
|
1037
|
-
data.current.pressedKeys.delete(
|
|
1044
|
+
data.current.pressedKeys.delete(resolvedCode);
|
|
1038
1045
|
}
|
|
1039
1046
|
if (!hotkeyName) return;
|
|
1040
1047
|
const hotkeyConfig = __spreadValues(__spreadValues({}, tree.getHotkeyPresets()[hotkeyName]), hotkeys == null ? void 0 : hotkeys[hotkeyName]);
|
|
@@ -1049,7 +1056,7 @@ var hotkeysCoreFeature = {
|
|
|
1049
1056
|
const keyup = (e) => {
|
|
1050
1057
|
var _a, _b;
|
|
1051
1058
|
(_b = (_a = data.current).pressedKeys) != null ? _b : _a.pressedKeys = /* @__PURE__ */ new Set();
|
|
1052
|
-
data.current.pressedKeys.delete(e
|
|
1059
|
+
data.current.pressedKeys.delete(resolveKeyCode(e));
|
|
1053
1060
|
};
|
|
1054
1061
|
const reset = () => {
|
|
1055
1062
|
data.current.pressedKeys = /* @__PURE__ */ new Set();
|
|
@@ -1230,15 +1237,17 @@ var asyncDataLoaderFeature = {
|
|
|
1230
1237
|
}
|
|
1231
1238
|
yield loadChildrenIds(tree, itemId);
|
|
1232
1239
|
}),
|
|
1233
|
-
updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1240
|
+
updateCachedChildrenIds: ({ tree, itemId }, childrenIds, skipUpdateTree) => {
|
|
1241
|
+
getDataRef(tree).current.childrenIds[itemId] = childrenIds;
|
|
1242
|
+
if (!skipUpdateTree) {
|
|
1243
|
+
tree.rebuildTree();
|
|
1244
|
+
}
|
|
1237
1245
|
},
|
|
1238
|
-
updateCachedData: ({ tree, itemId }, data) => {
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1246
|
+
updateCachedData: ({ tree, itemId }, data, skipUpdateTree) => {
|
|
1247
|
+
getDataRef(tree).current.itemData[itemId] = data;
|
|
1248
|
+
if (!skipUpdateTree) {
|
|
1249
|
+
tree.rebuildTree();
|
|
1250
|
+
}
|
|
1242
1251
|
},
|
|
1243
1252
|
hasLoadedData: ({ tree, itemId }) => {
|
|
1244
1253
|
const dataRef = tree.getDataRef();
|
|
@@ -1405,15 +1414,16 @@ var getReparentTarget = (item, reparentLevel, draggedItems) => {
|
|
|
1405
1414
|
dragLineLevel: reparentLevel
|
|
1406
1415
|
};
|
|
1407
1416
|
};
|
|
1408
|
-
var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) => {
|
|
1417
|
+
var getDragTarget = (e, item, tree, hasDataTransferPayload, canReorder = tree.getConfig().canReorder) => {
|
|
1409
1418
|
var _a;
|
|
1419
|
+
const dataTransfer = hasDataTransferPayload ? e.dataTransfer : null;
|
|
1410
1420
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1411
1421
|
const itemMeta = item.getItemMeta();
|
|
1412
1422
|
const parent = item.getParent();
|
|
1413
1423
|
const itemTarget = { item };
|
|
1414
1424
|
const parentTarget = parent ? { item: parent } : null;
|
|
1415
|
-
const canBecomeSibling = parentTarget && canDrop(
|
|
1416
|
-
const canMakeChild = canDrop(
|
|
1425
|
+
const canBecomeSibling = parentTarget && canDrop(dataTransfer, parentTarget, tree);
|
|
1426
|
+
const canMakeChild = canDrop(dataTransfer, itemTarget, tree);
|
|
1417
1427
|
const placement = getTargetPlacement(e, item, tree, canMakeChild);
|
|
1418
1428
|
if (!canReorder && parent && canBecomeSibling && placement.type !== 2 /* MakeChild */) {
|
|
1419
1429
|
if (draggedItems == null ? void 0 : draggedItems.some((item2) => item2.isDescendentOf(parent.getId()))) {
|
|
@@ -1422,7 +1432,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1422
1432
|
return parentTarget;
|
|
1423
1433
|
}
|
|
1424
1434
|
if (!canReorder && parent && !canBecomeSibling) {
|
|
1425
|
-
return getDragTarget(e, parent, tree, false);
|
|
1435
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1426
1436
|
}
|
|
1427
1437
|
if (!parent) {
|
|
1428
1438
|
return itemTarget;
|
|
@@ -1431,7 +1441,7 @@ var getDragTarget = (e, item, tree, canReorder = tree.getConfig().canReorder) =>
|
|
|
1431
1441
|
return itemTarget;
|
|
1432
1442
|
}
|
|
1433
1443
|
if (!canBecomeSibling) {
|
|
1434
|
-
return getDragTarget(e, parent, tree, false);
|
|
1444
|
+
return getDragTarget(e, parent, tree, hasDataTransferPayload, false);
|
|
1435
1445
|
}
|
|
1436
1446
|
if (placement.type === 3 /* Reparent */) {
|
|
1437
1447
|
return getReparentTarget(item, placement.reparentLevel, draggedItems);
|
|
@@ -1475,7 +1485,8 @@ var dragAndDropFeature = {
|
|
|
1475
1485
|
canDragForeignDragObjectOver: defaultConfig.canDropForeignDragObject !== defaultCanDropForeignDragObject ? (dataTransfer) => dataTransfer.effectAllowed !== "none" : () => false,
|
|
1476
1486
|
setDndState: makeStateUpdater("dnd", tree),
|
|
1477
1487
|
canReorder: true,
|
|
1478
|
-
openOnDropDelay: 800
|
|
1488
|
+
openOnDropDelay: 800,
|
|
1489
|
+
draggedItemOverwritesSelection: true
|
|
1479
1490
|
}, defaultConfig),
|
|
1480
1491
|
stateHandlerNames: {
|
|
1481
1492
|
dnd: "setDndState"
|
|
@@ -1568,36 +1579,8 @@ var dragAndDropFeature = {
|
|
|
1568
1579
|
}
|
|
1569
1580
|
},
|
|
1570
1581
|
itemInstance: {
|
|
1571
|
-
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1572
|
-
draggable: true,
|
|
1582
|
+
getProps: ({ tree, item, prev }) => __spreadProps(__spreadValues(__spreadValues({}, prev == null ? void 0 : prev()), tree.getConfig().seperateDragHandle ? {} : item.getDragHandleProps()), {
|
|
1573
1583
|
onDragEnter: (e) => e.preventDefault(),
|
|
1574
|
-
onDragStart: (e) => {
|
|
1575
|
-
var _a, _b, _c, _d;
|
|
1576
|
-
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1577
|
-
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
1578
|
-
const config = tree.getConfig();
|
|
1579
|
-
if (!selectedItems.includes(item)) {
|
|
1580
|
-
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1581
|
-
}
|
|
1582
|
-
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1583
|
-
e.preventDefault();
|
|
1584
|
-
return;
|
|
1585
|
-
}
|
|
1586
|
-
if (config.setDragImage) {
|
|
1587
|
-
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1588
|
-
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1589
|
-
}
|
|
1590
|
-
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1591
|
-
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1592
|
-
e.dataTransfer.setData(format, data);
|
|
1593
|
-
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1594
|
-
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1595
|
-
}
|
|
1596
|
-
tree.applySubStateUpdate("dnd", {
|
|
1597
|
-
draggedItems: items,
|
|
1598
|
-
draggingOverItem: tree.getFocusedItem()
|
|
1599
|
-
});
|
|
1600
|
-
},
|
|
1601
1584
|
onDragOver: (e) => {
|
|
1602
1585
|
var _a, _b, _c;
|
|
1603
1586
|
e.stopPropagation();
|
|
@@ -1613,12 +1596,12 @@ var dragAndDropFeature = {
|
|
|
1613
1596
|
dataRef.current.lastDragCode = nextDragCode;
|
|
1614
1597
|
dataRef.current.lastDragEnter = Date.now();
|
|
1615
1598
|
handleAutoOpenFolder(dataRef, tree, item, placement);
|
|
1616
|
-
const target = getDragTarget(e, item, tree);
|
|
1599
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1617
1600
|
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)))) {
|
|
1618
1601
|
dataRef.current.lastAllowDrop = false;
|
|
1619
1602
|
return;
|
|
1620
1603
|
}
|
|
1621
|
-
if (!canDrop(
|
|
1604
|
+
if (!canDrop(null, target, tree)) {
|
|
1622
1605
|
dataRef.current.lastAllowDrop = false;
|
|
1623
1606
|
return;
|
|
1624
1607
|
}
|
|
@@ -1641,24 +1624,11 @@ var dragAndDropFeature = {
|
|
|
1641
1624
|
}));
|
|
1642
1625
|
}, 100);
|
|
1643
1626
|
},
|
|
1644
|
-
onDragEnd: (e) => {
|
|
1645
|
-
var _a, _b;
|
|
1646
|
-
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1647
|
-
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1648
|
-
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1649
|
-
return;
|
|
1650
|
-
}
|
|
1651
|
-
const target = getDragTarget(e, item, tree);
|
|
1652
|
-
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1653
|
-
return;
|
|
1654
|
-
}
|
|
1655
|
-
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1656
|
-
},
|
|
1657
1627
|
onDrop: (e) => __async(null, null, function* () {
|
|
1658
1628
|
var _a, _b, _c;
|
|
1659
1629
|
e.stopPropagation();
|
|
1660
1630
|
const dataRef = tree.getDataRef();
|
|
1661
|
-
const target = getDragTarget(e, item, tree);
|
|
1631
|
+
const target = getDragTarget(e, item, tree, true);
|
|
1662
1632
|
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1663
1633
|
const isValidDrop = canDrop(e.dataTransfer, target, tree);
|
|
1664
1634
|
tree.applySubStateUpdate("dnd", {
|
|
@@ -1674,11 +1644,59 @@ var dragAndDropFeature = {
|
|
|
1674
1644
|
dataRef.current.lastDragCode = void 0;
|
|
1675
1645
|
if (draggedItems) {
|
|
1676
1646
|
yield (_b = config.onDrop) == null ? void 0 : _b.call(config, draggedItems, target);
|
|
1647
|
+
draggedItems[0].setFocused();
|
|
1677
1648
|
} else if (e.dataTransfer) {
|
|
1678
1649
|
yield (_c = config.onDropForeignDragObject) == null ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
1679
1650
|
}
|
|
1651
|
+
tree.applySubStateUpdate("dnd", null);
|
|
1652
|
+
tree.updateDomFocus();
|
|
1680
1653
|
})
|
|
1681
1654
|
}),
|
|
1655
|
+
getDragHandleProps: ({ tree, item, prev }) => __spreadProps(__spreadValues({}, prev == null ? void 0 : prev()), {
|
|
1656
|
+
draggable: true,
|
|
1657
|
+
onDragStart: (e) => {
|
|
1658
|
+
var _a, _b, _c, _d;
|
|
1659
|
+
const { draggedItemOverwritesSelection } = tree.getConfig();
|
|
1660
|
+
const selectedItems = tree.getSelectedItems ? tree.getSelectedItems() : [tree.getFocusedItem()];
|
|
1661
|
+
const overwriteSelection = !selectedItems.includes(item) && draggedItemOverwritesSelection;
|
|
1662
|
+
const items = overwriteSelection ? [item] : selectedItems;
|
|
1663
|
+
const config = tree.getConfig();
|
|
1664
|
+
if (overwriteSelection) {
|
|
1665
|
+
(_a = tree.setSelectedItems) == null ? void 0 : _a.call(tree, [item.getItemMeta().itemId]);
|
|
1666
|
+
}
|
|
1667
|
+
if (!((_c = (_b = config.canDrag) == null ? void 0 : _b.call(config, items)) != null ? _c : true)) {
|
|
1668
|
+
e.preventDefault();
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1671
|
+
if (config.setDragImage) {
|
|
1672
|
+
const { imgElement, xOffset, yOffset } = config.setDragImage(items);
|
|
1673
|
+
(_d = e.dataTransfer) == null ? void 0 : _d.setDragImage(imgElement, xOffset != null ? xOffset : 0, yOffset != null ? yOffset : 0);
|
|
1674
|
+
}
|
|
1675
|
+
if (config.createForeignDragObject && e.dataTransfer) {
|
|
1676
|
+
const { format, data, dropEffect, effectAllowed } = config.createForeignDragObject(items);
|
|
1677
|
+
e.dataTransfer.setData(format, data);
|
|
1678
|
+
if (dropEffect) e.dataTransfer.dropEffect = dropEffect;
|
|
1679
|
+
if (effectAllowed) e.dataTransfer.effectAllowed = effectAllowed;
|
|
1680
|
+
}
|
|
1681
|
+
tree.applySubStateUpdate("dnd", {
|
|
1682
|
+
draggedItems: items,
|
|
1683
|
+
draggingOverItem: tree.getFocusedItem()
|
|
1684
|
+
});
|
|
1685
|
+
},
|
|
1686
|
+
onDragEnd: (e) => {
|
|
1687
|
+
var _a, _b;
|
|
1688
|
+
const { onCompleteForeignDrop, canDragForeignDragObjectOver } = tree.getConfig();
|
|
1689
|
+
const draggedItems = (_a = tree.getState().dnd) == null ? void 0 : _a.draggedItems;
|
|
1690
|
+
if (((_b = e.dataTransfer) == null ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
1691
|
+
return;
|
|
1692
|
+
}
|
|
1693
|
+
const target = getDragTarget(e, item, tree, false);
|
|
1694
|
+
if (canDragForeignDragObjectOver && e.dataTransfer && !canDragForeignDragObjectOver(e.dataTransfer, target)) {
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
onCompleteForeignDrop == null ? void 0 : onCompleteForeignDrop(draggedItems);
|
|
1698
|
+
}
|
|
1699
|
+
}),
|
|
1682
1700
|
isDragTarget: ({ tree, item }) => {
|
|
1683
1701
|
const target = tree.getDragTarget();
|
|
1684
1702
|
return target ? target.item.getId() === item.getId() : false;
|
|
@@ -1902,6 +1920,7 @@ var keyboardDragAndDropFeature = {
|
|
|
1902
1920
|
} else if (dataTransfer) {
|
|
1903
1921
|
yield (_d = config.onDropForeignDragObject) == null ? void 0 : _d.call(config, dataTransfer, target);
|
|
1904
1922
|
}
|
|
1923
|
+
tree.updateDomFocus();
|
|
1905
1924
|
tree.applySubStateUpdate(
|
|
1906
1925
|
"assistiveDndState",
|
|
1907
1926
|
3 /* Completed */
|
|
@@ -2252,6 +2271,14 @@ var propMemoizationFeature = {
|
|
|
2252
2271
|
(_e = (_d = dataRef.current.memo).item) != null ? _e : _d.item = {};
|
|
2253
2272
|
return memoize(props, dataRef.current.memo.item);
|
|
2254
2273
|
},
|
|
2274
|
+
getDragHandleProps: ({ item, prev }) => {
|
|
2275
|
+
var _a, _b, _c, _d, _e;
|
|
2276
|
+
const dataRef = item.getDataRef();
|
|
2277
|
+
const props = (_a = prev == null ? void 0 : prev()) != null ? _a : {};
|
|
2278
|
+
(_c = (_b = dataRef.current).memo) != null ? _c : _b.memo = {};
|
|
2279
|
+
(_e = (_d = dataRef.current.memo).drag) != null ? _e : _d.drag = {};
|
|
2280
|
+
return memoize(props, dataRef.current.memo.drag);
|
|
2281
|
+
},
|
|
2255
2282
|
getRenameInputProps: ({ item, prev }) => {
|
|
2256
2283
|
var _a, _b, _c, _d, _e;
|
|
2257
2284
|
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);
|
|
@@ -708,5 +787,99 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
708
787
|
expect(canDrop).toBeCalledTimes(3);
|
|
709
788
|
});
|
|
710
789
|
});
|
|
790
|
+
|
|
791
|
+
describe("draggedItemOverwritesSelection", () => {
|
|
792
|
+
it("overwrites selection when dragging unselected item with draggedItemOverwritesSelection=true", () => {
|
|
793
|
+
tree.do.selectItem("x111");
|
|
794
|
+
tree.do.ctrlSelectItem("x112");
|
|
795
|
+
tree.do.ctrlSelectItem("x113");
|
|
796
|
+
|
|
797
|
+
expect(tree.instance.getItemInstance("x111").isSelected()).toBe(true);
|
|
798
|
+
expect(tree.instance.getItemInstance("x112").isSelected()).toBe(true);
|
|
799
|
+
expect(tree.instance.getItemInstance("x113").isSelected()).toBe(true);
|
|
800
|
+
expect(tree.instance.getItemInstance("x114").isSelected()).toBe(false);
|
|
801
|
+
|
|
802
|
+
tree.do.startDrag("x114");
|
|
803
|
+
|
|
804
|
+
expect(tree.instance.getItemInstance("x111").isSelected()).toBe(false);
|
|
805
|
+
expect(tree.instance.getItemInstance("x112").isSelected()).toBe(false);
|
|
806
|
+
expect(tree.instance.getItemInstance("x113").isSelected()).toBe(false);
|
|
807
|
+
expect(tree.instance.getItemInstance("x114").isSelected()).toBe(true);
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
it("preserves selection when dragging unselected item with draggedItemOverwritesSelection=false", async () => {
|
|
811
|
+
const testTree = await tree
|
|
812
|
+
.with({ draggedItemOverwritesSelection: false })
|
|
813
|
+
.createTestCaseTree();
|
|
814
|
+
|
|
815
|
+
testTree.do.selectItem("x111");
|
|
816
|
+
testTree.do.ctrlSelectItem("x112");
|
|
817
|
+
testTree.do.ctrlSelectItem("x113");
|
|
818
|
+
|
|
819
|
+
expect(testTree.item("x111").isSelected()).toBe(true);
|
|
820
|
+
expect(testTree.item("x112").isSelected()).toBe(true);
|
|
821
|
+
expect(testTree.item("x113").isSelected()).toBe(true);
|
|
822
|
+
expect(testTree.item("x114").isSelected()).toBe(false);
|
|
823
|
+
testTree.do.startDrag("x114");
|
|
824
|
+
|
|
825
|
+
expect(testTree.item("x111").isSelected()).toBe(true);
|
|
826
|
+
expect(testTree.item("x112").isSelected()).toBe(true);
|
|
827
|
+
expect(testTree.item("x113").isSelected()).toBe(true);
|
|
828
|
+
expect(testTree.item("x114").isSelected()).toBe(false);
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
it("does not overwrite selection when dragging selected item with draggedItemOverwritesSelection=true", () => {
|
|
832
|
+
tree.do.selectItem("x111");
|
|
833
|
+
tree.do.ctrlSelectItem("x112");
|
|
834
|
+
tree.do.ctrlSelectItem("x113");
|
|
835
|
+
|
|
836
|
+
expect(tree.item("x111").isSelected()).toBe(true);
|
|
837
|
+
expect(tree.item("x112").isSelected()).toBe(true);
|
|
838
|
+
expect(tree.item("x113").isSelected()).toBe(true);
|
|
839
|
+
|
|
840
|
+
tree.do.startDrag("x111");
|
|
841
|
+
|
|
842
|
+
expect(tree.item("x111").isSelected()).toBe(true);
|
|
843
|
+
expect(tree.item("x112").isSelected()).toBe(true);
|
|
844
|
+
expect(tree.item("x113").isSelected()).toBe(true);
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
it("does not overwrite selection when dragging selected item with draggedItemOverwritesSelection=false", async () => {
|
|
848
|
+
const testTree = await tree
|
|
849
|
+
.with({ draggedItemOverwritesSelection: false })
|
|
850
|
+
.createTestCaseTree();
|
|
851
|
+
|
|
852
|
+
testTree.do.selectItem("x111");
|
|
853
|
+
testTree.do.ctrlSelectItem("x112");
|
|
854
|
+
testTree.do.ctrlSelectItem("x113");
|
|
855
|
+
|
|
856
|
+
expect(testTree.item("x111").isSelected()).toBe(true);
|
|
857
|
+
expect(testTree.item("x112").isSelected()).toBe(true);
|
|
858
|
+
expect(testTree.item("x113").isSelected()).toBe(true);
|
|
859
|
+
|
|
860
|
+
testTree.do.startDrag("x111");
|
|
861
|
+
|
|
862
|
+
expect(testTree.item("x111").isSelected()).toBe(true);
|
|
863
|
+
expect(testTree.item("x112").isSelected()).toBe(true);
|
|
864
|
+
expect(testTree.item("x113").isSelected()).toBe(true);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
it("drags all selected items when draggedItemOverwritesSelection=false", async () => {
|
|
868
|
+
const testTree = await tree
|
|
869
|
+
.with({ draggedItemOverwritesSelection: false })
|
|
870
|
+
.createTestCaseTree();
|
|
871
|
+
|
|
872
|
+
testTree.do.selectItem("x111");
|
|
873
|
+
testTree.do.ctrlSelectItem("x112");
|
|
874
|
+
testTree.do.ctrlSelectItem("x113");
|
|
875
|
+
|
|
876
|
+
testTree.do.startDrag("x111");
|
|
877
|
+
testTree.do.dragOverAndDrop("x21");
|
|
878
|
+
|
|
879
|
+
testTree.expect.dropped(["x111", "x112", "x113"], {
|
|
880
|
+
item: testTree.item("x21"),
|
|
881
|
+
});
|
|
882
|
+
});
|
|
883
|
+
});
|
|
711
884
|
});
|
|
712
885
|
});
|