@headless-tree/core 0.0.0-20250224204705 → 0.0.0-20250322153940
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 +13 -1
- package/lib/cjs/core/create-tree.js +13 -4
- package/lib/cjs/features/async-data-loader/feature.js +73 -48
- package/lib/cjs/features/async-data-loader/types.d.ts +17 -14
- package/lib/cjs/features/drag-and-drop/feature.js +89 -84
- package/lib/cjs/features/drag-and-drop/types.d.ts +8 -20
- package/lib/cjs/features/drag-and-drop/utils.js +8 -21
- package/lib/cjs/features/expand-all/feature.js +26 -3
- package/lib/cjs/features/expand-all/types.d.ts +3 -1
- package/lib/cjs/features/hotkeys-core/feature.js +6 -3
- package/lib/cjs/features/hotkeys-core/types.d.ts +4 -5
- package/lib/cjs/features/prop-memoization/feature.js +2 -2
- package/lib/cjs/features/prop-memoization/types.d.ts +2 -2
- package/lib/cjs/features/renaming/feature.js +1 -1
- package/lib/cjs/features/search/feature.js +2 -0
- package/lib/cjs/features/search/types.d.ts +2 -2
- package/lib/cjs/features/selection/feature.js +4 -4
- package/lib/cjs/features/selection/types.d.ts +1 -1
- package/lib/cjs/features/sync-data-loader/feature.js +31 -5
- package/lib/cjs/features/sync-data-loader/types.d.ts +5 -5
- package/lib/cjs/features/tree/feature.js +4 -7
- package/lib/cjs/features/tree/types.d.ts +7 -5
- package/lib/cjs/test-utils/test-tree-do.d.ts +2 -2
- package/lib/cjs/test-utils/test-tree-do.js +19 -6
- package/lib/cjs/test-utils/test-tree.d.ts +2 -1
- package/lib/cjs/test-utils/test-tree.js +24 -21
- package/lib/cjs/utilities/create-on-drop-handler.d.ts +1 -1
- package/lib/cjs/utilities/create-on-drop-handler.js +13 -4
- package/lib/cjs/utilities/insert-items-at-target.d.ts +1 -1
- package/lib/cjs/utilities/insert-items-at-target.js +21 -12
- package/lib/cjs/utilities/remove-items-from-parents.d.ts +1 -1
- package/lib/cjs/utilities/remove-items-from-parents.js +12 -3
- package/lib/esm/core/create-tree.js +13 -4
- package/lib/esm/features/async-data-loader/feature.js +73 -48
- package/lib/esm/features/async-data-loader/types.d.ts +17 -14
- package/lib/esm/features/drag-and-drop/feature.js +89 -84
- package/lib/esm/features/drag-and-drop/types.d.ts +8 -20
- package/lib/esm/features/drag-and-drop/utils.js +8 -21
- package/lib/esm/features/expand-all/feature.js +26 -3
- package/lib/esm/features/expand-all/types.d.ts +3 -1
- package/lib/esm/features/hotkeys-core/feature.js +6 -3
- package/lib/esm/features/hotkeys-core/types.d.ts +4 -5
- package/lib/esm/features/prop-memoization/feature.js +2 -2
- package/lib/esm/features/prop-memoization/types.d.ts +2 -2
- package/lib/esm/features/renaming/feature.js +1 -1
- package/lib/esm/features/search/feature.js +2 -0
- package/lib/esm/features/search/types.d.ts +2 -2
- package/lib/esm/features/selection/feature.js +4 -4
- package/lib/esm/features/selection/types.d.ts +1 -1
- package/lib/esm/features/sync-data-loader/feature.js +31 -5
- package/lib/esm/features/sync-data-loader/types.d.ts +5 -5
- package/lib/esm/features/tree/feature.js +4 -7
- package/lib/esm/features/tree/types.d.ts +7 -5
- package/lib/esm/test-utils/test-tree-do.d.ts +2 -2
- package/lib/esm/test-utils/test-tree-do.js +19 -6
- package/lib/esm/test-utils/test-tree.d.ts +2 -1
- package/lib/esm/test-utils/test-tree.js +24 -21
- package/lib/esm/utilities/create-on-drop-handler.d.ts +1 -1
- package/lib/esm/utilities/create-on-drop-handler.js +13 -4
- package/lib/esm/utilities/insert-items-at-target.d.ts +1 -1
- package/lib/esm/utilities/insert-items-at-target.js +21 -12
- package/lib/esm/utilities/remove-items-from-parents.d.ts +1 -1
- package/lib/esm/utilities/remove-items-from-parents.js +12 -3
- package/package.json +2 -2
- package/src/core/core.spec.ts +31 -0
- package/src/core/create-tree.ts +15 -5
- package/src/features/async-data-loader/async-data-loader.spec.ts +10 -6
- package/src/features/async-data-loader/feature.ts +76 -48
- package/src/features/async-data-loader/types.ts +18 -11
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +69 -83
- package/src/features/drag-and-drop/feature.ts +9 -10
- package/src/features/drag-and-drop/types.ts +15 -27
- package/src/features/drag-and-drop/utils.ts +7 -20
- package/src/features/expand-all/feature.ts +29 -5
- package/src/features/expand-all/types.ts +3 -1
- package/src/features/hotkeys-core/feature.ts +3 -0
- package/src/features/hotkeys-core/types.ts +4 -13
- package/src/features/prop-memoization/feature.ts +2 -2
- package/src/features/prop-memoization/prop-memoization.spec.ts +2 -2
- package/src/features/prop-memoization/types.ts +2 -2
- package/src/features/renaming/feature.ts +8 -2
- package/src/features/search/feature.ts +2 -0
- package/src/features/search/types.ts +2 -2
- package/src/features/selection/feature.ts +4 -4
- package/src/features/selection/types.ts +1 -1
- package/src/features/sync-data-loader/feature.ts +26 -7
- package/src/features/sync-data-loader/types.ts +5 -5
- package/src/features/tree/feature.ts +8 -11
- package/src/features/tree/types.ts +7 -5
- package/src/test-utils/test-tree-do.ts +3 -3
- package/src/test-utils/test-tree.ts +26 -22
- package/src/utilities/create-on-drop-handler.ts +3 -3
- package/src/utilities/insert-items-at-target.ts +16 -12
- package/src/utilities/remove-items-from-parents.ts +6 -3
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.expandAllFeature = void 0;
|
|
13
|
-
const utils_1 = require("../../utils");
|
|
14
13
|
exports.expandAllFeature = {
|
|
15
14
|
key: "expand-all",
|
|
16
15
|
treeInstance: {
|
|
@@ -31,17 +30,41 @@ exports.expandAllFeature = {
|
|
|
31
30
|
return;
|
|
32
31
|
}
|
|
33
32
|
item.expand();
|
|
34
|
-
yield
|
|
33
|
+
yield tree.waitForItemChildrenLoaded(item.getId());
|
|
35
34
|
yield Promise.all(item.getChildren().map((child) => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
-
yield
|
|
35
|
+
yield tree.waitForItemChildrenLoaded(item.getId());
|
|
37
36
|
yield (child === null || child === void 0 ? void 0 : child.expandAll(cancelToken));
|
|
38
37
|
})));
|
|
39
38
|
}),
|
|
40
39
|
collapseAll: ({ item }) => {
|
|
40
|
+
if (!item.isExpanded())
|
|
41
|
+
return;
|
|
41
42
|
for (const child of item.getChildren()) {
|
|
42
43
|
child === null || child === void 0 ? void 0 : child.collapseAll();
|
|
43
44
|
}
|
|
44
45
|
item.collapse();
|
|
45
46
|
},
|
|
46
47
|
},
|
|
48
|
+
hotkeys: {
|
|
49
|
+
expandSelected: {
|
|
50
|
+
hotkey: "Control+Shift+Plus",
|
|
51
|
+
handler: (_, tree) => __awaiter(void 0, void 0, void 0, function* () {
|
|
52
|
+
const cancelToken = { current: false };
|
|
53
|
+
const cancelHandler = (e) => {
|
|
54
|
+
if (e.key === "Escape") {
|
|
55
|
+
cancelToken.current = true;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
document.addEventListener("keydown", cancelHandler);
|
|
59
|
+
yield Promise.all(tree.getSelectedItems().map((item) => item.expandAll(cancelToken)));
|
|
60
|
+
document.removeEventListener("keydown", cancelHandler);
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
collapseSelected: {
|
|
64
|
+
hotkey: "Control+Shift+-",
|
|
65
|
+
handler: (_, tree) => {
|
|
66
|
+
tree.getSelectedItems().forEach((item) => item.collapseAll());
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
47
70
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export interface ExpandAllDataRef {
|
|
2
|
+
}
|
|
1
3
|
export type ExpandAllFeatureDef = {
|
|
2
4
|
state: {};
|
|
3
5
|
config: {};
|
|
@@ -13,5 +15,5 @@ export type ExpandAllFeatureDef = {
|
|
|
13
15
|
}) => Promise<void>;
|
|
14
16
|
collapseAll: () => void;
|
|
15
17
|
};
|
|
16
|
-
hotkeys:
|
|
18
|
+
hotkeys: "expandSelected" | "collapseSelected";
|
|
17
19
|
};
|
|
@@ -4,6 +4,8 @@ exports.hotkeysCoreFeature = void 0;
|
|
|
4
4
|
const specialKeys = {
|
|
5
5
|
Letter: /^[a-z]$/,
|
|
6
6
|
LetterOrNumber: /^[a-z0-9]$/,
|
|
7
|
+
Plus: /^\+$/,
|
|
8
|
+
Space: /^ $/,
|
|
7
9
|
};
|
|
8
10
|
const testHotkeyMatch = (pressedKeys, tree, hotkey) => {
|
|
9
11
|
const supposedKeys = hotkey.hotkey.split("+");
|
|
@@ -23,9 +25,9 @@ exports.hotkeysCoreFeature = {
|
|
|
23
25
|
onTreeMount: (tree, element) => {
|
|
24
26
|
const data = tree.getDataRef();
|
|
25
27
|
const keydown = (e) => {
|
|
26
|
-
var _a, _b;
|
|
27
|
-
var
|
|
28
|
-
(_a = (
|
|
28
|
+
var _a, _b, _c, _d;
|
|
29
|
+
var _e;
|
|
30
|
+
(_a = (_e = data.current).pressedKeys) !== null && _a !== void 0 ? _a : (_e.pressedKeys = new Set());
|
|
29
31
|
const newMatch = !data.current.pressedKeys.has(e.key);
|
|
30
32
|
data.current.pressedKeys.add(e.key);
|
|
31
33
|
const hotkeyName = findHotkeyMatch(data.current.pressedKeys, tree, tree.getHotkeyPresets(), tree.getConfig().hotkeys);
|
|
@@ -42,6 +44,7 @@ exports.hotkeysCoreFeature = {
|
|
|
42
44
|
if (hotkeyConfig.preventDefault)
|
|
43
45
|
e.preventDefault();
|
|
44
46
|
hotkeyConfig.handler(e, tree);
|
|
47
|
+
(_d = (_c = tree.getConfig()).onTreeHotkey) === null || _d === void 0 ? void 0 : _d.call(_c, hotkeyName, e);
|
|
45
48
|
};
|
|
46
49
|
const keyup = (e) => {
|
|
47
50
|
var _a;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CustomHotkeysConfig,
|
|
1
|
+
import { CustomHotkeysConfig, TreeInstance } from "../../types/core";
|
|
2
2
|
export interface HotkeyConfig<T> {
|
|
3
3
|
hotkey: string;
|
|
4
4
|
canRepeat?: boolean;
|
|
@@ -7,17 +7,16 @@ export interface HotkeyConfig<T> {
|
|
|
7
7
|
preventDefault?: boolean;
|
|
8
8
|
handler: (e: KeyboardEvent, tree: TreeInstance<T>) => void;
|
|
9
9
|
}
|
|
10
|
-
export
|
|
10
|
+
export interface HotkeysCoreDataRef {
|
|
11
11
|
keydownHandler?: (e: KeyboardEvent) => void;
|
|
12
12
|
keyupHandler?: (e: KeyboardEvent) => void;
|
|
13
13
|
pressedKeys: Set<string>;
|
|
14
|
-
}
|
|
14
|
+
}
|
|
15
15
|
export type HotkeysCoreFeatureDef<T> = {
|
|
16
16
|
state: {};
|
|
17
17
|
config: {
|
|
18
18
|
hotkeys?: CustomHotkeysConfig<T>;
|
|
19
|
-
onTreeHotkey?: (name: string,
|
|
20
|
-
onItemHotkey?: (name: string, item: ItemInstance<T>, element: HTMLElement) => void;
|
|
19
|
+
onTreeHotkey?: (name: string, e: KeyboardEvent) => void;
|
|
21
20
|
};
|
|
22
21
|
treeInstance: {};
|
|
23
22
|
itemInstance: {};
|
|
@@ -30,10 +30,10 @@ exports.propMemoizationFeature = {
|
|
|
30
30
|
"selection",
|
|
31
31
|
],
|
|
32
32
|
treeInstance: {
|
|
33
|
-
getContainerProps: ({ tree, prev }) => {
|
|
33
|
+
getContainerProps: ({ tree, prev }, treeLabel) => {
|
|
34
34
|
var _a;
|
|
35
35
|
const dataRef = tree.getDataRef();
|
|
36
|
-
const props = (_a = prev === null || prev === void 0 ? void 0 : prev()) !== null && _a !== void 0 ? _a : {};
|
|
36
|
+
const props = (_a = prev === null || prev === void 0 ? void 0 : prev(treeLabel)) !== null && _a !== void 0 ? _a : {};
|
|
37
37
|
return memoize(props, dataRef.current);
|
|
38
38
|
},
|
|
39
39
|
},
|
|
@@ -40,11 +40,11 @@ exports.renamingFeature = {
|
|
|
40
40
|
tree.applySubStateUpdate("renamingValue", item.getItemName());
|
|
41
41
|
},
|
|
42
42
|
getRenameInputProps: ({ tree }) => ({
|
|
43
|
+
ref: (r) => r === null || r === void 0 ? void 0 : r.focus(),
|
|
43
44
|
onBlur: () => tree.abortRenaming(),
|
|
44
45
|
value: tree.getRenamingValue(),
|
|
45
46
|
onChange: (e) => {
|
|
46
47
|
var _a;
|
|
47
|
-
// TODO custom type with e.target.value
|
|
48
48
|
tree.applySubStateUpdate("renamingValue", (_a = e.target) === null || _a === void 0 ? void 0 : _a.value);
|
|
49
49
|
},
|
|
50
50
|
}),
|
|
@@ -43,10 +43,12 @@ exports.searchFeature = {
|
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
45
|
getSearchInputElement: ({ tree }) => { var _a; return (_a = tree.getDataRef().current.searchInput) !== null && _a !== void 0 ? _a : null; },
|
|
46
|
+
// TODO memoize with propMemoizationFeature
|
|
46
47
|
getSearchInputElementProps: ({ tree }) => ({
|
|
47
48
|
value: tree.getSearchValue(),
|
|
48
49
|
onChange: (e) => tree.setSearch(e.target.value),
|
|
49
50
|
onBlur: () => tree.closeSearch(),
|
|
51
|
+
ref: tree.registerSearchInputElement,
|
|
50
52
|
}),
|
|
51
53
|
getSearchMatchingItems: (0, utils_1.memo)(({ tree }) => [
|
|
52
54
|
tree.getSearchValue(),
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ItemInstance, SetStateFn } from "../../types/core";
|
|
2
2
|
import { HotkeysCoreDataRef } from "../hotkeys-core/types";
|
|
3
|
-
export
|
|
3
|
+
export interface SearchFeatureDataRef<T = any> extends HotkeysCoreDataRef {
|
|
4
4
|
matchingItems: ItemInstance<T>[];
|
|
5
5
|
searchInput: HTMLInputElement | null;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
export type SearchFeatureDef<T> = {
|
|
8
8
|
state: {
|
|
9
9
|
search: string | null;
|
|
@@ -13,7 +13,6 @@ exports.selectionFeature = {
|
|
|
13
13
|
setSelectedItems: ({ tree }, selectedItems) => {
|
|
14
14
|
tree.applySubStateUpdate("selectedItems", selectedItems);
|
|
15
15
|
},
|
|
16
|
-
// TODO memo
|
|
17
16
|
getSelectedItems: ({ tree }) => {
|
|
18
17
|
return tree.getState().selectedItems.map(tree.getItemInstance);
|
|
19
18
|
},
|
|
@@ -81,9 +80,10 @@ exports.selectionFeature = {
|
|
|
81
80
|
// tree.setSelectedItems([tree.getFocusedItem().getId()]);
|
|
82
81
|
// },
|
|
83
82
|
// },
|
|
84
|
-
|
|
85
|
-
hotkey: "
|
|
86
|
-
|
|
83
|
+
toggleSelectedItem: {
|
|
84
|
+
hotkey: "Control+Space",
|
|
85
|
+
preventDefault: true,
|
|
86
|
+
handler: (_, tree) => {
|
|
87
87
|
tree.getFocusedItem().toggleSelect();
|
|
88
88
|
},
|
|
89
89
|
},
|
|
@@ -17,5 +17,5 @@ export type SelectionFeatureDef<T> = {
|
|
|
17
17
|
isSelected: () => boolean;
|
|
18
18
|
selectUpTo: (ctrl: boolean) => void;
|
|
19
19
|
};
|
|
20
|
-
hotkeys: "
|
|
20
|
+
hotkeys: "toggleSelectedItem" | "selectUpwards" | "selectDownwards" | "selectAll";
|
|
21
21
|
};
|
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.syncDataLoaderFeature = void 0;
|
|
4
13
|
const utils_1 = require("../../utils");
|
|
14
|
+
const errors_1 = require("../../utilities/errors");
|
|
15
|
+
const promiseErrorMessage = "sync dataLoader returned promise";
|
|
5
16
|
exports.syncDataLoaderFeature = {
|
|
6
17
|
key: "sync-data-loader",
|
|
7
|
-
getInitialState: (initialState) => (Object.assign({
|
|
8
|
-
getDefaultConfig: (defaultConfig, tree) => (Object.assign({
|
|
18
|
+
getInitialState: (initialState) => (Object.assign({ loadingItemData: [], loadingItemChildrens: [] }, initialState)),
|
|
19
|
+
getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItemData: (0, utils_1.makeStateUpdater)("loadingItemData", tree), setLoadingItemChildrens: (0, utils_1.makeStateUpdater)("loadingItemChildrens", tree) }, defaultConfig)),
|
|
9
20
|
stateHandlerNames: {
|
|
10
|
-
|
|
21
|
+
loadingItemData: "setLoadingItemData",
|
|
22
|
+
loadingItemChildrens: "setLoadingItemChildrens",
|
|
11
23
|
},
|
|
12
24
|
treeInstance: {
|
|
13
|
-
|
|
14
|
-
|
|
25
|
+
waitForItemDataLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
26
|
+
waitForItemChildrenLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
|
|
27
|
+
retrieveItemData: ({ tree }, itemId) => {
|
|
28
|
+
const data = tree.getConfig().dataLoader.getItem(itemId);
|
|
29
|
+
if (typeof data === "object" && "then" in data) {
|
|
30
|
+
throw (0, errors_1.throwError)(promiseErrorMessage);
|
|
31
|
+
}
|
|
32
|
+
return data;
|
|
33
|
+
},
|
|
34
|
+
retrieveChildrenIds: ({ tree }, itemId) => {
|
|
35
|
+
const data = tree.getConfig().dataLoader.getChildren(itemId);
|
|
36
|
+
if (typeof data === "object" && "then" in data) {
|
|
37
|
+
throw (0, errors_1.throwError)(promiseErrorMessage);
|
|
38
|
+
}
|
|
39
|
+
return data;
|
|
40
|
+
},
|
|
15
41
|
},
|
|
16
42
|
itemInstance: {
|
|
17
43
|
isLoading: () => false,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
export
|
|
2
|
-
getItem: (itemId: string) => T
|
|
3
|
-
getChildren: (itemId: string) => string[]
|
|
4
|
-
}
|
|
1
|
+
export interface TreeDataLoader<T> {
|
|
2
|
+
getItem: (itemId: string) => T | Promise<T>;
|
|
3
|
+
getChildren: (itemId: string) => string[] | Promise<string[]>;
|
|
4
|
+
}
|
|
5
5
|
export type SyncDataLoaderFeatureDef<T> = {
|
|
6
6
|
state: {};
|
|
7
7
|
config: {
|
|
8
8
|
rootItemId: string;
|
|
9
|
-
dataLoader
|
|
9
|
+
dataLoader: TreeDataLoader<T>;
|
|
10
10
|
};
|
|
11
11
|
treeInstance: {
|
|
12
12
|
retrieveItemData: (itemId: string) => T;
|
|
@@ -24,7 +24,7 @@ exports.treeFeature = {
|
|
|
24
24
|
const { rootItemId } = tree.getConfig();
|
|
25
25
|
const { expandedItems } = tree.getState();
|
|
26
26
|
const flatItems = [];
|
|
27
|
-
const expandedItemsSet = new Set(expandedItems);
|
|
27
|
+
const expandedItemsSet = new Set(expandedItems); // TODO support setting state expandedItems as set instead of array
|
|
28
28
|
const recursiveAdd = (itemId, parentId, level, setSize, posInSet) => {
|
|
29
29
|
var _a;
|
|
30
30
|
flatItems.push({
|
|
@@ -36,7 +36,6 @@ exports.treeFeature = {
|
|
|
36
36
|
posInSet,
|
|
37
37
|
});
|
|
38
38
|
if (expandedItemsSet.has(itemId)) {
|
|
39
|
-
// TODO THIS MADE A HUGE DIFFERENCE!
|
|
40
39
|
const children = (_a = tree.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : [];
|
|
41
40
|
let i = 0;
|
|
42
41
|
for (const childId of children) {
|
|
@@ -82,7 +81,7 @@ exports.treeFeature = {
|
|
|
82
81
|
}));
|
|
83
82
|
},
|
|
84
83
|
// TODO add label parameter
|
|
85
|
-
getContainerProps: ({ prev, tree }) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": "", ref: tree.registerElement })),
|
|
84
|
+
getContainerProps: ({ prev, tree }, treeLabel) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": treeLabel !== null && treeLabel !== void 0 ? treeLabel : "", ref: tree.registerElement })),
|
|
86
85
|
// relevant for hotkeys of this feature
|
|
87
86
|
isSearchOpen: () => false,
|
|
88
87
|
},
|
|
@@ -118,7 +117,7 @@ exports.treeFeature = {
|
|
|
118
117
|
if (!item.isFolder()) {
|
|
119
118
|
return;
|
|
120
119
|
}
|
|
121
|
-
if ((_a = tree.getState().
|
|
120
|
+
if ((_a = tree.getState().loadingItemChildrens) === null || _a === void 0 ? void 0 : _a.includes(itemId)) {
|
|
122
121
|
return;
|
|
123
122
|
}
|
|
124
123
|
tree.applySubStateUpdate("expandedItems", (expandedItems) => [
|
|
@@ -157,9 +156,7 @@ exports.treeFeature = {
|
|
|
157
156
|
? tree.getItemInstance(item.getItemMeta().parentId)
|
|
158
157
|
: undefined,
|
|
159
158
|
getIndexInParent: ({ item }) => item.getItemMeta().posInSet,
|
|
160
|
-
getChildren: ({ tree,
|
|
161
|
-
.retrieveChildrenIds(item.getItemMeta().itemId)
|
|
162
|
-
.map((id) => tree.getItemInstance(id)),
|
|
159
|
+
getChildren: ({ tree, itemId }) => tree.retrieveChildrenIds(itemId).map((id) => tree.getItemInstance(id)),
|
|
163
160
|
getTree: ({ tree }) => tree,
|
|
164
161
|
getItemAbove: ({ tree, item }) => tree.getItems()[item.getItemMeta().index - 1],
|
|
165
162
|
getItemBelow: ({ tree, item }) => tree.getItems()[item.getItemMeta().index + 1],
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { ItemInstance, SetStateFn, TreeInstance } from "../../types/core";
|
|
2
|
-
export
|
|
2
|
+
export interface ItemMeta {
|
|
3
3
|
itemId: string;
|
|
4
4
|
parentId: string;
|
|
5
5
|
level: number;
|
|
6
6
|
index: number;
|
|
7
7
|
setSize: number;
|
|
8
8
|
posInSet: number;
|
|
9
|
-
}
|
|
10
|
-
export
|
|
9
|
+
}
|
|
10
|
+
export interface TreeItemDataRef {
|
|
11
11
|
memoizedValues: Record<string, any>;
|
|
12
12
|
memoizedDeps: Record<string, any[] | undefined>;
|
|
13
|
-
}
|
|
13
|
+
}
|
|
14
14
|
export type TreeFeatureDef<T> = {
|
|
15
15
|
state: {
|
|
16
16
|
expandedItems: string[];
|
|
@@ -31,7 +31,9 @@ export type TreeFeatureDef<T> = {
|
|
|
31
31
|
focusNextItem: () => void;
|
|
32
32
|
focusPreviousItem: () => void;
|
|
33
33
|
updateDomFocus: () => void;
|
|
34
|
-
|
|
34
|
+
/** Pass to the container rendering the tree children. The `treeLabel` parameter
|
|
35
|
+
* will be passed as `aria-label` parameter, and is recommended to be set. */
|
|
36
|
+
getContainerProps: (treeLabel?: string) => Record<string, any>;
|
|
35
37
|
};
|
|
36
38
|
itemInstance: {
|
|
37
39
|
getId: () => string;
|
|
@@ -17,7 +17,7 @@ export declare class TestTreeDo<T> {
|
|
|
17
17
|
dragOverNotAllowed(itemId: string, event?: DragEvent): DragEvent<Element>;
|
|
18
18
|
dragLeave(itemId: string): void;
|
|
19
19
|
dragEnd(itemId: string, event?: DragEvent): DragEvent<Element>;
|
|
20
|
-
drop(itemId: string, event?: DragEvent): DragEvent<Element
|
|
21
|
-
dragOverAndDrop(itemId: string, event?: DragEvent): DragEvent<Element
|
|
20
|
+
drop(itemId: string, event?: DragEvent): Promise<DragEvent<Element>>;
|
|
21
|
+
dragOverAndDrop(itemId: string, event?: DragEvent): Promise<DragEvent<Element>>;
|
|
22
22
|
private consistentCalls;
|
|
23
23
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.TestTreeDo = void 0;
|
|
4
13
|
const vitest_1 = require("vitest");
|
|
@@ -79,14 +88,18 @@ class TestTreeDo {
|
|
|
79
88
|
return e;
|
|
80
89
|
}
|
|
81
90
|
drop(itemId, event) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
|
|
93
|
+
yield this.itemProps(itemId).onDrop(e);
|
|
94
|
+
return e;
|
|
95
|
+
});
|
|
85
96
|
}
|
|
86
97
|
dragOverAndDrop(itemId, event) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
|
|
100
|
+
this.dragOver(itemId, e);
|
|
101
|
+
return this.drop(itemId, e);
|
|
102
|
+
});
|
|
90
103
|
}
|
|
91
104
|
consistentCalls(fn) {
|
|
92
105
|
if (!vitest_1.vi.isMockFunction(fn)) {
|
|
@@ -8,6 +8,7 @@ export declare class TestTree<T = string> {
|
|
|
8
8
|
readonly expect: TestTreeExpect<T>;
|
|
9
9
|
private treeInstance;
|
|
10
10
|
private static asyncLoaderResolvers;
|
|
11
|
+
private asyncDataLoaderImp;
|
|
11
12
|
suits: {
|
|
12
13
|
sync: () => {
|
|
13
14
|
tree: TestTree<T>;
|
|
@@ -41,7 +42,7 @@ export declare class TestTree<T = string> {
|
|
|
41
42
|
reset(): void;
|
|
42
43
|
debug(): void;
|
|
43
44
|
setElementBoundingBox(itemId: string, bb?: Partial<DOMRect>): void;
|
|
44
|
-
static dragEvent(
|
|
45
|
+
static dragEvent(clientX?: number, clientY?: number): DragEvent;
|
|
45
46
|
createTopDragEvent(indent?: number): DragEvent<Element>;
|
|
46
47
|
createBottomDragEvent(indent?: number): DragEvent<Element>;
|
|
47
48
|
}
|
|
@@ -42,13 +42,31 @@ class TestTree {
|
|
|
42
42
|
this.do = new test_tree_do_1.TestTreeDo(this);
|
|
43
43
|
this.expect = new test_tree_expect_1.TestTreeExpect(this);
|
|
44
44
|
this.treeInstance = null;
|
|
45
|
+
this.asyncDataLoaderImp = {
|
|
46
|
+
getItem: (id) => __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
yield new Promise((r) => {
|
|
48
|
+
r.debugName = `Loading getItem ${id}`;
|
|
49
|
+
TestTree.asyncLoaderResolvers.push(r);
|
|
50
|
+
});
|
|
51
|
+
return id;
|
|
52
|
+
}),
|
|
53
|
+
getChildren: (id) => __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
yield new Promise((r) => {
|
|
55
|
+
r.debugName = `Loading getChildren ${id}`;
|
|
56
|
+
TestTree.asyncLoaderResolvers.push(r);
|
|
57
|
+
});
|
|
58
|
+
return [`${id}1`, `${id}2`, `${id}3`, `${id}4`];
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
45
61
|
this.suits = {
|
|
46
62
|
sync: () => ({
|
|
47
63
|
tree: this.withFeatures(feature_1.syncDataLoaderFeature),
|
|
48
64
|
title: "Synchronous Data Loader",
|
|
49
65
|
}),
|
|
50
66
|
async: () => ({
|
|
51
|
-
tree: this.withFeatures(feature_2.asyncDataLoaderFeature)
|
|
67
|
+
tree: this.withFeatures(feature_2.asyncDataLoaderFeature).with({
|
|
68
|
+
dataLoader: this.asyncDataLoaderImp,
|
|
69
|
+
}),
|
|
52
70
|
title: "Asynchronous Data Loader",
|
|
53
71
|
}),
|
|
54
72
|
proxifiedSync: () => ({
|
|
@@ -68,12 +86,12 @@ class TestTree {
|
|
|
68
86
|
static resolveAsyncLoaders() {
|
|
69
87
|
return __awaiter(this, void 0, void 0, function* () {
|
|
70
88
|
var _a;
|
|
71
|
-
|
|
89
|
+
do {
|
|
72
90
|
(_a = TestTree.asyncLoaderResolvers.shift()) === null || _a === void 0 ? void 0 : _a();
|
|
73
91
|
yield new Promise((r) => {
|
|
74
92
|
setTimeout(r);
|
|
75
93
|
});
|
|
76
|
-
}
|
|
94
|
+
} while (TestTree.asyncLoaderResolvers.length);
|
|
77
95
|
});
|
|
78
96
|
}
|
|
79
97
|
resolveAsyncVisibleItems() {
|
|
@@ -88,21 +106,6 @@ class TestTree {
|
|
|
88
106
|
return new TestTree(Object.assign({ rootItemId: "x", createLoadingItemData: () => "loading", dataLoader: {
|
|
89
107
|
getItem: (id) => id,
|
|
90
108
|
getChildren: (id) => [`${id}1`, `${id}2`, `${id}3`, `${id}4`],
|
|
91
|
-
}, asyncDataLoader: {
|
|
92
|
-
getItem: (id) => __awaiter(this, void 0, void 0, function* () {
|
|
93
|
-
yield new Promise((r) => {
|
|
94
|
-
r.debugName = `Loading getItem ${id}`;
|
|
95
|
-
TestTree.asyncLoaderResolvers.push(r);
|
|
96
|
-
});
|
|
97
|
-
return id;
|
|
98
|
-
}),
|
|
99
|
-
getChildren: (id) => __awaiter(this, void 0, void 0, function* () {
|
|
100
|
-
yield new Promise((r) => {
|
|
101
|
-
r.debugName = `Loading getChildren ${id}`;
|
|
102
|
-
TestTree.asyncLoaderResolvers.push(r);
|
|
103
|
-
});
|
|
104
|
-
return [`${id}1`, `${id}2`, `${id}3`, `${id}4`];
|
|
105
|
-
}),
|
|
106
109
|
}, getItemName: (item) => item.getItemData(), indent: 20, isItemFolder: (item) => item.getItemMeta().level < 2, initialState: {
|
|
107
110
|
expandedItems: ["x1", "x11"],
|
|
108
111
|
}, features: [] }, config));
|
|
@@ -179,7 +182,7 @@ class TestTree {
|
|
|
179
182
|
getBoundingClientRect: () => bb,
|
|
180
183
|
});
|
|
181
184
|
}
|
|
182
|
-
static dragEvent(
|
|
185
|
+
static dragEvent(clientX = 1000, clientY = 0) {
|
|
183
186
|
return {
|
|
184
187
|
preventDefault: vitest_1.vi.fn(),
|
|
185
188
|
stopPropagation: vitest_1.vi.fn(),
|
|
@@ -188,8 +191,8 @@ class TestTree {
|
|
|
188
191
|
getData: vitest_1.vi.fn(),
|
|
189
192
|
dropEffect: "unchaged-from-test",
|
|
190
193
|
},
|
|
191
|
-
|
|
192
|
-
|
|
194
|
+
clientX,
|
|
195
|
+
clientY,
|
|
193
196
|
};
|
|
194
197
|
}
|
|
195
198
|
createTopDragEvent(indent = 0) {
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ItemInstance } from "../types/core";
|
|
2
2
|
import { DropTarget } from "../features/drag-and-drop/types";
|
|
3
|
-
export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target: DropTarget<T>) => void
|
|
3
|
+
export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target: DropTarget<T>) => Promise<void>;
|
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.createOnDropHandler = void 0;
|
|
4
13
|
const remove_items_from_parents_1 = require("./remove-items-from-parents");
|
|
5
14
|
const insert_items_at_target_1 = require("./insert-items-at-target");
|
|
6
|
-
const createOnDropHandler = (onChangeChildren) => (items, target) => {
|
|
15
|
+
const createOnDropHandler = (onChangeChildren) => (items, target) => __awaiter(void 0, void 0, void 0, function* () {
|
|
7
16
|
const itemIds = items.map((item) => item.getId());
|
|
8
|
-
(0, remove_items_from_parents_1.removeItemsFromParents)(items, onChangeChildren);
|
|
9
|
-
(0, insert_items_at_target_1.insertItemsAtTarget)(itemIds, target, onChangeChildren);
|
|
10
|
-
};
|
|
17
|
+
yield (0, remove_items_from_parents_1.removeItemsFromParents)(items, onChangeChildren);
|
|
18
|
+
yield (0, insert_items_at_target_1.insertItemsAtTarget)(itemIds, target, onChangeChildren);
|
|
19
|
+
});
|
|
11
20
|
exports.createOnDropHandler = createOnDropHandler;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ItemInstance } from "../types/core";
|
|
2
2
|
import { DropTarget } from "../features/drag-and-drop/types";
|
|
3
|
-
export declare const insertItemsAtTarget: <T>(itemIds: string[], target: DropTarget<T>, onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void) => void
|
|
3
|
+
export declare const insertItemsAtTarget: <T>(itemIds: string[], target: DropTarget<T>, onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => Promise<void> | void) => Promise<void>;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
12
|
exports.insertItemsAtTarget = void 0;
|
|
4
|
-
const insertItemsAtTarget = (itemIds, target, onChangeChildren) => {
|
|
13
|
+
const insertItemsAtTarget = (itemIds, target, onChangeChildren) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14
|
+
yield target.item.getTree().waitForItemChildrenLoaded(target.item.getId());
|
|
15
|
+
const oldChildrenIds = target.item
|
|
16
|
+
.getTree()
|
|
17
|
+
.retrieveChildrenIds(target.item.getId());
|
|
5
18
|
// add moved items to new common parent, if dropped onto parent
|
|
6
|
-
if (
|
|
7
|
-
const newChildren = [
|
|
8
|
-
|
|
9
|
-
...itemIds,
|
|
10
|
-
];
|
|
11
|
-
onChangeChildren(target.item, newChildren);
|
|
19
|
+
if (!("childIndex" in target)) {
|
|
20
|
+
const newChildren = [...oldChildrenIds, ...itemIds];
|
|
21
|
+
yield onChangeChildren(target.item, newChildren);
|
|
12
22
|
if (target.item && "updateCachedChildrenIds" in target.item) {
|
|
13
23
|
target.item.updateCachedChildrenIds(newChildren);
|
|
14
24
|
}
|
|
@@ -16,16 +26,15 @@ const insertItemsAtTarget = (itemIds, target, onChangeChildren) => {
|
|
|
16
26
|
return;
|
|
17
27
|
}
|
|
18
28
|
// add moved items to new common parent, if dropped between siblings
|
|
19
|
-
const oldChildren = target.item.getChildren();
|
|
20
29
|
const newChildren = [
|
|
21
|
-
...
|
|
30
|
+
...oldChildrenIds.slice(0, target.insertionIndex),
|
|
22
31
|
...itemIds,
|
|
23
|
-
...
|
|
32
|
+
...oldChildrenIds.slice(target.insertionIndex),
|
|
24
33
|
];
|
|
25
|
-
onChangeChildren(target.item, newChildren);
|
|
34
|
+
yield onChangeChildren(target.item, newChildren);
|
|
26
35
|
if (target.item && "updateCachedChildrenIds" in target.item) {
|
|
27
36
|
target.item.updateCachedChildrenIds(newChildren);
|
|
28
37
|
}
|
|
29
38
|
target.item.getTree().rebuildTree();
|
|
30
|
-
};
|
|
39
|
+
});
|
|
31
40
|
exports.insertItemsAtTarget = insertItemsAtTarget;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ItemInstance } from "../types/core";
|
|
2
|
-
export declare const removeItemsFromParents: <T>(movedItems: ItemInstance<T>[], onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void) => void
|
|
2
|
+
export declare const removeItemsFromParents: <T>(movedItems: ItemInstance<T>[], onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void | Promise<void>) => Promise<void>;
|