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