@headless-tree/core 0.0.0-20250511185653 → 0.0.0-20250511194715
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 +2 -1
- package/lib/cjs/core/create-tree.js +0 -9
- package/lib/cjs/features/async-data-loader/feature.js +20 -41
- package/lib/cjs/features/async-data-loader/types.d.ts +4 -4
- package/lib/cjs/features/expand-all/feature.js +2 -2
- package/lib/cjs/features/hotkeys-core/feature.js +27 -13
- package/lib/cjs/features/keyboard-drag-and-drop/feature.js +1 -1
- package/lib/cjs/features/main/types.d.ts +0 -2
- package/lib/cjs/features/selection/feature.js +1 -1
- package/lib/cjs/features/sync-data-loader/feature.js +2 -0
- package/lib/cjs/index.d.ts +0 -2
- package/lib/cjs/index.js +0 -2
- package/lib/cjs/types/core.d.ts +1 -2
- package/lib/esm/core/create-tree.js +0 -9
- package/lib/esm/features/async-data-loader/feature.js +20 -41
- package/lib/esm/features/async-data-loader/types.d.ts +4 -4
- package/lib/esm/features/expand-all/feature.js +2 -2
- package/lib/esm/features/hotkeys-core/feature.js +27 -13
- package/lib/esm/features/keyboard-drag-and-drop/feature.js +1 -1
- package/lib/esm/features/main/types.d.ts +0 -2
- package/lib/esm/features/selection/feature.js +1 -1
- package/lib/esm/features/sync-data-loader/feature.js +2 -0
- package/lib/esm/index.d.ts +0 -2
- package/lib/esm/index.js +0 -2
- package/lib/esm/types/core.d.ts +1 -2
- package/package.json +1 -1
- package/src/core/create-tree.ts +0 -13
- package/src/features/async-data-loader/feature.ts +24 -35
- package/src/features/async-data-loader/types.ts +4 -4
- package/src/features/expand-all/feature.ts +2 -2
- package/src/features/hotkeys-core/feature.ts +33 -15
- package/src/features/keyboard-drag-and-drop/feature.ts +1 -1
- package/src/features/main/types.ts +0 -2
- package/src/features/selection/feature.ts +1 -1
- package/src/features/sync-data-loader/feature.ts +3 -0
- package/src/features/tree/types.ts +1 -1
- package/src/index.ts +0 -2
- package/src/types/core.ts +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/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/src/features/checkboxes/checkboxes.spec.ts +0 -134
- package/src/features/checkboxes/feature.ts +0 -119
- package/src/features/checkboxes/types.ts +0 -28
|
@@ -37,6 +37,8 @@ export const syncDataLoaderFeature = {
|
|
|
37
37
|
}
|
|
38
38
|
return unpromise(dataLoader.getChildrenWithData(itemId)).map((c) => c.data);
|
|
39
39
|
},
|
|
40
|
+
loadItemData: ({ tree }, itemId) => tree.retrieveItemData(itemId),
|
|
41
|
+
loadChildrenIds: ({ tree }, itemId) => tree.retrieveChildrenIds(itemId),
|
|
40
42
|
},
|
|
41
43
|
itemInstance: {
|
|
42
44
|
isLoading: () => false,
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export { MainFeatureDef, InstanceBuilder } from "./features/main/types";
|
|
|
5
5
|
export * from "./features/drag-and-drop/types";
|
|
6
6
|
export * from "./features/keyboard-drag-and-drop/types";
|
|
7
7
|
export * from "./features/selection/types";
|
|
8
|
-
export * from "./features/checkboxes/types";
|
|
9
8
|
export * from "./features/async-data-loader/types";
|
|
10
9
|
export * from "./features/sync-data-loader/types";
|
|
11
10
|
export * from "./features/hotkeys-core/types";
|
|
@@ -14,7 +13,6 @@ export * from "./features/renaming/types";
|
|
|
14
13
|
export * from "./features/expand-all/types";
|
|
15
14
|
export * from "./features/prop-memoization/types";
|
|
16
15
|
export * from "./features/selection/feature";
|
|
17
|
-
export * from "./features/checkboxes/feature";
|
|
18
16
|
export * from "./features/hotkeys-core/feature";
|
|
19
17
|
export * from "./features/async-data-loader/feature";
|
|
20
18
|
export * from "./features/sync-data-loader/feature";
|
package/lib/esm/index.js
CHANGED
|
@@ -4,7 +4,6 @@ export * from "./features/tree/types";
|
|
|
4
4
|
export * from "./features/drag-and-drop/types";
|
|
5
5
|
export * from "./features/keyboard-drag-and-drop/types";
|
|
6
6
|
export * from "./features/selection/types";
|
|
7
|
-
export * from "./features/checkboxes/types";
|
|
8
7
|
export * from "./features/async-data-loader/types";
|
|
9
8
|
export * from "./features/sync-data-loader/types";
|
|
10
9
|
export * from "./features/hotkeys-core/types";
|
|
@@ -13,7 +12,6 @@ export * from "./features/renaming/types";
|
|
|
13
12
|
export * from "./features/expand-all/types";
|
|
14
13
|
export * from "./features/prop-memoization/types";
|
|
15
14
|
export * from "./features/selection/feature";
|
|
16
|
-
export * from "./features/checkboxes/feature";
|
|
17
15
|
export * from "./features/hotkeys-core/feature";
|
|
18
16
|
export * from "./features/async-data-loader/feature";
|
|
19
17
|
export * from "./features/sync-data-loader/feature";
|
package/lib/esm/types/core.d.ts
CHANGED
|
@@ -10,7 +10,6 @@ import { RenamingFeatureDef } from "../features/renaming/types";
|
|
|
10
10
|
import { ExpandAllFeatureDef } from "../features/expand-all/types";
|
|
11
11
|
import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
|
|
12
12
|
import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
|
|
13
|
-
import { CheckboxesFeatureDef } from "../features/checkboxes/types";
|
|
14
13
|
export type Updater<T> = T | ((old: T) => T);
|
|
15
14
|
export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
|
|
16
15
|
export type FeatureDef = {
|
|
@@ -35,7 +34,7 @@ type MergedFeatures<F extends FeatureDef> = {
|
|
|
35
34
|
itemInstance: UnionToIntersection<F["itemInstance"]>;
|
|
36
35
|
hotkeys: F["hotkeys"];
|
|
37
36
|
};
|
|
38
|
-
export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> |
|
|
37
|
+
export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | DragAndDropFeatureDef<T> | KeyboardDragAndDropFeatureDef<T> | HotkeysCoreFeatureDef<T> | SyncDataLoaderFeatureDef<T> | AsyncDataLoaderFeatureDef<T> | SearchFeatureDef<T> | RenamingFeatureDef<T> | ExpandAllFeatureDef | PropMemoizationFeatureDef;
|
|
39
38
|
type TreeStateType<T> = MergedFeatures<RegisteredFeatures<T>>["state"];
|
|
40
39
|
export interface TreeState<T> extends TreeStateType<T> {
|
|
41
40
|
}
|
package/package.json
CHANGED
package/src/core/create-tree.ts
CHANGED
|
@@ -151,19 +151,6 @@ export const createTree = <T>(
|
|
|
151
151
|
] as Function;
|
|
152
152
|
externalStateSetter?.(state[stateName]);
|
|
153
153
|
},
|
|
154
|
-
buildItemInstance: ({}, itemId) => {
|
|
155
|
-
const [instance, finalizeInstance] = buildInstance(
|
|
156
|
-
features,
|
|
157
|
-
"itemInstance",
|
|
158
|
-
(instance) => ({
|
|
159
|
-
item: instance,
|
|
160
|
-
tree: treeInstance,
|
|
161
|
-
itemId,
|
|
162
|
-
}),
|
|
163
|
-
);
|
|
164
|
-
finalizeInstance();
|
|
165
|
-
return instance;
|
|
166
|
-
},
|
|
167
154
|
// TODO rebuildSubTree: (itemId: string) => void;
|
|
168
155
|
rebuildTree: () => {
|
|
169
156
|
rebuildItemMeta();
|
|
@@ -20,23 +20,21 @@ const loadItemData = async <T>(tree: TreeInstance<T>, itemId: string) => {
|
|
|
20
20
|
loadingItemData.filter((id) => id !== itemId),
|
|
21
21
|
);
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
delete dataRef.current.awaitingItemDataLoading?.[itemId];
|
|
23
|
+
return item;
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
|
|
28
27
|
const config = tree.getConfig();
|
|
29
28
|
const dataRef = getDataRef(tree);
|
|
29
|
+
let childrenIds: string[];
|
|
30
30
|
|
|
31
31
|
if ("getChildrenWithData" in config.dataLoader) {
|
|
32
32
|
const children = await config.dataLoader.getChildrenWithData(itemId);
|
|
33
|
-
|
|
33
|
+
childrenIds = children.map((c) => c.id);
|
|
34
34
|
dataRef.current.childrenIds[itemId] = childrenIds;
|
|
35
35
|
children.forEach(({ id, data }) => {
|
|
36
36
|
dataRef.current.itemData[id] = data;
|
|
37
37
|
config.onLoadedItem?.(id, data);
|
|
38
|
-
dataRef.current.awaitingItemDataLoading?.[id].forEach((cb) => cb());
|
|
39
|
-
delete dataRef.current.awaitingItemDataLoading?.[id];
|
|
40
38
|
});
|
|
41
39
|
|
|
42
40
|
config.onLoadedChildren?.(itemId, childrenIds);
|
|
@@ -45,7 +43,7 @@ const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
|
|
|
45
43
|
loadingItemData.filter((id) => !childrenIds.includes(id)),
|
|
46
44
|
);
|
|
47
45
|
} else {
|
|
48
|
-
|
|
46
|
+
childrenIds = await config.dataLoader.getChildren(itemId);
|
|
49
47
|
dataRef.current.childrenIds[itemId] = childrenIds;
|
|
50
48
|
config.onLoadedChildren?.(itemId, childrenIds);
|
|
51
49
|
tree.rebuildTree();
|
|
@@ -55,8 +53,7 @@ const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
|
|
|
55
53
|
loadingItemChildrens.filter((id) => id !== itemId),
|
|
56
54
|
);
|
|
57
55
|
|
|
58
|
-
|
|
59
|
-
delete dataRef.current.awaitingItemChildrensLoading?.[itemId];
|
|
56
|
+
return childrenIds;
|
|
60
57
|
};
|
|
61
58
|
|
|
62
59
|
export const asyncDataLoaderFeature: FeatureImplementation = {
|
|
@@ -80,33 +77,25 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
|
|
|
80
77
|
},
|
|
81
78
|
|
|
82
79
|
treeInstance: {
|
|
83
|
-
waitForItemDataLoaded:
|
|
84
|
-
tree.retrieveItemData(itemId);
|
|
85
|
-
if (!tree.getState().loadingItemData.includes(itemId)) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
await new Promise<void>((resolve) => {
|
|
89
|
-
const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
|
|
90
|
-
dataRef.current.awaitingItemDataLoading ??= {};
|
|
91
|
-
dataRef.current.awaitingItemDataLoading[itemId] ??= [];
|
|
92
|
-
dataRef.current.awaitingItemDataLoading[itemId].push(resolve);
|
|
93
|
-
});
|
|
94
|
-
},
|
|
80
|
+
waitForItemDataLoaded: ({ tree }, itemId) => tree.loadItemData(itemId),
|
|
95
81
|
|
|
96
|
-
waitForItemChildrenLoaded:
|
|
97
|
-
tree.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
82
|
+
waitForItemChildrenLoaded: ({ tree }, itemId) =>
|
|
83
|
+
tree.loadChildrenIds(itemId),
|
|
84
|
+
|
|
85
|
+
loadItemData: async ({ tree }, itemId) => {
|
|
86
|
+
return (
|
|
87
|
+
getDataRef(tree).current.itemData[itemId] ??
|
|
88
|
+
(await loadItemData(tree, itemId))
|
|
89
|
+
);
|
|
90
|
+
},
|
|
91
|
+
loadChildrenIds: async ({ tree }, itemId) => {
|
|
92
|
+
return (
|
|
93
|
+
getDataRef(tree).current.childrenIds[itemId] ??
|
|
94
|
+
(await loadChildrenIds(tree, itemId))
|
|
95
|
+
);
|
|
107
96
|
},
|
|
108
97
|
|
|
109
|
-
retrieveItemData: ({ tree }, itemId
|
|
98
|
+
retrieveItemData: ({ tree }, itemId) => {
|
|
110
99
|
const config = tree.getConfig();
|
|
111
100
|
const dataRef = getDataRef(tree);
|
|
112
101
|
|
|
@@ -114,7 +103,7 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
|
|
|
114
103
|
return dataRef.current.itemData[itemId];
|
|
115
104
|
}
|
|
116
105
|
|
|
117
|
-
if (!tree.getState().loadingItemData.includes(itemId)
|
|
106
|
+
if (!tree.getState().loadingItemData.includes(itemId)) {
|
|
118
107
|
tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
|
|
119
108
|
...loadingItemData,
|
|
120
109
|
itemId,
|
|
@@ -126,13 +115,13 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
|
|
|
126
115
|
return config.createLoadingItemData?.() ?? null;
|
|
127
116
|
},
|
|
128
117
|
|
|
129
|
-
retrieveChildrenIds: ({ tree }, itemId
|
|
118
|
+
retrieveChildrenIds: ({ tree }, itemId) => {
|
|
130
119
|
const dataRef = getDataRef(tree);
|
|
131
120
|
if (dataRef.current.childrenIds[itemId]) {
|
|
132
121
|
return dataRef.current.childrenIds[itemId];
|
|
133
122
|
}
|
|
134
123
|
|
|
135
|
-
if (tree.getState().loadingItemChildrens.includes(itemId)
|
|
124
|
+
if (tree.getState().loadingItemChildrens.includes(itemId)) {
|
|
136
125
|
return [];
|
|
137
126
|
}
|
|
138
127
|
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { SetStateFn } from "../../types/core";
|
|
2
2
|
import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
|
|
3
3
|
|
|
4
|
-
type AwaitingLoaderCallbacks = Record<string, (() => void)[]>;
|
|
5
|
-
|
|
6
4
|
export interface AsyncDataLoaderDataRef<T = any> {
|
|
7
5
|
itemData: Record<string, T>;
|
|
8
6
|
childrenIds: Record<string, string[]>;
|
|
9
|
-
awaitingItemDataLoading: AwaitingLoaderCallbacks;
|
|
10
|
-
awaitingItemChildrensLoading: AwaitingLoaderCallbacks;
|
|
11
7
|
}
|
|
12
8
|
|
|
13
9
|
/**
|
|
@@ -32,8 +28,12 @@ export type AsyncDataLoaderFeatureDef<T> = {
|
|
|
32
28
|
onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
|
|
33
29
|
};
|
|
34
30
|
treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"] & {
|
|
31
|
+
/** @deprecated use loadItemData instead */
|
|
35
32
|
waitForItemDataLoaded: (itemId: string) => Promise<void>;
|
|
33
|
+
/** @deprecated use loadChildrenIds instead */
|
|
36
34
|
waitForItemChildrenLoaded: (itemId: string) => Promise<void>;
|
|
35
|
+
loadItemData: (itemId: string) => Promise<T>;
|
|
36
|
+
loadChildrenIds: (itemId: string) => Promise<string[]>;
|
|
37
37
|
};
|
|
38
38
|
itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
|
|
39
39
|
/** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible
|
|
@@ -50,7 +50,7 @@ export const expandAllFeature: FeatureImplementation = {
|
|
|
50
50
|
handler: async (_, tree) => {
|
|
51
51
|
const cancelToken = { current: false };
|
|
52
52
|
const cancelHandler = (e: KeyboardEvent) => {
|
|
53
|
-
if (e.
|
|
53
|
+
if (e.code === "Escape") {
|
|
54
54
|
cancelToken.current = true;
|
|
55
55
|
}
|
|
56
56
|
};
|
|
@@ -63,7 +63,7 @@ export const expandAllFeature: FeatureImplementation = {
|
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
collapseSelected: {
|
|
66
|
-
hotkey: "Control+Shift
|
|
66
|
+
hotkey: "Control+Shift+Minus",
|
|
67
67
|
handler: (_, tree) => {
|
|
68
68
|
tree.getSelectedItems().forEach((item) => item.collapseAll());
|
|
69
69
|
},
|
|
@@ -6,10 +6,13 @@ import {
|
|
|
6
6
|
import { HotkeyConfig, HotkeysCoreDataRef } from "./types";
|
|
7
7
|
|
|
8
8
|
const specialKeys: Record<string, RegExp> = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
// TODO:breaking deprecate auto-lowercase
|
|
10
|
+
letter: /^Key[A-Z]$/,
|
|
11
|
+
letterornumber: /^(Key[A-Z]|Digit[0-9])$/,
|
|
12
|
+
plus: /^(NumpadAdd|Plus)$/,
|
|
13
|
+
minus: /^(NumpadSubtract|Minus)$/,
|
|
14
|
+
control: /^(ControlLeft|ControlRight)$/,
|
|
15
|
+
shift: /^(ShiftLeft|ShiftRight)$/,
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
const testHotkeyMatch = (
|
|
@@ -17,12 +20,28 @@ const testHotkeyMatch = (
|
|
|
17
20
|
tree: TreeInstance<any>,
|
|
18
21
|
hotkey: HotkeyConfig<any>,
|
|
19
22
|
) => {
|
|
20
|
-
const supposedKeys = hotkey.hotkey.toLowerCase().split("+");
|
|
21
|
-
const doKeysMatch = supposedKeys.every((key) =>
|
|
22
|
-
key in specialKeys
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const supposedKeys = hotkey.hotkey.toLowerCase().split("+"); // TODO:breaking deprecate auto-lowercase
|
|
24
|
+
const doKeysMatch = supposedKeys.every((key) => {
|
|
25
|
+
if (key in specialKeys) {
|
|
26
|
+
return [...pressedKeys].some((pressedKey) =>
|
|
27
|
+
specialKeys[key].test(pressedKey),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const pressedKeysLowerCase = [...pressedKeys] // TODO:breaking deprecate auto-lowercase
|
|
32
|
+
.map((k) => k.toLowerCase());
|
|
33
|
+
|
|
34
|
+
if (pressedKeysLowerCase.includes(key.toLowerCase())) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (pressedKeysLowerCase.includes(`key${key.toLowerCase()}`)) {
|
|
39
|
+
// TODO:breaking deprecate e.key character matching
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return false;
|
|
44
|
+
});
|
|
26
45
|
const isEnabled = !hotkey.isEnabled || hotkey.isEnabled(tree);
|
|
27
46
|
const equalCounts = pressedKeys.size === supposedKeys.length;
|
|
28
47
|
return doKeysMatch && isEnabled && equalCounts;
|
|
@@ -50,10 +69,9 @@ export const hotkeysCoreFeature: FeatureImplementation = {
|
|
|
50
69
|
return;
|
|
51
70
|
}
|
|
52
71
|
|
|
53
|
-
const key = e.key.toLowerCase();
|
|
54
72
|
data.current.pressedKeys ??= new Set();
|
|
55
|
-
const newMatch = !data.current.pressedKeys.has(
|
|
56
|
-
data.current.pressedKeys.add(
|
|
73
|
+
const newMatch = !data.current.pressedKeys.has(e.code);
|
|
74
|
+
data.current.pressedKeys.add(e.code);
|
|
57
75
|
|
|
58
76
|
const hotkeyName = findHotkeyMatch(
|
|
59
77
|
data.current.pressedKeys,
|
|
@@ -65,7 +83,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
|
|
|
65
83
|
if (e.target instanceof HTMLInputElement) {
|
|
66
84
|
// JS respects composite keydowns while input elements are focused, and
|
|
67
85
|
// doesnt send the associated keyup events with the same key name
|
|
68
|
-
data.current.pressedKeys.delete(
|
|
86
|
+
data.current.pressedKeys.delete(e.code);
|
|
69
87
|
}
|
|
70
88
|
|
|
71
89
|
if (!hotkeyName) return;
|
|
@@ -90,7 +108,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
|
|
|
90
108
|
|
|
91
109
|
const keyup = (e: KeyboardEvent) => {
|
|
92
110
|
data.current.pressedKeys ??= new Set();
|
|
93
|
-
data.current.pressedKeys.delete(e.
|
|
111
|
+
data.current.pressedKeys.delete(e.code);
|
|
94
112
|
};
|
|
95
113
|
|
|
96
114
|
const reset = () => {
|
|
@@ -187,7 +187,7 @@ export const keyboardDragAndDropFeature: FeatureImplementation = {
|
|
|
187
187
|
|
|
188
188
|
hotkeys: {
|
|
189
189
|
startDrag: {
|
|
190
|
-
hotkey: "Control+Shift+
|
|
190
|
+
hotkey: "Control+Shift+KeyD",
|
|
191
191
|
preventDefault: true,
|
|
192
192
|
isEnabled: (tree) => !tree.getState().dnd,
|
|
193
193
|
handler: (_, tree) => {
|
|
@@ -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>>;
|
|
@@ -144,7 +144,7 @@ export const selectionFeature: FeatureImplementation = {
|
|
|
144
144
|
},
|
|
145
145
|
},
|
|
146
146
|
selectAll: {
|
|
147
|
-
hotkey: "Control+
|
|
147
|
+
hotkey: "Control+KeyA",
|
|
148
148
|
preventDefault: true,
|
|
149
149
|
handler: (e, tree) => {
|
|
150
150
|
tree.setSelectedItems(tree.getItems().map((item) => item.getId()));
|
|
@@ -47,6 +47,9 @@ export const syncDataLoaderFeature: FeatureImplementation = {
|
|
|
47
47
|
(c) => c.data,
|
|
48
48
|
);
|
|
49
49
|
},
|
|
50
|
+
|
|
51
|
+
loadItemData: ({ tree }, itemId) => tree.retrieveItemData(itemId),
|
|
52
|
+
loadChildrenIds: ({ tree }, itemId) => tree.retrieveChildrenIds(itemId),
|
|
50
53
|
},
|
|
51
54
|
|
|
52
55
|
itemInstance: {
|
|
@@ -20,7 +20,7 @@ export type TreeFeatureDef<T> = {
|
|
|
20
20
|
focusedItem: string | null;
|
|
21
21
|
};
|
|
22
22
|
config: {
|
|
23
|
-
isItemFolder: (item: ItemInstance<T>) => boolean;
|
|
23
|
+
isItemFolder: (item: ItemInstance<T>) => boolean;
|
|
24
24
|
getItemName: (item: ItemInstance<T>) => string;
|
|
25
25
|
|
|
26
26
|
onPrimaryAction?: (item: ItemInstance<T>) => void;
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,6 @@ export { MainFeatureDef, InstanceBuilder } from "./features/main/types";
|
|
|
6
6
|
export * from "./features/drag-and-drop/types";
|
|
7
7
|
export * from "./features/keyboard-drag-and-drop/types";
|
|
8
8
|
export * from "./features/selection/types";
|
|
9
|
-
export * from "./features/checkboxes/types";
|
|
10
9
|
export * from "./features/async-data-loader/types";
|
|
11
10
|
export * from "./features/sync-data-loader/types";
|
|
12
11
|
export * from "./features/hotkeys-core/types";
|
|
@@ -16,7 +15,6 @@ export * from "./features/expand-all/types";
|
|
|
16
15
|
export * from "./features/prop-memoization/types";
|
|
17
16
|
|
|
18
17
|
export * from "./features/selection/feature";
|
|
19
|
-
export * from "./features/checkboxes/feature";
|
|
20
18
|
export * from "./features/hotkeys-core/feature";
|
|
21
19
|
export * from "./features/async-data-loader/feature";
|
|
22
20
|
export * from "./features/sync-data-loader/feature";
|
package/src/types/core.ts
CHANGED
|
@@ -13,7 +13,6 @@ import { RenamingFeatureDef } from "../features/renaming/types";
|
|
|
13
13
|
import { ExpandAllFeatureDef } from "../features/expand-all/types";
|
|
14
14
|
import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
|
|
15
15
|
import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
|
|
16
|
-
import { CheckboxesFeatureDef } from "../features/checkboxes/types";
|
|
17
16
|
|
|
18
17
|
export type Updater<T> = T | ((old: T) => T);
|
|
19
18
|
export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
|
|
@@ -54,7 +53,6 @@ export type RegisteredFeatures<T> =
|
|
|
54
53
|
| MainFeatureDef<T>
|
|
55
54
|
| TreeFeatureDef<T>
|
|
56
55
|
| SelectionFeatureDef<T>
|
|
57
|
-
| CheckboxesFeatureDef<T>
|
|
58
56
|
| DragAndDropFeatureDef<T>
|
|
59
57
|
| KeyboardDragAndDropFeatureDef<T>
|
|
60
58
|
| HotkeysCoreFeatureDef<T>
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.checkboxesFeature = void 0;
|
|
4
|
-
const utils_1 = require("../../utils");
|
|
5
|
-
const types_1 = require("./types");
|
|
6
|
-
const errors_1 = require("../../utilities/errors");
|
|
7
|
-
const getAllLoadedDescendants = (tree, itemId) => {
|
|
8
|
-
if (!tree.getConfig().isItemFolder(tree.buildItemInstance(itemId))) {
|
|
9
|
-
return [itemId];
|
|
10
|
-
}
|
|
11
|
-
return tree
|
|
12
|
-
.retrieveChildrenIds(itemId)
|
|
13
|
-
.map((child) => getAllLoadedDescendants(tree, child))
|
|
14
|
-
.flat();
|
|
15
|
-
};
|
|
16
|
-
exports.checkboxesFeature = {
|
|
17
|
-
key: "checkboxes",
|
|
18
|
-
overwrites: ["selection"],
|
|
19
|
-
getInitialState: (initialState) => (Object.assign({ checkedItems: [] }, initialState)),
|
|
20
|
-
getDefaultConfig: (defaultConfig, tree) => {
|
|
21
|
-
var _a;
|
|
22
|
-
const hasAsyncLoader = (_a = defaultConfig.features) === null || _a === void 0 ? void 0 : _a.some((f) => f.key === "async-data-loader");
|
|
23
|
-
if (hasAsyncLoader && !defaultConfig.canCheckFolders) {
|
|
24
|
-
(0, errors_1.throwError)(`!canCheckFolders not supported with async trees`);
|
|
25
|
-
}
|
|
26
|
-
return Object.assign({ setCheckedItems: (0, utils_1.makeStateUpdater)("checkedItems", tree), canCheckFolders: hasAsyncLoader !== null && hasAsyncLoader !== void 0 ? hasAsyncLoader : false }, defaultConfig);
|
|
27
|
-
},
|
|
28
|
-
stateHandlerNames: {
|
|
29
|
-
checkedItems: "setCheckedItems",
|
|
30
|
-
},
|
|
31
|
-
treeInstance: {
|
|
32
|
-
setCheckedItems: ({ tree }, checkedItems) => {
|
|
33
|
-
tree.applySubStateUpdate("checkedItems", checkedItems);
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
itemInstance: {
|
|
37
|
-
getCheckboxProps: ({ item }) => {
|
|
38
|
-
const checkedState = item.getCheckedState();
|
|
39
|
-
return {
|
|
40
|
-
onChange: item.toggleCheckedState,
|
|
41
|
-
checked: checkedState === types_1.CheckedState.Checked,
|
|
42
|
-
ref: (r) => {
|
|
43
|
-
if (r) {
|
|
44
|
-
r.indeterminate = checkedState === types_1.CheckedState.Indeterminate;
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
toggleCheckedState: ({ item }) => {
|
|
50
|
-
if (item.getCheckedState() === types_1.CheckedState.Checked) {
|
|
51
|
-
item.setUnchecked();
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
item.setChecked();
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
getCheckedState: ({ item, tree, itemId }) => {
|
|
58
|
-
const { checkedItems } = tree.getState();
|
|
59
|
-
if (checkedItems.includes(itemId)) {
|
|
60
|
-
return types_1.CheckedState.Checked;
|
|
61
|
-
}
|
|
62
|
-
if (item.isFolder() && !tree.getConfig().canCheckFolders) {
|
|
63
|
-
const descendants = getAllLoadedDescendants(tree, itemId);
|
|
64
|
-
if (descendants.every((d) => checkedItems.includes(d))) {
|
|
65
|
-
return types_1.CheckedState.Checked;
|
|
66
|
-
}
|
|
67
|
-
if (descendants.some((d) => checkedItems.includes(d))) {
|
|
68
|
-
return types_1.CheckedState.Indeterminate;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return types_1.CheckedState.Unchecked;
|
|
72
|
-
},
|
|
73
|
-
setChecked: ({ item, tree, itemId }) => {
|
|
74
|
-
if (!item.isFolder() || tree.getConfig().canCheckFolders) {
|
|
75
|
-
tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
tree.applySubStateUpdate("checkedItems", (items) => [
|
|
79
|
-
...items,
|
|
80
|
-
...getAllLoadedDescendants(tree, itemId),
|
|
81
|
-
]);
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
setUnchecked: ({ item, tree, itemId }) => {
|
|
85
|
-
if (!item.isFolder() || tree.getConfig().canCheckFolders) {
|
|
86
|
-
tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => id !== itemId));
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
const descendants = getAllLoadedDescendants(tree, itemId);
|
|
90
|
-
tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => !descendants.includes(id)));
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { SetStateFn } from "../../types/core";
|
|
2
|
-
export declare enum CheckedState {
|
|
3
|
-
Checked = "checked",
|
|
4
|
-
Unchecked = "unchecked",
|
|
5
|
-
Indeterminate = "indeterminate"
|
|
6
|
-
}
|
|
7
|
-
export type CheckboxesFeatureDef<T> = {
|
|
8
|
-
state: {
|
|
9
|
-
checkedItems: string[];
|
|
10
|
-
};
|
|
11
|
-
config: {
|
|
12
|
-
setCheckedItems?: SetStateFn<string[]>;
|
|
13
|
-
canCheckFolders?: boolean;
|
|
14
|
-
};
|
|
15
|
-
treeInstance: {
|
|
16
|
-
setCheckedItems: (checkedItems: string[]) => void;
|
|
17
|
-
};
|
|
18
|
-
itemInstance: {
|
|
19
|
-
setChecked: () => void;
|
|
20
|
-
setUnchecked: () => void;
|
|
21
|
-
toggleCheckedState: () => void;
|
|
22
|
-
getCheckedState: () => CheckedState;
|
|
23
|
-
getCheckboxProps: () => Record<string, any>;
|
|
24
|
-
};
|
|
25
|
-
hotkeys: never;
|
|
26
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CheckedState = void 0;
|
|
4
|
-
var CheckedState;
|
|
5
|
-
(function (CheckedState) {
|
|
6
|
-
CheckedState["Checked"] = "checked";
|
|
7
|
-
CheckedState["Unchecked"] = "unchecked";
|
|
8
|
-
CheckedState["Indeterminate"] = "indeterminate";
|
|
9
|
-
})(CheckedState || (exports.CheckedState = CheckedState = {}));
|