@headless-tree/core 1.2.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/index.d.mts +580 -0
- package/dist/index.d.ts +580 -0
- package/dist/index.js +2347 -0
- package/dist/index.mjs +2302 -0
- package/package.json +18 -10
- package/src/core/create-tree.ts +26 -15
- package/src/features/async-data-loader/feature.ts +5 -0
- package/src/features/async-data-loader/types.ts +2 -0
- package/src/features/checkboxes/checkboxes.spec.ts +20 -5
- package/src/features/checkboxes/feature.ts +31 -16
- package/src/features/checkboxes/types.ts +1 -0
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +11 -2
- package/src/features/drag-and-drop/feature.ts +107 -24
- package/src/features/drag-and-drop/types.ts +21 -0
- package/src/features/drag-and-drop/utils.ts +8 -6
- package/src/features/keyboard-drag-and-drop/feature.ts +10 -1
- package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +34 -3
- package/src/features/main/types.ts +0 -2
- package/src/features/sync-data-loader/feature.ts +5 -1
- package/src/features/tree/feature.ts +4 -3
- package/src/features/tree/tree.spec.ts +14 -4
- package/src/test-utils/test-tree-do.ts +2 -0
- package/src/test-utils/test-tree.ts +1 -0
- package/tsconfig.json +1 -4
- package/vitest.config.ts +3 -1
- package/lib/cjs/core/build-proxified-instance.d.ts +0 -2
- package/lib/cjs/core/build-proxified-instance.js +0 -58
- package/lib/cjs/core/build-static-instance.d.ts +0 -2
- package/lib/cjs/core/build-static-instance.js +0 -26
- package/lib/cjs/core/create-tree.d.ts +0 -2
- package/lib/cjs/core/create-tree.js +0 -191
- package/lib/cjs/features/async-data-loader/feature.d.ts +0 -2
- package/lib/cjs/features/async-data-loader/feature.js +0 -135
- package/lib/cjs/features/async-data-loader/types.d.ts +0 -47
- package/lib/cjs/features/async-data-loader/types.js +0 -2
- package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
- package/lib/cjs/features/checkboxes/feature.js +0 -94
- package/lib/cjs/features/checkboxes/types.d.ts +0 -26
- package/lib/cjs/features/checkboxes/types.js +0 -9
- package/lib/cjs/features/drag-and-drop/feature.d.ts +0 -2
- package/lib/cjs/features/drag-and-drop/feature.js +0 -205
- package/lib/cjs/features/drag-and-drop/types.d.ts +0 -71
- package/lib/cjs/features/drag-and-drop/types.js +0 -9
- package/lib/cjs/features/drag-and-drop/utils.d.ts +0 -27
- package/lib/cjs/features/drag-and-drop/utils.js +0 -182
- package/lib/cjs/features/expand-all/feature.d.ts +0 -2
- package/lib/cjs/features/expand-all/feature.js +0 -70
- package/lib/cjs/features/expand-all/types.d.ts +0 -19
- package/lib/cjs/features/expand-all/types.js +0 -2
- package/lib/cjs/features/hotkeys-core/feature.d.ts +0 -2
- package/lib/cjs/features/hotkeys-core/feature.js +0 -107
- package/lib/cjs/features/hotkeys-core/types.d.ts +0 -27
- package/lib/cjs/features/hotkeys-core/types.js +0 -2
- package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +0 -2
- package/lib/cjs/features/keyboard-drag-and-drop/feature.js +0 -206
- package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +0 -27
- package/lib/cjs/features/keyboard-drag-and-drop/types.js +0 -11
- package/lib/cjs/features/main/types.d.ts +0 -47
- package/lib/cjs/features/main/types.js +0 -2
- package/lib/cjs/features/prop-memoization/feature.d.ts +0 -2
- package/lib/cjs/features/prop-memoization/feature.js +0 -70
- package/lib/cjs/features/prop-memoization/types.d.ts +0 -15
- package/lib/cjs/features/prop-memoization/types.js +0 -2
- package/lib/cjs/features/renaming/feature.d.ts +0 -2
- package/lib/cjs/features/renaming/feature.js +0 -86
- package/lib/cjs/features/renaming/types.d.ts +0 -27
- package/lib/cjs/features/renaming/types.js +0 -2
- package/lib/cjs/features/search/feature.d.ts +0 -2
- package/lib/cjs/features/search/feature.js +0 -119
- package/lib/cjs/features/search/types.d.ts +0 -32
- package/lib/cjs/features/search/types.js +0 -2
- package/lib/cjs/features/selection/feature.d.ts +0 -2
- package/lib/cjs/features/selection/feature.js +0 -132
- package/lib/cjs/features/selection/types.d.ts +0 -21
- package/lib/cjs/features/selection/types.js +0 -2
- package/lib/cjs/features/sync-data-loader/feature.d.ts +0 -2
- package/lib/cjs/features/sync-data-loader/feature.js +0 -49
- package/lib/cjs/features/sync-data-loader/types.d.ts +0 -28
- package/lib/cjs/features/sync-data-loader/types.js +0 -2
- package/lib/cjs/features/tree/feature.d.ts +0 -2
- package/lib/cjs/features/tree/feature.js +0 -244
- package/lib/cjs/features/tree/types.d.ts +0 -63
- package/lib/cjs/features/tree/types.js +0 -2
- package/lib/cjs/index.d.ts +0 -33
- package/lib/cjs/index.js +0 -51
- package/lib/cjs/mddocs-entry.d.ts +0 -121
- package/lib/cjs/mddocs-entry.js +0 -17
- package/lib/cjs/test-utils/test-tree-do.d.ts +0 -23
- package/lib/cjs/test-utils/test-tree-do.js +0 -112
- package/lib/cjs/test-utils/test-tree-expect.d.ts +0 -17
- package/lib/cjs/test-utils/test-tree-expect.js +0 -66
- package/lib/cjs/test-utils/test-tree.d.ts +0 -48
- package/lib/cjs/test-utils/test-tree.js +0 -207
- package/lib/cjs/types/core.d.ts +0 -84
- package/lib/cjs/types/core.js +0 -2
- package/lib/cjs/types/deep-merge.d.ts +0 -13
- package/lib/cjs/types/deep-merge.js +0 -2
- package/lib/cjs/utilities/create-on-drop-handler.d.ts +0 -3
- package/lib/cjs/utilities/create-on-drop-handler.js +0 -20
- package/lib/cjs/utilities/errors.d.ts +0 -2
- package/lib/cjs/utilities/errors.js +0 -9
- package/lib/cjs/utilities/insert-items-at-target.d.ts +0 -3
- package/lib/cjs/utilities/insert-items-at-target.js +0 -40
- package/lib/cjs/utilities/remove-items-from-parents.d.ts +0 -2
- package/lib/cjs/utilities/remove-items-from-parents.js +0 -32
- package/lib/cjs/utils.d.ts +0 -6
- package/lib/cjs/utils.js +0 -53
- package/lib/esm/core/build-proxified-instance.d.ts +0 -2
- package/lib/esm/core/build-proxified-instance.js +0 -54
- package/lib/esm/core/build-static-instance.d.ts +0 -2
- package/lib/esm/core/build-static-instance.js +0 -22
- package/lib/esm/core/create-tree.d.ts +0 -2
- package/lib/esm/core/create-tree.js +0 -187
- package/lib/esm/features/async-data-loader/feature.d.ts +0 -2
- package/lib/esm/features/async-data-loader/feature.js +0 -132
- package/lib/esm/features/async-data-loader/types.d.ts +0 -47
- package/lib/esm/features/async-data-loader/types.js +0 -1
- package/lib/esm/features/checkboxes/feature.d.ts +0 -2
- package/lib/esm/features/checkboxes/feature.js +0 -91
- package/lib/esm/features/checkboxes/types.d.ts +0 -26
- package/lib/esm/features/checkboxes/types.js +0 -6
- package/lib/esm/features/drag-and-drop/feature.d.ts +0 -2
- package/lib/esm/features/drag-and-drop/feature.js +0 -202
- package/lib/esm/features/drag-and-drop/types.d.ts +0 -71
- package/lib/esm/features/drag-and-drop/types.js +0 -6
- package/lib/esm/features/drag-and-drop/utils.d.ts +0 -27
- package/lib/esm/features/drag-and-drop/utils.js +0 -172
- package/lib/esm/features/expand-all/feature.d.ts +0 -2
- package/lib/esm/features/expand-all/feature.js +0 -67
- package/lib/esm/features/expand-all/types.d.ts +0 -19
- package/lib/esm/features/expand-all/types.js +0 -1
- package/lib/esm/features/hotkeys-core/feature.d.ts +0 -2
- package/lib/esm/features/hotkeys-core/feature.js +0 -104
- package/lib/esm/features/hotkeys-core/types.d.ts +0 -27
- package/lib/esm/features/hotkeys-core/types.js +0 -1
- package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +0 -2
- package/lib/esm/features/keyboard-drag-and-drop/feature.js +0 -203
- package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +0 -27
- package/lib/esm/features/keyboard-drag-and-drop/types.js +0 -8
- package/lib/esm/features/main/types.d.ts +0 -47
- package/lib/esm/features/main/types.js +0 -1
- package/lib/esm/features/prop-memoization/feature.d.ts +0 -2
- package/lib/esm/features/prop-memoization/feature.js +0 -67
- package/lib/esm/features/prop-memoization/types.d.ts +0 -15
- package/lib/esm/features/prop-memoization/types.js +0 -1
- package/lib/esm/features/renaming/feature.d.ts +0 -2
- package/lib/esm/features/renaming/feature.js +0 -83
- package/lib/esm/features/renaming/types.d.ts +0 -27
- package/lib/esm/features/renaming/types.js +0 -1
- package/lib/esm/features/search/feature.d.ts +0 -2
- package/lib/esm/features/search/feature.js +0 -116
- package/lib/esm/features/search/types.d.ts +0 -32
- package/lib/esm/features/search/types.js +0 -1
- package/lib/esm/features/selection/feature.d.ts +0 -2
- package/lib/esm/features/selection/feature.js +0 -129
- package/lib/esm/features/selection/types.d.ts +0 -21
- package/lib/esm/features/selection/types.js +0 -1
- package/lib/esm/features/sync-data-loader/feature.d.ts +0 -2
- package/lib/esm/features/sync-data-loader/feature.js +0 -46
- package/lib/esm/features/sync-data-loader/types.d.ts +0 -28
- package/lib/esm/features/sync-data-loader/types.js +0 -1
- package/lib/esm/features/tree/feature.d.ts +0 -2
- package/lib/esm/features/tree/feature.js +0 -241
- package/lib/esm/features/tree/types.d.ts +0 -63
- package/lib/esm/features/tree/types.js +0 -1
- package/lib/esm/index.d.ts +0 -33
- package/lib/esm/index.js +0 -32
- package/lib/esm/mddocs-entry.d.ts +0 -121
- package/lib/esm/mddocs-entry.js +0 -1
- package/lib/esm/test-utils/test-tree-do.d.ts +0 -23
- package/lib/esm/test-utils/test-tree-do.js +0 -108
- package/lib/esm/test-utils/test-tree-expect.d.ts +0 -17
- package/lib/esm/test-utils/test-tree-expect.js +0 -62
- package/lib/esm/test-utils/test-tree.d.ts +0 -48
- package/lib/esm/test-utils/test-tree.js +0 -203
- package/lib/esm/types/core.d.ts +0 -84
- package/lib/esm/types/core.js +0 -1
- package/lib/esm/types/deep-merge.d.ts +0 -13
- package/lib/esm/types/deep-merge.js +0 -1
- package/lib/esm/utilities/create-on-drop-handler.d.ts +0 -3
- package/lib/esm/utilities/create-on-drop-handler.js +0 -16
- package/lib/esm/utilities/errors.d.ts +0 -2
- package/lib/esm/utilities/errors.js +0 -4
- package/lib/esm/utilities/insert-items-at-target.d.ts +0 -3
- package/lib/esm/utilities/insert-items-at-target.js +0 -36
- package/lib/esm/utilities/remove-items-from-parents.d.ts +0 -2
- package/lib/esm/utilities/remove-items-from-parents.js +0 -28
- package/lib/esm/utils.d.ts +0 -6
- package/lib/esm/utils.js +0 -46
|
@@ -7,14 +7,14 @@ export enum ItemDropCategory {
|
|
|
7
7
|
LastInGroup,
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
enum PlacementType {
|
|
10
|
+
export enum PlacementType {
|
|
11
11
|
ReorderAbove,
|
|
12
12
|
ReorderBelow,
|
|
13
13
|
MakeChild,
|
|
14
14
|
Reparent,
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
type TargetPlacement =
|
|
17
|
+
export type TargetPlacement =
|
|
18
18
|
| {
|
|
19
19
|
type:
|
|
20
20
|
| PlacementType.ReorderAbove
|
|
@@ -95,7 +95,7 @@ export const getInsertionIndex = <T>(
|
|
|
95
95
|
return childIndex - numberOfDragItemsBeforeTarget;
|
|
96
96
|
};
|
|
97
97
|
|
|
98
|
-
const getTargetPlacement = (
|
|
98
|
+
export const getTargetPlacement = (
|
|
99
99
|
e: any,
|
|
100
100
|
item: ItemInstance<any>,
|
|
101
101
|
tree: TreeInstance<any>,
|
|
@@ -153,11 +153,9 @@ const getTargetPlacement = (
|
|
|
153
153
|
};
|
|
154
154
|
|
|
155
155
|
export const getDragCode = (
|
|
156
|
-
e: any,
|
|
157
156
|
item: ItemInstance<any>,
|
|
158
|
-
|
|
157
|
+
placement: TargetPlacement,
|
|
159
158
|
) => {
|
|
160
|
-
const placement = getTargetPlacement(e, item, tree, true);
|
|
161
159
|
return [
|
|
162
160
|
item.getId(),
|
|
163
161
|
placement.type,
|
|
@@ -222,6 +220,10 @@ export const getDragTarget = (
|
|
|
222
220
|
canBecomeSibling &&
|
|
223
221
|
placement.type !== PlacementType.MakeChild
|
|
224
222
|
) {
|
|
223
|
+
if (draggedItems?.some((item) => item.isDescendentOf(parent.getId()))) {
|
|
224
|
+
// dropping on itself should be illegal, return item, canDrop will then return false
|
|
225
|
+
return itemTarget;
|
|
226
|
+
}
|
|
225
227
|
return parentTarget;
|
|
226
228
|
}
|
|
227
229
|
|
|
@@ -191,7 +191,16 @@ export const keyboardDragAndDropFeature: FeatureImplementation = {
|
|
|
191
191
|
preventDefault: true,
|
|
192
192
|
isEnabled: (tree) => !tree.getState().dnd,
|
|
193
193
|
handler: (_, tree) => {
|
|
194
|
-
tree.
|
|
194
|
+
const selectedItems = tree.getSelectedItems?.() ?? [
|
|
195
|
+
tree.getFocusedItem(),
|
|
196
|
+
];
|
|
197
|
+
const focusedItem = tree.getFocusedItem();
|
|
198
|
+
|
|
199
|
+
tree.startKeyboardDrag(
|
|
200
|
+
selectedItems.includes(focusedItem)
|
|
201
|
+
? selectedItems
|
|
202
|
+
: selectedItems.concat(focusedItem),
|
|
203
|
+
);
|
|
195
204
|
},
|
|
196
205
|
},
|
|
197
206
|
dragUp: {
|
|
@@ -49,6 +49,37 @@ describe("core-feature/keyboard-drag-and-drop", () => {
|
|
|
49
49
|
tree.expect.substate("assistiveDndState", AssistiveDndState.Started);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
it("starts dragging only focused item", () => {
|
|
53
|
+
tree.item("x3").setFocused();
|
|
54
|
+
tree.do.hotkey("startDrag");
|
|
55
|
+
tree.expect.substate("dnd", {
|
|
56
|
+
draggedItems: [tree.item("x3")],
|
|
57
|
+
dragTarget: {
|
|
58
|
+
childIndex: 3,
|
|
59
|
+
dragLineIndex: 19,
|
|
60
|
+
dragLineLevel: 0,
|
|
61
|
+
insertionIndex: 2,
|
|
62
|
+
item: tree.item("x"),
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("starts dragging both selected and focused item", () => {
|
|
68
|
+
tree.do.selectMultiple("x111", "x112");
|
|
69
|
+
tree.item("x3").setFocused();
|
|
70
|
+
tree.do.hotkey("startDrag");
|
|
71
|
+
tree.expect.substate("dnd", {
|
|
72
|
+
draggedItems: [tree.item("x111"), tree.item("x112"), tree.item("x3")],
|
|
73
|
+
dragTarget: {
|
|
74
|
+
childIndex: 3,
|
|
75
|
+
dragLineIndex: 19,
|
|
76
|
+
dragLineLevel: 0,
|
|
77
|
+
insertionIndex: 2,
|
|
78
|
+
item: tree.item("x"),
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
52
83
|
it("moves down 1", () => {
|
|
53
84
|
tree.do.selectMultiple("x111", "x112");
|
|
54
85
|
tree.do.hotkey("startDrag");
|
|
@@ -355,13 +386,13 @@ describe("core-feature/keyboard-drag-and-drop", () => {
|
|
|
355
386
|
|
|
356
387
|
it("doesnt go below end of tree", () => {
|
|
357
388
|
const lastState = {
|
|
358
|
-
draggedItems: [tree.item("x111")],
|
|
389
|
+
draggedItems: [tree.item("x111"), tree.item("x3")],
|
|
359
390
|
dragTarget: {
|
|
360
391
|
item: tree.item("x"),
|
|
361
392
|
childIndex: 4,
|
|
362
393
|
dragLineIndex: 20,
|
|
363
394
|
dragLineLevel: 0,
|
|
364
|
-
insertionIndex:
|
|
395
|
+
insertionIndex: 3,
|
|
365
396
|
},
|
|
366
397
|
};
|
|
367
398
|
|
|
@@ -378,7 +409,7 @@ describe("core-feature/keyboard-drag-and-drop", () => {
|
|
|
378
409
|
|
|
379
410
|
it("doesnt go above top of tree", () => {
|
|
380
411
|
const firstState = {
|
|
381
|
-
draggedItems: [tree.item("x111")],
|
|
412
|
+
draggedItems: [tree.item("x111"), tree.item("x1")],
|
|
382
413
|
dragTarget: {
|
|
383
414
|
item: tree.item("x"),
|
|
384
415
|
childIndex: 0,
|
|
@@ -36,8 +36,6 @@ export type MainFeatureDef<T = any> = {
|
|
|
36
36
|
stateName: K,
|
|
37
37
|
updater: Updater<TreeState<T>[K]>,
|
|
38
38
|
) => void;
|
|
39
|
-
/** @internal */
|
|
40
|
-
buildItemInstance: (itemId: string) => ItemInstance<T>;
|
|
41
39
|
setState: SetStateFn<TreeState<T>>;
|
|
42
40
|
getState: () => TreeState<T>;
|
|
43
41
|
setConfig: SetStateFn<TreeConfig<T>>;
|
|
@@ -2,9 +2,13 @@ import { FeatureImplementation } from "../../types/core";
|
|
|
2
2
|
import { makeStateUpdater } from "../../utils";
|
|
3
3
|
import { throwError } from "../../utilities/errors";
|
|
4
4
|
|
|
5
|
+
const undefErrorMessage = "sync dataLoader returned undefined";
|
|
5
6
|
const promiseErrorMessage = "sync dataLoader returned promise";
|
|
6
7
|
const unpromise = <T>(data: T | Promise<T>): T => {
|
|
7
|
-
if (!data
|
|
8
|
+
if (!data) {
|
|
9
|
+
throw throwError(undefErrorMessage);
|
|
10
|
+
}
|
|
11
|
+
if (typeof data === "object" && "then" in data) {
|
|
8
12
|
throw throwError(promiseErrorMessage);
|
|
9
13
|
}
|
|
10
14
|
return data;
|
|
@@ -76,8 +76,9 @@ export const treeFeature: FeatureImplementation<any> = {
|
|
|
76
76
|
},
|
|
77
77
|
|
|
78
78
|
getFocusedItem: ({ tree }) => {
|
|
79
|
+
const focusedItemId = tree.getState().focusedItem;
|
|
79
80
|
return (
|
|
80
|
-
tree.getItemInstance(
|
|
81
|
+
(focusedItemId !== null ? tree.getItemInstance(focusedItemId) : null) ??
|
|
81
82
|
tree.getItems()[0]
|
|
82
83
|
);
|
|
83
84
|
},
|
|
@@ -139,10 +140,10 @@ export const treeFeature: FeatureImplementation<any> = {
|
|
|
139
140
|
ref: item.registerElement,
|
|
140
141
|
role: "treeitem",
|
|
141
142
|
"aria-setsize": itemMeta.setSize,
|
|
142
|
-
"aria-posinset": itemMeta.posInSet,
|
|
143
|
+
"aria-posinset": itemMeta.posInSet + 1,
|
|
143
144
|
"aria-selected": "false",
|
|
144
145
|
"aria-label": item.getItemName(),
|
|
145
|
-
"aria-level": itemMeta.level,
|
|
146
|
+
"aria-level": itemMeta.level + 1,
|
|
146
147
|
tabIndex: item.isFocused() ? 0 : -1,
|
|
147
148
|
onClick: (e: MouseEvent) => {
|
|
148
149
|
item.setFocused();
|
|
@@ -235,8 +235,8 @@ describe("core-feature/selections", () => {
|
|
|
235
235
|
it("generates item props for random item", () => {
|
|
236
236
|
expect(tree.instance.getItemInstance("x2").getProps()).toEqual({
|
|
237
237
|
"aria-label": "x2",
|
|
238
|
-
"aria-level":
|
|
239
|
-
"aria-posinset":
|
|
238
|
+
"aria-level": 1,
|
|
239
|
+
"aria-posinset": 2,
|
|
240
240
|
"aria-selected": "false",
|
|
241
241
|
"aria-setsize": 4,
|
|
242
242
|
onClick: expect.any(Function),
|
|
@@ -249,8 +249,8 @@ describe("core-feature/selections", () => {
|
|
|
249
249
|
it("generates item props for focused", () => {
|
|
250
250
|
expect(tree.instance.getItemInstance("x1").getProps()).toEqual({
|
|
251
251
|
"aria-label": "x1",
|
|
252
|
-
"aria-level":
|
|
253
|
-
"aria-posinset":
|
|
252
|
+
"aria-level": 1,
|
|
253
|
+
"aria-posinset": 1,
|
|
254
254
|
"aria-selected": "false",
|
|
255
255
|
"aria-setsize": 4,
|
|
256
256
|
onClick: expect.any(Function),
|
|
@@ -472,4 +472,14 @@ describe("core-feature/selections", () => {
|
|
|
472
472
|
});
|
|
473
473
|
});
|
|
474
474
|
});
|
|
475
|
+
|
|
476
|
+
describe("empty rootItemId", () => {
|
|
477
|
+
factory.with({ rootItemId: "" }).forSuits((tree) => {
|
|
478
|
+
describe("focused item", () => {
|
|
479
|
+
it("returns correct initial focused item", () => {
|
|
480
|
+
expect(tree.instance.getFocusedItem().getId()).toBe("1");
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
});
|
|
475
485
|
});
|
|
@@ -105,12 +105,14 @@ export class TestTreeDo<T> {
|
|
|
105
105
|
dragEnd(itemId: string, event?: DragEvent) {
|
|
106
106
|
const e = event ?? TestTree.dragEvent();
|
|
107
107
|
this.itemProps(itemId).onDragEnd(e);
|
|
108
|
+
window.dispatchEvent(new CustomEvent("dragend"));
|
|
108
109
|
return e;
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
async drop(itemId: string, event?: DragEvent) {
|
|
112
113
|
const e = event ?? TestTree.dragEvent();
|
|
113
114
|
await this.itemProps(itemId).onDrop(e);
|
|
115
|
+
window.dispatchEvent(new CustomEvent("dragend"));
|
|
114
116
|
return e;
|
|
115
117
|
}
|
|
116
118
|
|
|
@@ -137,6 +137,7 @@ export class TestTree<T = string> {
|
|
|
137
137
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
138
138
|
this.instance;
|
|
139
139
|
await this.resolveAsyncVisibleItems();
|
|
140
|
+
this.instance.registerElement({ getBoundingClientRect: () => null } as any);
|
|
140
141
|
return this;
|
|
141
142
|
}
|
|
142
143
|
|
package/tsconfig.json
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../tsconfig.json",
|
|
3
3
|
"include": ["./src/**/*"],
|
|
4
|
-
"exclude": ["./src/**/*.spec.tsx", "./src/**/*.spec.ts", "./src/**/*.stories.tsx"]
|
|
5
|
-
"compilerOptions": {
|
|
6
|
-
"outDir": "lib/esm"
|
|
7
|
-
}
|
|
4
|
+
"exclude": ["./src/**/*.spec.tsx", "./src/**/*.spec.ts", "./src/**/*.stories.tsx"]
|
|
8
5
|
}
|
package/vitest.config.ts
CHANGED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildProxiedInstance = void 0;
|
|
4
|
-
const errors_1 = require("../utilities/errors");
|
|
5
|
-
const noop = () => { };
|
|
6
|
-
const findPrevInstanceMethod = (features, instanceType, methodKey, featureSearchIndex) => {
|
|
7
|
-
var _a;
|
|
8
|
-
for (let i = featureSearchIndex; i >= 0; i--) {
|
|
9
|
-
const feature = features[i];
|
|
10
|
-
const itemInstanceMethod = (_a = feature[instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
|
|
11
|
-
if (itemInstanceMethod) {
|
|
12
|
-
return i;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return null;
|
|
16
|
-
};
|
|
17
|
-
const invokeInstanceMethod = (features, instanceType, opts, methodKey, featureIndex, args) => {
|
|
18
|
-
var _a;
|
|
19
|
-
const prevIndex = findPrevInstanceMethod(features, instanceType, methodKey, featureIndex - 1);
|
|
20
|
-
const itemInstanceMethod = (_a = features[featureIndex][instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
|
|
21
|
-
return itemInstanceMethod(Object.assign(Object.assign({}, opts), { prev: prevIndex !== null
|
|
22
|
-
? (...newArgs) => invokeInstanceMethod(features, instanceType, opts, methodKey, prevIndex, newArgs)
|
|
23
|
-
: null }), ...args);
|
|
24
|
-
};
|
|
25
|
-
const buildProxiedInstance = (features, instanceType, buildOpts) => {
|
|
26
|
-
// demo with prototypes: https://jsfiddle.net/bgenc58r/
|
|
27
|
-
const opts = {};
|
|
28
|
-
const item = new Proxy({}, {
|
|
29
|
-
has(target, key) {
|
|
30
|
-
if (typeof key === "symbol") {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
if (key === "toJSON") {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
const hasInstanceMethod = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
|
|
37
|
-
return Boolean(hasInstanceMethod);
|
|
38
|
-
},
|
|
39
|
-
get(target, key) {
|
|
40
|
-
if (typeof key === "symbol") {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
if (key === "toJSON") {
|
|
44
|
-
return {};
|
|
45
|
-
}
|
|
46
|
-
return (...args) => {
|
|
47
|
-
const featureIndex = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
|
|
48
|
-
if (featureIndex === null) {
|
|
49
|
-
throw (0, errors_1.throwError)(`feature missing for method ${key}`);
|
|
50
|
-
}
|
|
51
|
-
return invokeInstanceMethod(features, instanceType, opts, key, featureIndex, args);
|
|
52
|
-
};
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
Object.assign(opts, buildOpts(item));
|
|
56
|
-
return [item, noop];
|
|
57
|
-
};
|
|
58
|
-
exports.buildProxiedInstance = buildProxiedInstance;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/* eslint-disable no-continue,no-labels,no-extra-label */
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.buildStaticInstance = void 0;
|
|
5
|
-
const buildStaticInstance = (features, instanceType, buildOpts) => {
|
|
6
|
-
const instance = {};
|
|
7
|
-
const finalize = () => {
|
|
8
|
-
const opts = buildOpts(instance);
|
|
9
|
-
featureLoop: for (let i = 0; i < features.length; i++) {
|
|
10
|
-
// Loop goes in forward order, each features overwrite previous ones and wraps those in a prev() fn
|
|
11
|
-
const definition = features[i][instanceType];
|
|
12
|
-
if (!definition)
|
|
13
|
-
continue featureLoop;
|
|
14
|
-
methodLoop: for (const [key, method] of Object.entries(definition)) {
|
|
15
|
-
if (!method)
|
|
16
|
-
continue methodLoop;
|
|
17
|
-
const prev = instance[key];
|
|
18
|
-
instance[key] = (...args) => {
|
|
19
|
-
return method(Object.assign(Object.assign({}, opts), { prev }), ...args);
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
return [instance, finalize];
|
|
25
|
-
};
|
|
26
|
-
exports.buildStaticInstance = buildStaticInstance;
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createTree = void 0;
|
|
4
|
-
const feature_1 = require("../features/tree/feature");
|
|
5
|
-
const build_static_instance_1 = require("./build-static-instance");
|
|
6
|
-
const errors_1 = require("../utilities/errors");
|
|
7
|
-
const verifyFeatures = (features) => {
|
|
8
|
-
var _a;
|
|
9
|
-
const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key);
|
|
10
|
-
for (const feature of features !== null && features !== void 0 ? features : []) {
|
|
11
|
-
const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep)));
|
|
12
|
-
if (missingDependency) {
|
|
13
|
-
throw (0, errors_1.throwError)(`${feature.key} needs ${missingDependency}`);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
// Check all possible pairs and sort the array
|
|
18
|
-
const exhaustiveSort = (arr, compareFn) => {
|
|
19
|
-
const n = arr.length;
|
|
20
|
-
for (let i = 0; i < n; i++) {
|
|
21
|
-
for (let j = i + 1; j < n; j++) {
|
|
22
|
-
if (compareFn(arr[j], arr[i]) < 0) {
|
|
23
|
-
[arr[i], arr[j]] = [arr[j], arr[i]];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return arr;
|
|
28
|
-
};
|
|
29
|
-
const compareFeatures = (originalOrder) => (feature1, feature2) => {
|
|
30
|
-
var _a, _b;
|
|
31
|
-
if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) {
|
|
32
|
-
return 1;
|
|
33
|
-
}
|
|
34
|
-
if (feature1.key && ((_b = feature2.overwrites) === null || _b === void 0 ? void 0 : _b.includes(feature1.key))) {
|
|
35
|
-
return -1;
|
|
36
|
-
}
|
|
37
|
-
return originalOrder.indexOf(feature1) - originalOrder.indexOf(feature2);
|
|
38
|
-
};
|
|
39
|
-
const sortFeatures = (features = []) => exhaustiveSort(features, compareFeatures(features));
|
|
40
|
-
const createTree = (initialConfig) => {
|
|
41
|
-
var _a, _b, _c, _d;
|
|
42
|
-
const buildInstance = (_a = initialConfig.instanceBuilder) !== null && _a !== void 0 ? _a : build_static_instance_1.buildStaticInstance;
|
|
43
|
-
const additionalFeatures = [
|
|
44
|
-
feature_1.treeFeature,
|
|
45
|
-
...sortFeatures(initialConfig.features),
|
|
46
|
-
];
|
|
47
|
-
verifyFeatures(additionalFeatures);
|
|
48
|
-
const features = [...additionalFeatures];
|
|
49
|
-
const [treeInstance, finalizeTree] = buildInstance(features, "treeInstance", (tree) => ({ tree }));
|
|
50
|
-
let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_c = (_b = initialConfig.initialState) !== null && _b !== void 0 ? _b : initialConfig.state) !== null && _c !== void 0 ? _c : {});
|
|
51
|
-
let config = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getDefaultConfig) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, initialConfig);
|
|
52
|
-
const stateHandlerNames = additionalFeatures.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature.stateHandlerNames)), {});
|
|
53
|
-
let treeElement;
|
|
54
|
-
const treeDataRef = { current: {} };
|
|
55
|
-
const itemInstancesMap = {};
|
|
56
|
-
let itemInstances = [];
|
|
57
|
-
const itemElementsMap = {};
|
|
58
|
-
const itemDataRefs = {};
|
|
59
|
-
let itemMetaMap = {};
|
|
60
|
-
const hotkeyPresets = {};
|
|
61
|
-
const rebuildItemMeta = () => {
|
|
62
|
-
// TODO can we find a way to only run this for the changed substructure?
|
|
63
|
-
itemInstances = [];
|
|
64
|
-
itemMetaMap = {};
|
|
65
|
-
const [rootInstance, finalizeRootInstance] = buildInstance(features, "itemInstance", (item) => ({ item, tree: treeInstance, itemId: config.rootItemId }));
|
|
66
|
-
finalizeRootInstance();
|
|
67
|
-
itemInstancesMap[config.rootItemId] = rootInstance;
|
|
68
|
-
itemMetaMap[config.rootItemId] = {
|
|
69
|
-
itemId: config.rootItemId,
|
|
70
|
-
index: -1,
|
|
71
|
-
parentId: null,
|
|
72
|
-
level: -1,
|
|
73
|
-
posInSet: 0,
|
|
74
|
-
setSize: 1,
|
|
75
|
-
};
|
|
76
|
-
for (const item of treeInstance.getItemsMeta()) {
|
|
77
|
-
itemMetaMap[item.itemId] = item;
|
|
78
|
-
if (!itemInstancesMap[item.itemId]) {
|
|
79
|
-
const [instance, finalizeInstance] = buildInstance(features, "itemInstance", (instance) => ({
|
|
80
|
-
item: instance,
|
|
81
|
-
tree: treeInstance,
|
|
82
|
-
itemId: item.itemId,
|
|
83
|
-
}));
|
|
84
|
-
finalizeInstance();
|
|
85
|
-
itemInstancesMap[item.itemId] = instance;
|
|
86
|
-
itemInstances.push(instance);
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
itemInstances.push(itemInstancesMap[item.itemId]);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
const eachFeature = (fn) => {
|
|
94
|
-
for (const feature of additionalFeatures) {
|
|
95
|
-
fn(feature);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const mainFeature = {
|
|
99
|
-
key: "main",
|
|
100
|
-
treeInstance: {
|
|
101
|
-
getState: () => state,
|
|
102
|
-
setState: ({}, updater) => {
|
|
103
|
-
var _a;
|
|
104
|
-
// Not necessary, since I think the subupdate below keeps the state fresh anyways?
|
|
105
|
-
// state = typeof updater === "function" ? updater(state) : updater;
|
|
106
|
-
(_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state); // TODO this cant be right... This doesnt allow external state updates
|
|
107
|
-
// TODO this is never used, remove
|
|
108
|
-
},
|
|
109
|
-
applySubStateUpdate: ({}, stateName, updater) => {
|
|
110
|
-
state[stateName] =
|
|
111
|
-
typeof updater === "function" ? updater(state[stateName]) : updater;
|
|
112
|
-
const externalStateSetter = config[stateHandlerNames[stateName]];
|
|
113
|
-
externalStateSetter === null || externalStateSetter === void 0 ? void 0 : externalStateSetter(state[stateName]);
|
|
114
|
-
},
|
|
115
|
-
buildItemInstance: ({}, itemId) => {
|
|
116
|
-
const [instance, finalizeInstance] = buildInstance(features, "itemInstance", (instance) => ({
|
|
117
|
-
item: instance,
|
|
118
|
-
tree: treeInstance,
|
|
119
|
-
itemId,
|
|
120
|
-
}));
|
|
121
|
-
finalizeInstance();
|
|
122
|
-
return instance;
|
|
123
|
-
},
|
|
124
|
-
// TODO rebuildSubTree: (itemId: string) => void;
|
|
125
|
-
rebuildTree: () => {
|
|
126
|
-
var _a;
|
|
127
|
-
rebuildItemMeta();
|
|
128
|
-
(_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
|
|
129
|
-
},
|
|
130
|
-
getConfig: () => config,
|
|
131
|
-
setConfig: (_, updater) => {
|
|
132
|
-
var _a, _b, _c;
|
|
133
|
-
const newConfig = typeof updater === "function" ? updater(config) : updater;
|
|
134
|
-
const hasChangedExpandedItems = ((_a = newConfig.state) === null || _a === void 0 ? void 0 : _a.expandedItems) &&
|
|
135
|
-
((_b = newConfig.state) === null || _b === void 0 ? void 0 : _b.expandedItems) !== state.expandedItems;
|
|
136
|
-
config = newConfig;
|
|
137
|
-
if (newConfig.state) {
|
|
138
|
-
state = Object.assign(Object.assign({}, state), newConfig.state);
|
|
139
|
-
}
|
|
140
|
-
if (hasChangedExpandedItems) {
|
|
141
|
-
// if expanded items where changed from the outside
|
|
142
|
-
rebuildItemMeta();
|
|
143
|
-
(_c = config.setState) === null || _c === void 0 ? void 0 : _c.call(config, state);
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
getItemInstance: ({}, itemId) => itemInstancesMap[itemId],
|
|
147
|
-
getItems: () => itemInstances,
|
|
148
|
-
registerElement: ({}, element) => {
|
|
149
|
-
if (treeElement === element) {
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
if (treeElement && !element) {
|
|
153
|
-
eachFeature((feature) => { var _a; return (_a = feature.onTreeUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, treeElement); });
|
|
154
|
-
}
|
|
155
|
-
else if (!treeElement && element) {
|
|
156
|
-
eachFeature((feature) => { var _a; return (_a = feature.onTreeMount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, element); });
|
|
157
|
-
}
|
|
158
|
-
treeElement = element;
|
|
159
|
-
},
|
|
160
|
-
getElement: () => treeElement,
|
|
161
|
-
getDataRef: () => treeDataRef,
|
|
162
|
-
getHotkeyPresets: () => hotkeyPresets,
|
|
163
|
-
},
|
|
164
|
-
itemInstance: {
|
|
165
|
-
registerElement: ({ itemId, item }, element) => {
|
|
166
|
-
if (itemElementsMap[itemId] === element) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
const oldElement = itemElementsMap[itemId];
|
|
170
|
-
if (oldElement && !element) {
|
|
171
|
-
eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, item, oldElement, treeInstance); });
|
|
172
|
-
}
|
|
173
|
-
else if (!oldElement && element) {
|
|
174
|
-
eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature, item, element, treeInstance); });
|
|
175
|
-
}
|
|
176
|
-
itemElementsMap[itemId] = element;
|
|
177
|
-
},
|
|
178
|
-
getElement: ({ itemId }) => itemElementsMap[itemId],
|
|
179
|
-
// eslint-disable-next-line no-return-assign
|
|
180
|
-
getDataRef: ({ itemId }) => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); },
|
|
181
|
-
getItemMeta: ({ itemId }) => itemMetaMap[itemId],
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
features.unshift(mainFeature);
|
|
185
|
-
for (const feature of features) {
|
|
186
|
-
Object.assign(hotkeyPresets, (_d = feature.hotkeys) !== null && _d !== void 0 ? _d : {});
|
|
187
|
-
}
|
|
188
|
-
finalizeTree();
|
|
189
|
-
return treeInstance;
|
|
190
|
-
};
|
|
191
|
-
exports.createTree = createTree;
|