@headless-tree/core 0.0.10 → 0.0.12
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 +12 -0
- package/lib/cjs/core/build-proxified-instance.d.ts +2 -0
- package/lib/cjs/core/build-proxified-instance.js +58 -0
- package/lib/cjs/core/build-static-instance.d.ts +2 -0
- package/lib/cjs/core/build-static-instance.js +26 -0
- package/lib/cjs/core/create-tree.js +62 -40
- package/lib/cjs/features/async-data-loader/feature.d.ts +1 -4
- package/lib/cjs/features/async-data-loader/feature.js +35 -23
- package/lib/cjs/features/async-data-loader/types.d.ts +4 -6
- package/lib/cjs/features/drag-and-drop/feature.d.ts +2 -3
- package/lib/cjs/features/drag-and-drop/feature.js +79 -44
- package/lib/cjs/features/drag-and-drop/types.d.ts +15 -6
- package/lib/cjs/features/drag-and-drop/utils.d.ts +2 -3
- package/lib/cjs/features/drag-and-drop/utils.js +140 -37
- package/lib/cjs/features/expand-all/feature.d.ts +1 -5
- package/lib/cjs/features/expand-all/feature.js +12 -6
- package/lib/cjs/features/hotkeys-core/feature.d.ts +1 -3
- package/lib/cjs/features/main/types.d.ts +8 -2
- package/lib/cjs/features/prop-memoization/feature.d.ts +2 -0
- package/lib/cjs/features/prop-memoization/feature.js +48 -0
- package/lib/cjs/features/prop-memoization/types.d.ts +10 -0
- package/lib/cjs/features/prop-memoization/types.js +2 -0
- package/lib/cjs/features/renaming/feature.d.ts +1 -4
- package/lib/cjs/features/renaming/feature.js +36 -22
- package/lib/cjs/features/renaming/types.d.ts +2 -2
- package/lib/cjs/features/search/feature.d.ts +1 -4
- package/lib/cjs/features/search/feature.js +38 -24
- package/lib/cjs/features/search/types.d.ts +0 -1
- package/lib/cjs/features/selection/feature.d.ts +1 -4
- package/lib/cjs/features/selection/feature.js +54 -35
- package/lib/cjs/features/selection/types.d.ts +1 -1
- package/lib/cjs/features/sync-data-loader/feature.d.ts +1 -3
- package/lib/cjs/features/sync-data-loader/feature.js +7 -2
- package/lib/cjs/features/tree/feature.d.ts +1 -5
- package/lib/cjs/features/tree/feature.js +97 -92
- package/lib/cjs/features/tree/types.d.ts +5 -8
- package/lib/cjs/index.d.ts +5 -1
- package/lib/cjs/index.js +4 -1
- package/lib/cjs/mddocs-entry.d.ts +10 -0
- package/lib/cjs/test-utils/test-tree-do.d.ts +23 -0
- package/lib/cjs/test-utils/test-tree-do.js +99 -0
- package/lib/cjs/test-utils/test-tree-expect.d.ts +15 -0
- package/lib/cjs/test-utils/test-tree-expect.js +62 -0
- package/lib/cjs/test-utils/test-tree.d.ts +47 -0
- package/lib/cjs/test-utils/test-tree.js +203 -0
- package/lib/cjs/types/core.d.ts +39 -24
- package/lib/cjs/utilities/errors.d.ts +1 -0
- package/lib/cjs/utilities/errors.js +5 -0
- package/lib/cjs/utilities/insert-items-at-target.js +10 -3
- package/lib/cjs/utilities/remove-items-from-parents.js +14 -8
- package/lib/cjs/utils.d.ts +3 -3
- package/lib/cjs/utils.js +6 -6
- package/lib/esm/core/build-proxified-instance.d.ts +2 -0
- package/lib/esm/core/build-proxified-instance.js +54 -0
- package/lib/esm/core/build-static-instance.d.ts +2 -0
- package/lib/esm/core/build-static-instance.js +22 -0
- package/lib/esm/core/create-tree.js +62 -40
- package/lib/esm/features/async-data-loader/feature.d.ts +1 -4
- package/lib/esm/features/async-data-loader/feature.js +35 -23
- package/lib/esm/features/async-data-loader/types.d.ts +4 -6
- package/lib/esm/features/drag-and-drop/feature.d.ts +2 -3
- package/lib/esm/features/drag-and-drop/feature.js +79 -44
- package/lib/esm/features/drag-and-drop/types.d.ts +15 -6
- package/lib/esm/features/drag-and-drop/utils.d.ts +2 -3
- package/lib/esm/features/drag-and-drop/utils.js +138 -34
- package/lib/esm/features/expand-all/feature.d.ts +1 -5
- package/lib/esm/features/expand-all/feature.js +12 -6
- package/lib/esm/features/hotkeys-core/feature.d.ts +1 -3
- package/lib/esm/features/main/types.d.ts +8 -2
- package/lib/esm/features/prop-memoization/feature.d.ts +2 -0
- package/lib/esm/features/prop-memoization/feature.js +45 -0
- package/lib/esm/features/prop-memoization/types.d.ts +10 -0
- package/lib/esm/features/prop-memoization/types.js +1 -0
- package/lib/esm/features/renaming/feature.d.ts +1 -4
- package/lib/esm/features/renaming/feature.js +36 -22
- package/lib/esm/features/renaming/types.d.ts +2 -2
- package/lib/esm/features/search/feature.d.ts +1 -4
- package/lib/esm/features/search/feature.js +38 -24
- package/lib/esm/features/search/types.d.ts +0 -1
- package/lib/esm/features/selection/feature.d.ts +1 -4
- package/lib/esm/features/selection/feature.js +54 -35
- package/lib/esm/features/selection/types.d.ts +1 -1
- package/lib/esm/features/sync-data-loader/feature.d.ts +1 -3
- package/lib/esm/features/sync-data-loader/feature.js +7 -2
- package/lib/esm/features/tree/feature.d.ts +1 -5
- package/lib/esm/features/tree/feature.js +98 -93
- package/lib/esm/features/tree/types.d.ts +5 -8
- package/lib/esm/index.d.ts +5 -1
- package/lib/esm/index.js +4 -1
- package/lib/esm/mddocs-entry.d.ts +10 -0
- package/lib/esm/test-utils/test-tree-do.d.ts +23 -0
- package/lib/esm/test-utils/test-tree-do.js +95 -0
- package/lib/esm/test-utils/test-tree-expect.d.ts +15 -0
- package/lib/esm/test-utils/test-tree-expect.js +58 -0
- package/lib/esm/test-utils/test-tree.d.ts +47 -0
- package/lib/esm/test-utils/test-tree.js +199 -0
- package/lib/esm/types/core.d.ts +39 -24
- package/lib/esm/utilities/errors.d.ts +1 -0
- package/lib/esm/utilities/errors.js +1 -0
- package/lib/esm/utilities/insert-items-at-target.js +10 -3
- package/lib/esm/utilities/remove-items-from-parents.js +14 -8
- package/lib/esm/utils.d.ts +3 -3
- package/lib/esm/utils.js +3 -3
- package/package.json +7 -3
- package/src/core/build-proxified-instance.ts +117 -0
- package/src/core/build-static-instance.ts +27 -0
- package/src/core/core.spec.ts +210 -0
- package/src/core/create-tree.ts +73 -78
- package/src/features/async-data-loader/async-data-loader.spec.ts +124 -0
- package/src/features/async-data-loader/feature.ts +34 -44
- package/src/features/async-data-loader/types.ts +4 -6
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +717 -0
- package/src/features/drag-and-drop/feature.ts +88 -63
- package/src/features/drag-and-drop/types.ts +24 -10
- package/src/features/drag-and-drop/utils.ts +197 -56
- package/src/features/expand-all/expand-all.spec.ts +56 -0
- package/src/features/expand-all/feature.ts +9 -24
- package/src/features/hotkeys-core/feature.ts +5 -14
- package/src/features/main/types.ts +14 -1
- package/src/features/prop-memoization/feature.ts +51 -0
- package/src/features/prop-memoization/prop-memoization.spec.ts +68 -0
- package/src/features/prop-memoization/types.ts +11 -0
- package/src/features/renaming/feature.ts +37 -45
- package/src/features/renaming/renaming.spec.ts +127 -0
- package/src/features/renaming/types.ts +2 -2
- package/src/features/search/feature.ts +36 -46
- package/src/features/search/search.spec.ts +117 -0
- package/src/features/search/types.ts +0 -1
- package/src/features/selection/feature.ts +50 -53
- package/src/features/selection/selection.spec.ts +219 -0
- package/src/features/selection/types.ts +0 -2
- package/src/features/sync-data-loader/feature.ts +9 -18
- package/src/features/tree/feature.ts +101 -144
- package/src/features/tree/tree.spec.ts +475 -0
- package/src/features/tree/types.ts +5 -9
- package/src/index.ts +6 -1
- package/src/mddocs-entry.ts +13 -0
- package/src/test-utils/test-tree-do.ts +136 -0
- package/src/test-utils/test-tree-expect.ts +86 -0
- package/src/test-utils/test-tree.ts +227 -0
- package/src/types/core.ts +76 -108
- package/src/utilities/errors.ts +2 -0
- package/src/utilities/insert-items-at-target.ts +10 -3
- package/src/utilities/remove-items-from-parents.ts +15 -10
- package/src/utils.spec.ts +89 -0
- package/src/utils.ts +6 -6
- package/tsconfig.json +1 -0
- package/vitest.config.ts +6 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { throwError } from "../utilities/errors";
|
|
2
|
+
const noop = () => { };
|
|
3
|
+
const findPrevInstanceMethod = (features, instanceType, methodKey, featureSearchIndex) => {
|
|
4
|
+
var _a;
|
|
5
|
+
for (let i = featureSearchIndex; i >= 0; i--) {
|
|
6
|
+
const feature = features[i];
|
|
7
|
+
const itemInstanceMethod = (_a = feature[instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
|
|
8
|
+
if (itemInstanceMethod) {
|
|
9
|
+
return i;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
const invokeInstanceMethod = (features, instanceType, opts, methodKey, featureIndex, args) => {
|
|
15
|
+
var _a;
|
|
16
|
+
const prevIndex = findPrevInstanceMethod(features, instanceType, methodKey, featureIndex - 1);
|
|
17
|
+
const itemInstanceMethod = (_a = features[featureIndex][instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
|
|
18
|
+
return itemInstanceMethod(Object.assign(Object.assign({}, opts), { prev: prevIndex !== null
|
|
19
|
+
? (...newArgs) => invokeInstanceMethod(features, instanceType, opts, methodKey, prevIndex, newArgs)
|
|
20
|
+
: null }), ...args);
|
|
21
|
+
};
|
|
22
|
+
export const buildProxiedInstance = (features, instanceType, buildOpts) => {
|
|
23
|
+
// demo with prototypes: https://jsfiddle.net/bgenc58r/
|
|
24
|
+
const opts = {};
|
|
25
|
+
const item = new Proxy({}, {
|
|
26
|
+
has(target, key) {
|
|
27
|
+
if (typeof key === "symbol") {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (key === "toJSON") {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
const hasInstanceMethod = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
|
|
34
|
+
return Boolean(hasInstanceMethod);
|
|
35
|
+
},
|
|
36
|
+
get(target, key) {
|
|
37
|
+
if (typeof key === "symbol") {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
if (key === "toJSON") {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
return (...args) => {
|
|
44
|
+
const featureIndex = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
|
|
45
|
+
if (featureIndex === null) {
|
|
46
|
+
throw throwError(`feature missing for method ${key}`);
|
|
47
|
+
}
|
|
48
|
+
return invokeInstanceMethod(features, instanceType, opts, key, featureIndex, args);
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
Object.assign(opts, buildOpts(item));
|
|
53
|
+
return [item, noop];
|
|
54
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* eslint-disable no-continue,no-labels,no-extra-label */
|
|
2
|
+
export const buildStaticInstance = (features, instanceType, buildOpts) => {
|
|
3
|
+
const instance = {};
|
|
4
|
+
const finalize = () => {
|
|
5
|
+
const opts = buildOpts(instance);
|
|
6
|
+
featureLoop: for (let i = 0; i < features.length; i++) {
|
|
7
|
+
// Loop goes in forward order, each features overwrite previous ones and wraps those in a prev() fn
|
|
8
|
+
const definition = features[i][instanceType];
|
|
9
|
+
if (!definition)
|
|
10
|
+
continue featureLoop;
|
|
11
|
+
methodLoop: for (const [key, method] of Object.entries(definition)) {
|
|
12
|
+
if (!method)
|
|
13
|
+
continue methodLoop;
|
|
14
|
+
const prev = instance[key];
|
|
15
|
+
instance[key] = (...args) => {
|
|
16
|
+
return method(Object.assign(Object.assign({}, opts), { prev }), ...args);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
return [instance, finalize];
|
|
22
|
+
};
|
|
@@ -1,42 +1,38 @@
|
|
|
1
1
|
import { treeFeature } from "../features/tree/feature";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const itemInstance = {};
|
|
5
|
-
for (const feature of features) {
|
|
6
|
-
Object.assign(
|
|
7
|
-
// TODO dont run createItemInstance, but assign prototype objects instead?
|
|
8
|
-
// https://jsfiddle.net/bgenc58r/
|
|
9
|
-
itemInstance, (_b = (_a = feature.createItemInstance) === null || _a === void 0 ? void 0 : _a.call(feature, Object.assign({}, itemInstance), itemInstance, tree, itemId)) !== null && _b !== void 0 ? _b : {});
|
|
10
|
-
}
|
|
11
|
-
return itemInstance;
|
|
12
|
-
};
|
|
2
|
+
import { buildStaticInstance } from "./build-static-instance";
|
|
3
|
+
import { throwError } from "../utilities/errors";
|
|
13
4
|
const verifyFeatures = (features) => {
|
|
14
5
|
var _a;
|
|
15
6
|
const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key);
|
|
16
7
|
for (const feature of features !== null && features !== void 0 ? features : []) {
|
|
17
8
|
const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep)));
|
|
18
9
|
if (missingDependency) {
|
|
19
|
-
throw
|
|
10
|
+
throw throwError(`${feature.key} needs ${missingDependency}`);
|
|
20
11
|
}
|
|
21
12
|
}
|
|
22
13
|
};
|
|
23
|
-
const compareFeatures = (feature1, feature2) => {
|
|
24
|
-
var _a;
|
|
14
|
+
const compareFeatures = (originalOrder) => (feature1, feature2) => {
|
|
15
|
+
var _a, _b;
|
|
25
16
|
if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) {
|
|
26
17
|
return 1;
|
|
27
18
|
}
|
|
28
|
-
|
|
19
|
+
if (feature1.key && ((_b = feature2.overwrites) === null || _b === void 0 ? void 0 : _b.includes(feature1.key))) {
|
|
20
|
+
return -1;
|
|
21
|
+
}
|
|
22
|
+
return originalOrder.indexOf(feature1) - originalOrder.indexOf(feature2);
|
|
29
23
|
};
|
|
30
|
-
const sortFeatures = (features = []) => features.sort(compareFeatures);
|
|
24
|
+
const sortFeatures = (features = []) => features.sort(compareFeatures(features));
|
|
31
25
|
export const createTree = (initialConfig) => {
|
|
32
|
-
var _a, _b, _c, _d
|
|
33
|
-
const
|
|
26
|
+
var _a, _b, _c, _d;
|
|
27
|
+
const buildInstance = (_a = initialConfig.instanceBuilder) !== null && _a !== void 0 ? _a : buildStaticInstance;
|
|
34
28
|
const additionalFeatures = [
|
|
35
29
|
treeFeature,
|
|
36
30
|
...sortFeatures(initialConfig.features),
|
|
37
31
|
];
|
|
38
32
|
verifyFeatures(additionalFeatures);
|
|
39
|
-
|
|
33
|
+
const features = [...additionalFeatures];
|
|
34
|
+
const [treeInstance, finalizeTree] = buildInstance(features, "treeInstance", (tree) => ({ tree }));
|
|
35
|
+
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 : {});
|
|
40
36
|
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);
|
|
41
37
|
const stateHandlerNames = additionalFeatures.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature.stateHandlerNames)), {});
|
|
42
38
|
let treeElement;
|
|
@@ -47,11 +43,12 @@ export const createTree = (initialConfig) => {
|
|
|
47
43
|
const itemDataRefs = {};
|
|
48
44
|
let itemMetaMap = {};
|
|
49
45
|
const hotkeyPresets = {};
|
|
50
|
-
const rebuildItemMeta = (
|
|
46
|
+
const rebuildItemMeta = () => {
|
|
51
47
|
// TODO can we find a way to only run this for the changed substructure?
|
|
52
48
|
itemInstances = [];
|
|
53
49
|
itemMetaMap = {};
|
|
54
|
-
const rootInstance =
|
|
50
|
+
const [rootInstance, finalizeRootInstance] = buildInstance(features, "itemInstance", (item) => ({ item, tree: treeInstance, itemId: config.rootItemId }));
|
|
51
|
+
finalizeRootInstance();
|
|
55
52
|
itemInstancesMap[config.rootItemId] = rootInstance;
|
|
56
53
|
itemMetaMap[config.rootItemId] = {
|
|
57
54
|
itemId: config.rootItemId,
|
|
@@ -64,7 +61,12 @@ export const createTree = (initialConfig) => {
|
|
|
64
61
|
for (const item of treeInstance.getItemsMeta()) {
|
|
65
62
|
itemMetaMap[item.itemId] = item;
|
|
66
63
|
if (!itemInstancesMap[item.itemId]) {
|
|
67
|
-
const instance =
|
|
64
|
+
const [instance, finalizeInstance] = buildInstance(features, "itemInstance", (instance) => ({
|
|
65
|
+
item: instance,
|
|
66
|
+
tree: treeInstance,
|
|
67
|
+
itemId: item.itemId,
|
|
68
|
+
}));
|
|
69
|
+
finalizeInstance();
|
|
68
70
|
itemInstancesMap[item.itemId] = instance;
|
|
69
71
|
itemInstances.push(instance);
|
|
70
72
|
}
|
|
@@ -80,25 +82,36 @@ export const createTree = (initialConfig) => {
|
|
|
80
82
|
};
|
|
81
83
|
const mainFeature = {
|
|
82
84
|
key: "main",
|
|
83
|
-
|
|
85
|
+
treeInstance: {
|
|
86
|
+
getState: () => state,
|
|
87
|
+
setState: ({}, updater) => {
|
|
84
88
|
var _a;
|
|
85
89
|
// Not necessary, since I think the subupdate below keeps the state fresh anyways?
|
|
86
90
|
// state = typeof updater === "function" ? updater(state) : updater;
|
|
87
|
-
(_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
|
|
88
|
-
},
|
|
91
|
+
(_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state); // TODO this cant be right... This doesnt allow external state updates
|
|
92
|
+
},
|
|
93
|
+
applySubStateUpdate: ({}, stateName, updater) => {
|
|
89
94
|
state[stateName] =
|
|
90
95
|
typeof updater === "function" ? updater(state[stateName]) : updater;
|
|
91
|
-
config[stateHandlerNames[stateName]]
|
|
92
|
-
|
|
96
|
+
const externalStateSetter = config[stateHandlerNames[stateName]];
|
|
97
|
+
externalStateSetter === null || externalStateSetter === void 0 ? void 0 : externalStateSetter(state[stateName]);
|
|
98
|
+
},
|
|
99
|
+
// TODO rebuildSubTree: (itemId: string) => void;
|
|
100
|
+
rebuildTree: () => {
|
|
93
101
|
var _a;
|
|
94
|
-
rebuildItemMeta(
|
|
102
|
+
rebuildItemMeta();
|
|
95
103
|
(_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
|
|
96
|
-
},
|
|
104
|
+
},
|
|
105
|
+
getConfig: () => config,
|
|
106
|
+
setConfig: (_, updater) => {
|
|
97
107
|
config = typeof updater === "function" ? updater(config) : updater;
|
|
98
108
|
if (config.state) {
|
|
99
109
|
state = Object.assign(Object.assign({}, state), config.state);
|
|
100
110
|
}
|
|
101
|
-
},
|
|
111
|
+
},
|
|
112
|
+
getItemInstance: ({}, itemId) => itemInstancesMap[itemId],
|
|
113
|
+
getItems: () => itemInstances,
|
|
114
|
+
registerElement: ({}, element) => {
|
|
102
115
|
if (treeElement === element) {
|
|
103
116
|
return;
|
|
104
117
|
}
|
|
@@ -109,28 +122,37 @@ export const createTree = (initialConfig) => {
|
|
|
109
122
|
eachFeature((feature) => { var _a; return (_a = feature.onTreeMount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, element); });
|
|
110
123
|
}
|
|
111
124
|
treeElement = element;
|
|
112
|
-
},
|
|
113
|
-
|
|
125
|
+
},
|
|
126
|
+
getElement: () => treeElement,
|
|
127
|
+
getDataRef: () => treeDataRef,
|
|
128
|
+
getHotkeyPresets: () => hotkeyPresets,
|
|
129
|
+
},
|
|
130
|
+
itemInstance: {
|
|
131
|
+
// TODO just change to a getRef method that memoizes, maybe as part of getProps
|
|
132
|
+
registerElement: ({ itemId, item }, element) => {
|
|
114
133
|
if (itemElementsMap[itemId] === element) {
|
|
115
134
|
return;
|
|
116
135
|
}
|
|
117
136
|
const oldElement = itemElementsMap[itemId];
|
|
118
137
|
if (oldElement && !element) {
|
|
119
|
-
eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature,
|
|
138
|
+
eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, item, oldElement, treeInstance); });
|
|
120
139
|
}
|
|
121
140
|
else if (!oldElement && element) {
|
|
122
|
-
eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature,
|
|
141
|
+
eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature, item, element, treeInstance); });
|
|
123
142
|
}
|
|
124
143
|
itemElementsMap[itemId] = element;
|
|
125
|
-
},
|
|
144
|
+
},
|
|
145
|
+
getElement: ({ itemId }) => itemElementsMap[itemId],
|
|
126
146
|
// eslint-disable-next-line no-return-assign
|
|
127
|
-
getDataRef: () => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); },
|
|
147
|
+
getDataRef: ({ itemId }) => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); },
|
|
148
|
+
getItemMeta: ({ itemId }) => itemMetaMap[itemId],
|
|
149
|
+
},
|
|
128
150
|
};
|
|
129
|
-
|
|
151
|
+
features.unshift(mainFeature);
|
|
130
152
|
for (const feature of features) {
|
|
131
|
-
Object.assign(
|
|
132
|
-
Object.assign(hotkeyPresets, (_e = feature.hotkeys) !== null && _e !== void 0 ? _e : {});
|
|
153
|
+
Object.assign(hotkeyPresets, (_d = feature.hotkeys) !== null && _d !== void 0 ? _d : {});
|
|
133
154
|
}
|
|
134
|
-
|
|
155
|
+
finalizeTree();
|
|
156
|
+
rebuildItemMeta();
|
|
135
157
|
return treeInstance;
|
|
136
158
|
};
|
|
@@ -1,5 +1,2 @@
|
|
|
1
1
|
import { FeatureImplementation } from "../../types/core";
|
|
2
|
-
|
|
3
|
-
import { MainFeatureDef } from "../main/types";
|
|
4
|
-
import { TreeFeatureDef } from "../tree/types";
|
|
5
|
-
export declare const asyncDataLoaderFeature: FeatureImplementation<any, AsyncDataLoaderFeatureDef<any>, MainFeatureDef | TreeFeatureDef<any> | AsyncDataLoaderFeatureDef<any>>;
|
|
2
|
+
export declare const asyncDataLoaderFeature: FeatureImplementation;
|
|
@@ -6,18 +6,19 @@ export const asyncDataLoaderFeature = {
|
|
|
6
6
|
stateHandlerNames: {
|
|
7
7
|
loadingItems: "setLoadingItems",
|
|
8
8
|
},
|
|
9
|
-
|
|
9
|
+
treeInstance: {
|
|
10
|
+
retrieveItemData: ({ tree }, itemId) => {
|
|
10
11
|
var _a, _b, _c, _d, _e;
|
|
11
12
|
var _f, _g;
|
|
12
|
-
const config =
|
|
13
|
-
const dataRef =
|
|
13
|
+
const config = tree.getConfig();
|
|
14
|
+
const dataRef = tree.getDataRef();
|
|
14
15
|
(_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
|
|
15
16
|
(_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
|
|
16
17
|
if (dataRef.current.itemData[itemId]) {
|
|
17
18
|
return dataRef.current.itemData[itemId];
|
|
18
19
|
}
|
|
19
|
-
if (!
|
|
20
|
-
|
|
20
|
+
if (!tree.getState().loadingItems.includes(itemId)) {
|
|
21
|
+
tree.applySubStateUpdate("loadingItems", (loadingItems) => [
|
|
21
22
|
...loadingItems,
|
|
22
23
|
itemId,
|
|
23
24
|
]);
|
|
@@ -25,24 +26,25 @@ export const asyncDataLoaderFeature = {
|
|
|
25
26
|
var _a;
|
|
26
27
|
dataRef.current.itemData[itemId] = item;
|
|
27
28
|
(_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, itemId, item);
|
|
28
|
-
|
|
29
|
+
tree.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
|
|
29
30
|
});
|
|
30
31
|
}
|
|
31
32
|
return (_e = (_d = config.createLoadingItemData) === null || _d === void 0 ? void 0 : _d.call(config)) !== null && _e !== void 0 ? _e : null;
|
|
32
|
-
},
|
|
33
|
+
},
|
|
34
|
+
retrieveChildrenIds: ({ tree }, itemId) => {
|
|
33
35
|
var _a, _b, _c, _d, _e;
|
|
34
36
|
var _f, _g;
|
|
35
|
-
const config =
|
|
36
|
-
const dataRef =
|
|
37
|
+
const config = tree.getConfig();
|
|
38
|
+
const dataRef = tree.getDataRef();
|
|
37
39
|
(_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
|
|
38
40
|
(_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
|
|
39
41
|
if (dataRef.current.childrenIds[itemId]) {
|
|
40
42
|
return dataRef.current.childrenIds[itemId];
|
|
41
43
|
}
|
|
42
|
-
if (
|
|
44
|
+
if (tree.getState().loadingItems.includes(itemId)) {
|
|
43
45
|
return [];
|
|
44
46
|
}
|
|
45
|
-
|
|
47
|
+
tree.applySubStateUpdate("loadingItems", (loadingItems) => [
|
|
46
48
|
...loadingItems,
|
|
47
49
|
itemId,
|
|
48
50
|
]);
|
|
@@ -56,8 +58,8 @@ export const asyncDataLoaderFeature = {
|
|
|
56
58
|
const childrenIds = children.map(({ id }) => id);
|
|
57
59
|
dataRef.current.childrenIds[itemId] = childrenIds;
|
|
58
60
|
(_b = config.onLoadedChildren) === null || _b === void 0 ? void 0 : _b.call(config, itemId, childrenIds);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
tree.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
|
|
62
|
+
tree.rebuildTree();
|
|
61
63
|
});
|
|
62
64
|
}
|
|
63
65
|
else {
|
|
@@ -65,21 +67,31 @@ export const asyncDataLoaderFeature = {
|
|
|
65
67
|
var _a;
|
|
66
68
|
dataRef.current.childrenIds[itemId] = childrenIds;
|
|
67
69
|
(_a = config.onLoadedChildren) === null || _a === void 0 ? void 0 : _a.call(config, itemId, childrenIds);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
tree.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
|
|
71
|
+
tree.rebuildTree();
|
|
70
72
|
});
|
|
71
73
|
}
|
|
72
74
|
return [];
|
|
73
|
-
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
itemInstance: {
|
|
78
|
+
isLoading: ({ tree, item }) => tree.getState().loadingItems.includes(item.getItemMeta().itemId),
|
|
79
|
+
invalidateItemData: ({ tree, itemId }) => {
|
|
74
80
|
var _a;
|
|
75
|
-
const dataRef =
|
|
81
|
+
const dataRef = tree.getDataRef();
|
|
76
82
|
(_a = dataRef.current.itemData) === null || _a === void 0 ? true : delete _a[itemId];
|
|
77
|
-
|
|
78
|
-
},
|
|
83
|
+
tree.retrieveItemData(itemId);
|
|
84
|
+
},
|
|
85
|
+
invalidateChildrenIds: ({ tree, itemId }) => {
|
|
79
86
|
var _a;
|
|
80
|
-
const dataRef =
|
|
87
|
+
const dataRef = tree.getDataRef();
|
|
81
88
|
(_a = dataRef.current.childrenIds) === null || _a === void 0 ? true : delete _a[itemId];
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
89
|
+
tree.retrieveChildrenIds(itemId);
|
|
90
|
+
},
|
|
91
|
+
updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
|
|
92
|
+
const dataRef = tree.getDataRef();
|
|
93
|
+
dataRef.current.childrenIds[itemId] = childrenIds;
|
|
94
|
+
tree.rebuildTree();
|
|
95
|
+
},
|
|
96
|
+
},
|
|
85
97
|
};
|
|
@@ -27,15 +27,13 @@ export type AsyncDataLoaderFeatureDef<T> = {
|
|
|
27
27
|
onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
|
|
28
28
|
asyncDataLoader?: AsyncTreeDataLoader<T>;
|
|
29
29
|
};
|
|
30
|
-
treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"]
|
|
31
|
-
/** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible */
|
|
32
|
-
invalidateItemData: (itemId: string) => void;
|
|
33
|
-
invalidateChildrenIds: (itemId: string) => void;
|
|
34
|
-
};
|
|
30
|
+
treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"];
|
|
35
31
|
itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
|
|
32
|
+
/** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible */
|
|
36
33
|
invalidateItemData: () => void;
|
|
37
34
|
invalidateChildrenIds: () => void;
|
|
38
|
-
|
|
35
|
+
updateCachedChildrenIds: (childrenIds: string[]) => void;
|
|
36
|
+
isLoading: () => boolean;
|
|
39
37
|
};
|
|
40
38
|
hotkeys: SyncDataLoaderFeatureDef<T>["hotkeys"];
|
|
41
39
|
};
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare const dragAndDropFeature: FeatureImplementation<any, DragAndDropFeatureDef<any>, FeatureDefs<any>>;
|
|
1
|
+
import { FeatureImplementation } from "../../types/core";
|
|
2
|
+
export declare const dragAndDropFeature: FeatureImplementation;
|
|
@@ -1,47 +1,69 @@
|
|
|
1
1
|
import { canDrop, getDragCode, getDropTarget } from "./utils";
|
|
2
2
|
import { makeStateUpdater } from "../../utils";
|
|
3
3
|
export const dragAndDropFeature = {
|
|
4
|
-
key: "
|
|
4
|
+
key: "drag-and-drop",
|
|
5
5
|
deps: ["selection"],
|
|
6
|
-
getDefaultConfig: (defaultConfig, tree) => (Object.assign({ canDrop: (_, target) => target.item.isFolder(), canDropForeignDragObject: () => false, setDndState: makeStateUpdater("dnd", tree) }, defaultConfig)),
|
|
6
|
+
getDefaultConfig: (defaultConfig, tree) => (Object.assign({ canDrop: (_, target) => target.item.isFolder(), canDropForeignDragObject: () => false, setDndState: makeStateUpdater("dnd", tree), canReorder: true }, defaultConfig)),
|
|
7
7
|
stateHandlerNames: {
|
|
8
8
|
dnd: "setDndState",
|
|
9
9
|
},
|
|
10
|
-
|
|
10
|
+
treeInstance: {
|
|
11
|
+
getDropTarget: ({ tree }) => {
|
|
11
12
|
var _a, _b;
|
|
12
13
|
return (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.dragTarget) !== null && _b !== void 0 ? _b : null;
|
|
13
|
-
},
|
|
14
|
-
|
|
14
|
+
},
|
|
15
|
+
getDragLineData: ({ tree }) => {
|
|
16
|
+
var _a, _b, _c, _d, _e, _f;
|
|
15
17
|
const target = tree.getDropTarget();
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
+
const indent = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1;
|
|
19
|
+
const treeBb = (_b = tree.getElement()) === null || _b === void 0 ? void 0 : _b.getBoundingClientRect();
|
|
20
|
+
if (!target || !treeBb || target.childIndex === null)
|
|
18
21
|
return null;
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
const leftOffset = target.dragLineLevel * ((_c = tree.getConfig().indent) !== null && _c !== void 0 ? _c : 1);
|
|
23
|
+
const targetItem = tree.getItems()[target.dragLineIndex];
|
|
24
|
+
if (!targetItem) {
|
|
25
|
+
const bb = (_e = (_d = tree
|
|
26
|
+
.getItems()[target.dragLineIndex - 1]) === null || _d === void 0 ? void 0 : _d.getElement()) === null || _e === void 0 ? void 0 : _e.getBoundingClientRect();
|
|
22
27
|
if (bb) {
|
|
23
28
|
return {
|
|
24
|
-
|
|
25
|
-
top: bb.bottom,
|
|
26
|
-
left: bb.left,
|
|
27
|
-
|
|
29
|
+
indent,
|
|
30
|
+
top: bb.bottom - treeBb.bottom,
|
|
31
|
+
left: bb.left + leftOffset - treeBb.left,
|
|
32
|
+
width: bb.width - leftOffset,
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
}
|
|
31
|
-
const bb = (
|
|
36
|
+
const bb = (_f = targetItem.getElement()) === null || _f === void 0 ? void 0 : _f.getBoundingClientRect();
|
|
32
37
|
if (bb) {
|
|
33
38
|
return {
|
|
34
|
-
|
|
35
|
-
top: bb.top,
|
|
36
|
-
left: bb.left,
|
|
37
|
-
|
|
39
|
+
indent,
|
|
40
|
+
top: bb.top - treeBb.top,
|
|
41
|
+
left: bb.left + leftOffset - treeBb.left,
|
|
42
|
+
width: bb.width - leftOffset,
|
|
38
43
|
};
|
|
39
44
|
}
|
|
40
45
|
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
46
|
+
},
|
|
47
|
+
getDragLineStyle: ({ tree }, topOffset = -1, leftOffset = -8) => {
|
|
48
|
+
const dragLine = tree.getDragLineData();
|
|
49
|
+
return dragLine
|
|
50
|
+
? {
|
|
51
|
+
top: `${dragLine.top + topOffset}px`,
|
|
52
|
+
left: `${dragLine.left + leftOffset}px`,
|
|
53
|
+
width: `${dragLine.width - leftOffset}px`,
|
|
54
|
+
pointerEvents: "none", // important to prevent capturing drag events
|
|
55
|
+
}
|
|
56
|
+
: { display: "none" };
|
|
57
|
+
},
|
|
58
|
+
getContainerProps: ({ prev }) => {
|
|
59
|
+
const prevProps = prev === null || prev === void 0 ? void 0 : prev();
|
|
60
|
+
return Object.assign(Object.assign({}, prevProps), { style: Object.assign(Object.assign({}, prevProps === null || prevProps === void 0 ? void 0 : prevProps.style), { position: "relative" }) });
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
itemInstance: {
|
|
64
|
+
getProps: ({ tree, item, prev }) => {
|
|
43
65
|
var _a, _b, _c;
|
|
44
|
-
return (Object.assign(Object.assign({}, prev
|
|
66
|
+
return (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: (e) => {
|
|
45
67
|
var _a, _b, _c;
|
|
46
68
|
const selectedItems = tree.getSelectedItems();
|
|
47
69
|
const items = selectedItems.includes(item) ? selectedItems : [item];
|
|
@@ -61,37 +83,45 @@ export const dragAndDropFeature = {
|
|
|
61
83
|
draggedItems: items,
|
|
62
84
|
draggingOverItem: tree.getFocusedItem(),
|
|
63
85
|
});
|
|
64
|
-
}
|
|
86
|
+
}, onDragOver: (e) => {
|
|
65
87
|
var _a, _b, _c;
|
|
66
|
-
const target = getDropTarget(e, item, tree);
|
|
67
88
|
const dataRef = tree.getDataRef();
|
|
68
|
-
|
|
69
|
-
|
|
89
|
+
const nextDragCode = getDragCode(e, item, tree);
|
|
90
|
+
if (nextDragCode === dataRef.current.lastDragCode) {
|
|
91
|
+
if (dataRef.current.lastAllowDrop) {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
}
|
|
70
94
|
return;
|
|
71
95
|
}
|
|
72
|
-
|
|
96
|
+
dataRef.current.lastDragCode = nextDragCode;
|
|
97
|
+
const target = getDropTarget(e, item, tree);
|
|
98
|
+
if (!((_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) &&
|
|
99
|
+
(!e.dataTransfer ||
|
|
100
|
+
!((_c = (_b = tree
|
|
101
|
+
.getConfig()).canDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(_b, e.dataTransfer, target)))) {
|
|
102
|
+
dataRef.current.lastAllowDrop = false;
|
|
73
103
|
return;
|
|
74
104
|
}
|
|
75
|
-
e.
|
|
76
|
-
|
|
77
|
-
if (nextDragCode === dataRef.current.lastDragCode) {
|
|
105
|
+
if (!canDrop(e.dataTransfer, target, tree)) {
|
|
106
|
+
dataRef.current.lastAllowDrop = false;
|
|
78
107
|
return;
|
|
79
108
|
}
|
|
80
|
-
dataRef.current.lastDragCode = nextDragCode;
|
|
81
109
|
tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
|
|
82
|
-
|
|
110
|
+
dataRef.current.lastAllowDrop = true;
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
}, onDragLeave: () => {
|
|
83
113
|
const dataRef = tree.getDataRef();
|
|
84
114
|
dataRef.current.lastDragCode = "no-drag";
|
|
85
115
|
tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
|
|
86
|
-
}
|
|
87
|
-
var _a, _b, _c;
|
|
116
|
+
}, onDragEnd: (e) => {
|
|
117
|
+
var _a, _b, _c, _d;
|
|
88
118
|
const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
|
|
89
119
|
tree.applySubStateUpdate("dnd", null);
|
|
90
|
-
if (e.dataTransfer.dropEffect === "none" || !draggedItems) {
|
|
120
|
+
if (((_b = e.dataTransfer) === null || _b === void 0 ? void 0 : _b.dropEffect) === "none" || !draggedItems) {
|
|
91
121
|
return;
|
|
92
122
|
}
|
|
93
|
-
(
|
|
94
|
-
}
|
|
123
|
+
(_d = (_c = tree.getConfig()).onCompleteForeignDrop) === null || _d === void 0 ? void 0 : _d.call(_c, draggedItems);
|
|
124
|
+
}, onDrop: (e) => {
|
|
95
125
|
var _a, _b, _c;
|
|
96
126
|
const dataRef = tree.getDataRef();
|
|
97
127
|
const target = getDropTarget(e, item, tree);
|
|
@@ -106,30 +136,35 @@ export const dragAndDropFeature = {
|
|
|
106
136
|
if (draggedItems) {
|
|
107
137
|
(_b = config.onDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target);
|
|
108
138
|
}
|
|
109
|
-
else {
|
|
139
|
+
else if (e.dataTransfer) {
|
|
110
140
|
(_c = config.onDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(config, e.dataTransfer, target);
|
|
111
141
|
}
|
|
112
142
|
// TODO rebuild tree?
|
|
113
|
-
}
|
|
114
|
-
},
|
|
143
|
+
} }));
|
|
144
|
+
},
|
|
145
|
+
isDropTarget: ({ tree, item }) => {
|
|
115
146
|
const target = tree.getDropTarget();
|
|
116
147
|
return target ? target.item.getId() === item.getId() : false;
|
|
117
|
-
},
|
|
148
|
+
},
|
|
149
|
+
isDropTargetAbove: ({ tree, item }) => {
|
|
118
150
|
const target = tree.getDropTarget();
|
|
119
151
|
if (!target ||
|
|
120
152
|
target.childIndex === null ||
|
|
121
153
|
target.item !== item.getParent())
|
|
122
154
|
return false;
|
|
123
155
|
return target.childIndex === item.getItemMeta().posInSet;
|
|
124
|
-
},
|
|
156
|
+
},
|
|
157
|
+
isDropTargetBelow: ({ tree, item }) => {
|
|
125
158
|
const target = tree.getDropTarget();
|
|
126
159
|
if (!target ||
|
|
127
160
|
target.childIndex === null ||
|
|
128
161
|
target.item !== item.getParent())
|
|
129
162
|
return false;
|
|
130
163
|
return target.childIndex - 1 === item.getItemMeta().posInSet;
|
|
131
|
-
},
|
|
164
|
+
},
|
|
165
|
+
isDraggingOver: ({ tree, item }) => {
|
|
132
166
|
var _a, _b;
|
|
133
167
|
return ((_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggingOverItem) === null || _b === void 0 ? void 0 : _b.getId()) === item.getId();
|
|
134
|
-
}
|
|
168
|
+
},
|
|
169
|
+
},
|
|
135
170
|
};
|