@headless-tree/core 1.2.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/index.d.mts +577 -0
  3. package/dist/index.d.ts +577 -0
  4. package/dist/index.js +2321 -0
  5. package/dist/index.mjs +2276 -0
  6. package/package.json +18 -10
  7. package/src/core/create-tree.ts +26 -15
  8. package/src/features/async-data-loader/feature.ts +5 -0
  9. package/src/features/async-data-loader/types.ts +2 -0
  10. package/src/features/checkboxes/checkboxes.spec.ts +20 -5
  11. package/src/features/checkboxes/feature.ts +31 -16
  12. package/src/features/checkboxes/types.ts +1 -0
  13. package/src/features/drag-and-drop/drag-and-drop.spec.ts +11 -2
  14. package/src/features/drag-and-drop/feature.ts +51 -16
  15. package/src/features/drag-and-drop/types.ts +17 -0
  16. package/src/features/keyboard-drag-and-drop/feature.ts +8 -1
  17. package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +34 -3
  18. package/src/features/main/types.ts +0 -2
  19. package/src/features/sync-data-loader/feature.ts +5 -1
  20. package/src/features/tree/feature.ts +4 -3
  21. package/src/features/tree/tree.spec.ts +14 -4
  22. package/src/test-utils/test-tree-do.ts +2 -0
  23. package/src/test-utils/test-tree.ts +1 -0
  24. package/tsconfig.json +1 -4
  25. package/vitest.config.ts +3 -1
  26. package/lib/cjs/core/build-proxified-instance.d.ts +0 -2
  27. package/lib/cjs/core/build-proxified-instance.js +0 -58
  28. package/lib/cjs/core/build-static-instance.d.ts +0 -2
  29. package/lib/cjs/core/build-static-instance.js +0 -26
  30. package/lib/cjs/core/create-tree.d.ts +0 -2
  31. package/lib/cjs/core/create-tree.js +0 -191
  32. package/lib/cjs/features/async-data-loader/feature.d.ts +0 -2
  33. package/lib/cjs/features/async-data-loader/feature.js +0 -135
  34. package/lib/cjs/features/async-data-loader/types.d.ts +0 -47
  35. package/lib/cjs/features/async-data-loader/types.js +0 -2
  36. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  37. package/lib/cjs/features/checkboxes/feature.js +0 -94
  38. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  39. package/lib/cjs/features/checkboxes/types.js +0 -9
  40. package/lib/cjs/features/drag-and-drop/feature.d.ts +0 -2
  41. package/lib/cjs/features/drag-and-drop/feature.js +0 -205
  42. package/lib/cjs/features/drag-and-drop/types.d.ts +0 -71
  43. package/lib/cjs/features/drag-and-drop/types.js +0 -9
  44. package/lib/cjs/features/drag-and-drop/utils.d.ts +0 -27
  45. package/lib/cjs/features/drag-and-drop/utils.js +0 -182
  46. package/lib/cjs/features/expand-all/feature.d.ts +0 -2
  47. package/lib/cjs/features/expand-all/feature.js +0 -70
  48. package/lib/cjs/features/expand-all/types.d.ts +0 -19
  49. package/lib/cjs/features/expand-all/types.js +0 -2
  50. package/lib/cjs/features/hotkeys-core/feature.d.ts +0 -2
  51. package/lib/cjs/features/hotkeys-core/feature.js +0 -107
  52. package/lib/cjs/features/hotkeys-core/types.d.ts +0 -27
  53. package/lib/cjs/features/hotkeys-core/types.js +0 -2
  54. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  55. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +0 -206
  56. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +0 -27
  57. package/lib/cjs/features/keyboard-drag-and-drop/types.js +0 -11
  58. package/lib/cjs/features/main/types.d.ts +0 -47
  59. package/lib/cjs/features/main/types.js +0 -2
  60. package/lib/cjs/features/prop-memoization/feature.d.ts +0 -2
  61. package/lib/cjs/features/prop-memoization/feature.js +0 -70
  62. package/lib/cjs/features/prop-memoization/types.d.ts +0 -15
  63. package/lib/cjs/features/prop-memoization/types.js +0 -2
  64. package/lib/cjs/features/renaming/feature.d.ts +0 -2
  65. package/lib/cjs/features/renaming/feature.js +0 -86
  66. package/lib/cjs/features/renaming/types.d.ts +0 -27
  67. package/lib/cjs/features/renaming/types.js +0 -2
  68. package/lib/cjs/features/search/feature.d.ts +0 -2
  69. package/lib/cjs/features/search/feature.js +0 -119
  70. package/lib/cjs/features/search/types.d.ts +0 -32
  71. package/lib/cjs/features/search/types.js +0 -2
  72. package/lib/cjs/features/selection/feature.d.ts +0 -2
  73. package/lib/cjs/features/selection/feature.js +0 -132
  74. package/lib/cjs/features/selection/types.d.ts +0 -21
  75. package/lib/cjs/features/selection/types.js +0 -2
  76. package/lib/cjs/features/sync-data-loader/feature.d.ts +0 -2
  77. package/lib/cjs/features/sync-data-loader/feature.js +0 -49
  78. package/lib/cjs/features/sync-data-loader/types.d.ts +0 -28
  79. package/lib/cjs/features/sync-data-loader/types.js +0 -2
  80. package/lib/cjs/features/tree/feature.d.ts +0 -2
  81. package/lib/cjs/features/tree/feature.js +0 -244
  82. package/lib/cjs/features/tree/types.d.ts +0 -63
  83. package/lib/cjs/features/tree/types.js +0 -2
  84. package/lib/cjs/index.d.ts +0 -33
  85. package/lib/cjs/index.js +0 -51
  86. package/lib/cjs/mddocs-entry.d.ts +0 -121
  87. package/lib/cjs/mddocs-entry.js +0 -17
  88. package/lib/cjs/test-utils/test-tree-do.d.ts +0 -23
  89. package/lib/cjs/test-utils/test-tree-do.js +0 -112
  90. package/lib/cjs/test-utils/test-tree-expect.d.ts +0 -17
  91. package/lib/cjs/test-utils/test-tree-expect.js +0 -66
  92. package/lib/cjs/test-utils/test-tree.d.ts +0 -48
  93. package/lib/cjs/test-utils/test-tree.js +0 -207
  94. package/lib/cjs/types/core.d.ts +0 -84
  95. package/lib/cjs/types/core.js +0 -2
  96. package/lib/cjs/types/deep-merge.d.ts +0 -13
  97. package/lib/cjs/types/deep-merge.js +0 -2
  98. package/lib/cjs/utilities/create-on-drop-handler.d.ts +0 -3
  99. package/lib/cjs/utilities/create-on-drop-handler.js +0 -20
  100. package/lib/cjs/utilities/errors.d.ts +0 -2
  101. package/lib/cjs/utilities/errors.js +0 -9
  102. package/lib/cjs/utilities/insert-items-at-target.d.ts +0 -3
  103. package/lib/cjs/utilities/insert-items-at-target.js +0 -40
  104. package/lib/cjs/utilities/remove-items-from-parents.d.ts +0 -2
  105. package/lib/cjs/utilities/remove-items-from-parents.js +0 -32
  106. package/lib/cjs/utils.d.ts +0 -6
  107. package/lib/cjs/utils.js +0 -53
  108. package/lib/esm/core/build-proxified-instance.d.ts +0 -2
  109. package/lib/esm/core/build-proxified-instance.js +0 -54
  110. package/lib/esm/core/build-static-instance.d.ts +0 -2
  111. package/lib/esm/core/build-static-instance.js +0 -22
  112. package/lib/esm/core/create-tree.d.ts +0 -2
  113. package/lib/esm/core/create-tree.js +0 -187
  114. package/lib/esm/features/async-data-loader/feature.d.ts +0 -2
  115. package/lib/esm/features/async-data-loader/feature.js +0 -132
  116. package/lib/esm/features/async-data-loader/types.d.ts +0 -47
  117. package/lib/esm/features/async-data-loader/types.js +0 -1
  118. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  119. package/lib/esm/features/checkboxes/feature.js +0 -91
  120. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  121. package/lib/esm/features/checkboxes/types.js +0 -6
  122. package/lib/esm/features/drag-and-drop/feature.d.ts +0 -2
  123. package/lib/esm/features/drag-and-drop/feature.js +0 -202
  124. package/lib/esm/features/drag-and-drop/types.d.ts +0 -71
  125. package/lib/esm/features/drag-and-drop/types.js +0 -6
  126. package/lib/esm/features/drag-and-drop/utils.d.ts +0 -27
  127. package/lib/esm/features/drag-and-drop/utils.js +0 -172
  128. package/lib/esm/features/expand-all/feature.d.ts +0 -2
  129. package/lib/esm/features/expand-all/feature.js +0 -67
  130. package/lib/esm/features/expand-all/types.d.ts +0 -19
  131. package/lib/esm/features/expand-all/types.js +0 -1
  132. package/lib/esm/features/hotkeys-core/feature.d.ts +0 -2
  133. package/lib/esm/features/hotkeys-core/feature.js +0 -104
  134. package/lib/esm/features/hotkeys-core/types.d.ts +0 -27
  135. package/lib/esm/features/hotkeys-core/types.js +0 -1
  136. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  137. package/lib/esm/features/keyboard-drag-and-drop/feature.js +0 -203
  138. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +0 -27
  139. package/lib/esm/features/keyboard-drag-and-drop/types.js +0 -8
  140. package/lib/esm/features/main/types.d.ts +0 -47
  141. package/lib/esm/features/main/types.js +0 -1
  142. package/lib/esm/features/prop-memoization/feature.d.ts +0 -2
  143. package/lib/esm/features/prop-memoization/feature.js +0 -67
  144. package/lib/esm/features/prop-memoization/types.d.ts +0 -15
  145. package/lib/esm/features/prop-memoization/types.js +0 -1
  146. package/lib/esm/features/renaming/feature.d.ts +0 -2
  147. package/lib/esm/features/renaming/feature.js +0 -83
  148. package/lib/esm/features/renaming/types.d.ts +0 -27
  149. package/lib/esm/features/renaming/types.js +0 -1
  150. package/lib/esm/features/search/feature.d.ts +0 -2
  151. package/lib/esm/features/search/feature.js +0 -116
  152. package/lib/esm/features/search/types.d.ts +0 -32
  153. package/lib/esm/features/search/types.js +0 -1
  154. package/lib/esm/features/selection/feature.d.ts +0 -2
  155. package/lib/esm/features/selection/feature.js +0 -129
  156. package/lib/esm/features/selection/types.d.ts +0 -21
  157. package/lib/esm/features/selection/types.js +0 -1
  158. package/lib/esm/features/sync-data-loader/feature.d.ts +0 -2
  159. package/lib/esm/features/sync-data-loader/feature.js +0 -46
  160. package/lib/esm/features/sync-data-loader/types.d.ts +0 -28
  161. package/lib/esm/features/sync-data-loader/types.js +0 -1
  162. package/lib/esm/features/tree/feature.d.ts +0 -2
  163. package/lib/esm/features/tree/feature.js +0 -241
  164. package/lib/esm/features/tree/types.d.ts +0 -63
  165. package/lib/esm/features/tree/types.js +0 -1
  166. package/lib/esm/index.d.ts +0 -33
  167. package/lib/esm/index.js +0 -32
  168. package/lib/esm/mddocs-entry.d.ts +0 -121
  169. package/lib/esm/mddocs-entry.js +0 -1
  170. package/lib/esm/test-utils/test-tree-do.d.ts +0 -23
  171. package/lib/esm/test-utils/test-tree-do.js +0 -108
  172. package/lib/esm/test-utils/test-tree-expect.d.ts +0 -17
  173. package/lib/esm/test-utils/test-tree-expect.js +0 -62
  174. package/lib/esm/test-utils/test-tree.d.ts +0 -48
  175. package/lib/esm/test-utils/test-tree.js +0 -203
  176. package/lib/esm/types/core.d.ts +0 -84
  177. package/lib/esm/types/core.js +0 -1
  178. package/lib/esm/types/deep-merge.d.ts +0 -13
  179. package/lib/esm/types/deep-merge.js +0 -1
  180. package/lib/esm/utilities/create-on-drop-handler.d.ts +0 -3
  181. package/lib/esm/utilities/create-on-drop-handler.js +0 -16
  182. package/lib/esm/utilities/errors.d.ts +0 -2
  183. package/lib/esm/utilities/errors.js +0 -4
  184. package/lib/esm/utilities/insert-items-at-target.d.ts +0 -3
  185. package/lib/esm/utilities/insert-items-at-target.js +0 -36
  186. package/lib/esm/utilities/remove-items-from-parents.d.ts +0 -2
  187. package/lib/esm/utilities/remove-items-from-parents.js +0 -28
  188. package/lib/esm/utils.d.ts +0 -6
  189. package/lib/esm/utils.js +0 -46
@@ -235,8 +235,8 @@ describe("core-feature/selections", () => {
235
235
  it("generates item props for random item", () => {
236
236
  expect(tree.instance.getItemInstance("x2").getProps()).toEqual({
237
237
  "aria-label": "x2",
238
- "aria-level": 0,
239
- "aria-posinset": 1,
238
+ "aria-level": 1,
239
+ "aria-posinset": 2,
240
240
  "aria-selected": "false",
241
241
  "aria-setsize": 4,
242
242
  onClick: expect.any(Function),
@@ -249,8 +249,8 @@ describe("core-feature/selections", () => {
249
249
  it("generates item props for focused", () => {
250
250
  expect(tree.instance.getItemInstance("x1").getProps()).toEqual({
251
251
  "aria-label": "x1",
252
- "aria-level": 0,
253
- "aria-posinset": 0,
252
+ "aria-level": 1,
253
+ "aria-posinset": 1,
254
254
  "aria-selected": "false",
255
255
  "aria-setsize": 4,
256
256
  onClick: expect.any(Function),
@@ -472,4 +472,14 @@ describe("core-feature/selections", () => {
472
472
  });
473
473
  });
474
474
  });
475
+
476
+ describe("empty rootItemId", () => {
477
+ factory.with({ rootItemId: "" }).forSuits((tree) => {
478
+ describe("focused item", () => {
479
+ it("returns correct initial focused item", () => {
480
+ expect(tree.instance.getFocusedItem().getId()).toBe("1");
481
+ });
482
+ });
483
+ });
484
+ });
475
485
  });
@@ -105,12 +105,14 @@ export class TestTreeDo<T> {
105
105
  dragEnd(itemId: string, event?: DragEvent) {
106
106
  const e = event ?? TestTree.dragEvent();
107
107
  this.itemProps(itemId).onDragEnd(e);
108
+ window.dispatchEvent(new CustomEvent("dragend"));
108
109
  return e;
109
110
  }
110
111
 
111
112
  async drop(itemId: string, event?: DragEvent) {
112
113
  const e = event ?? TestTree.dragEvent();
113
114
  await this.itemProps(itemId).onDrop(e);
115
+ window.dispatchEvent(new CustomEvent("dragend"));
114
116
  return e;
115
117
  }
116
118
 
@@ -137,6 +137,7 @@ export class TestTree<T = string> {
137
137
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
138
138
  this.instance;
139
139
  await this.resolveAsyncVisibleItems();
140
+ this.instance.registerElement({ getBoundingClientRect: () => null } as any);
140
141
  return this;
141
142
  }
142
143
 
package/tsconfig.json CHANGED
@@ -1,8 +1,5 @@
1
1
  {
2
2
  "extends": "../../tsconfig.json",
3
3
  "include": ["./src/**/*"],
4
- "exclude": ["./src/**/*.spec.tsx", "./src/**/*.spec.ts", "./src/**/*.stories.tsx"],
5
- "compilerOptions": {
6
- "outDir": "lib/esm"
7
- }
4
+ "exclude": ["./src/**/*.spec.tsx", "./src/**/*.spec.ts", "./src/**/*.stories.tsx"]
8
5
  }
package/vitest.config.ts CHANGED
@@ -2,5 +2,7 @@
2
2
  import { defineConfig } from "vitest/config";
3
3
 
4
4
  export default defineConfig({
5
- test: {},
5
+ test: {
6
+ environment: "jsdom",
7
+ },
6
8
  });
@@ -1,2 +0,0 @@
1
- import { InstanceBuilder } from "../features/main/types";
2
- export declare const buildProxiedInstance: InstanceBuilder;
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.buildProxiedInstance = void 0;
4
- const errors_1 = require("../utilities/errors");
5
- const noop = () => { };
6
- const findPrevInstanceMethod = (features, instanceType, methodKey, featureSearchIndex) => {
7
- var _a;
8
- for (let i = featureSearchIndex; i >= 0; i--) {
9
- const feature = features[i];
10
- const itemInstanceMethod = (_a = feature[instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
11
- if (itemInstanceMethod) {
12
- return i;
13
- }
14
- }
15
- return null;
16
- };
17
- const invokeInstanceMethod = (features, instanceType, opts, methodKey, featureIndex, args) => {
18
- var _a;
19
- const prevIndex = findPrevInstanceMethod(features, instanceType, methodKey, featureIndex - 1);
20
- const itemInstanceMethod = (_a = features[featureIndex][instanceType]) === null || _a === void 0 ? void 0 : _a[methodKey];
21
- return itemInstanceMethod(Object.assign(Object.assign({}, opts), { prev: prevIndex !== null
22
- ? (...newArgs) => invokeInstanceMethod(features, instanceType, opts, methodKey, prevIndex, newArgs)
23
- : null }), ...args);
24
- };
25
- const buildProxiedInstance = (features, instanceType, buildOpts) => {
26
- // demo with prototypes: https://jsfiddle.net/bgenc58r/
27
- const opts = {};
28
- const item = new Proxy({}, {
29
- has(target, key) {
30
- if (typeof key === "symbol") {
31
- return false;
32
- }
33
- if (key === "toJSON") {
34
- return false;
35
- }
36
- const hasInstanceMethod = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
37
- return Boolean(hasInstanceMethod);
38
- },
39
- get(target, key) {
40
- if (typeof key === "symbol") {
41
- return undefined;
42
- }
43
- if (key === "toJSON") {
44
- return {};
45
- }
46
- return (...args) => {
47
- const featureIndex = findPrevInstanceMethod(features, instanceType, key, features.length - 1);
48
- if (featureIndex === null) {
49
- throw (0, errors_1.throwError)(`feature missing for method ${key}`);
50
- }
51
- return invokeInstanceMethod(features, instanceType, opts, key, featureIndex, args);
52
- };
53
- },
54
- });
55
- Object.assign(opts, buildOpts(item));
56
- return [item, noop];
57
- };
58
- exports.buildProxiedInstance = buildProxiedInstance;
@@ -1,2 +0,0 @@
1
- import { InstanceBuilder } from "../features/main/types";
2
- export declare const buildStaticInstance: InstanceBuilder;
@@ -1,26 +0,0 @@
1
- "use strict";
2
- /* eslint-disable no-continue,no-labels,no-extra-label */
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.buildStaticInstance = void 0;
5
- const buildStaticInstance = (features, instanceType, buildOpts) => {
6
- const instance = {};
7
- const finalize = () => {
8
- const opts = buildOpts(instance);
9
- featureLoop: for (let i = 0; i < features.length; i++) {
10
- // Loop goes in forward order, each features overwrite previous ones and wraps those in a prev() fn
11
- const definition = features[i][instanceType];
12
- if (!definition)
13
- continue featureLoop;
14
- methodLoop: for (const [key, method] of Object.entries(definition)) {
15
- if (!method)
16
- continue methodLoop;
17
- const prev = instance[key];
18
- instance[key] = (...args) => {
19
- return method(Object.assign(Object.assign({}, opts), { prev }), ...args);
20
- };
21
- }
22
- }
23
- };
24
- return [instance, finalize];
25
- };
26
- exports.buildStaticInstance = buildStaticInstance;
@@ -1,2 +0,0 @@
1
- import { TreeConfig, TreeInstance } from "../types/core";
2
- export declare const createTree: <T>(initialConfig: TreeConfig<T>) => TreeInstance<T>;
@@ -1,191 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTree = void 0;
4
- const feature_1 = require("../features/tree/feature");
5
- const build_static_instance_1 = require("./build-static-instance");
6
- const errors_1 = require("../utilities/errors");
7
- const verifyFeatures = (features) => {
8
- var _a;
9
- const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key);
10
- for (const feature of features !== null && features !== void 0 ? features : []) {
11
- const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep)));
12
- if (missingDependency) {
13
- throw (0, errors_1.throwError)(`${feature.key} needs ${missingDependency}`);
14
- }
15
- }
16
- };
17
- // Check all possible pairs and sort the array
18
- const exhaustiveSort = (arr, compareFn) => {
19
- const n = arr.length;
20
- for (let i = 0; i < n; i++) {
21
- for (let j = i + 1; j < n; j++) {
22
- if (compareFn(arr[j], arr[i]) < 0) {
23
- [arr[i], arr[j]] = [arr[j], arr[i]];
24
- }
25
- }
26
- }
27
- return arr;
28
- };
29
- const compareFeatures = (originalOrder) => (feature1, feature2) => {
30
- var _a, _b;
31
- if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) {
32
- return 1;
33
- }
34
- if (feature1.key && ((_b = feature2.overwrites) === null || _b === void 0 ? void 0 : _b.includes(feature1.key))) {
35
- return -1;
36
- }
37
- return originalOrder.indexOf(feature1) - originalOrder.indexOf(feature2);
38
- };
39
- const sortFeatures = (features = []) => exhaustiveSort(features, compareFeatures(features));
40
- const createTree = (initialConfig) => {
41
- var _a, _b, _c, _d;
42
- const buildInstance = (_a = initialConfig.instanceBuilder) !== null && _a !== void 0 ? _a : build_static_instance_1.buildStaticInstance;
43
- const additionalFeatures = [
44
- feature_1.treeFeature,
45
- ...sortFeatures(initialConfig.features),
46
- ];
47
- verifyFeatures(additionalFeatures);
48
- const features = [...additionalFeatures];
49
- const [treeInstance, finalizeTree] = buildInstance(features, "treeInstance", (tree) => ({ tree }));
50
- let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_c = (_b = initialConfig.initialState) !== null && _b !== void 0 ? _b : initialConfig.state) !== null && _c !== void 0 ? _c : {});
51
- let config = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getDefaultConfig) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, initialConfig);
52
- const stateHandlerNames = additionalFeatures.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature.stateHandlerNames)), {});
53
- let treeElement;
54
- const treeDataRef = { current: {} };
55
- const itemInstancesMap = {};
56
- let itemInstances = [];
57
- const itemElementsMap = {};
58
- const itemDataRefs = {};
59
- let itemMetaMap = {};
60
- const hotkeyPresets = {};
61
- const rebuildItemMeta = () => {
62
- // TODO can we find a way to only run this for the changed substructure?
63
- itemInstances = [];
64
- itemMetaMap = {};
65
- const [rootInstance, finalizeRootInstance] = buildInstance(features, "itemInstance", (item) => ({ item, tree: treeInstance, itemId: config.rootItemId }));
66
- finalizeRootInstance();
67
- itemInstancesMap[config.rootItemId] = rootInstance;
68
- itemMetaMap[config.rootItemId] = {
69
- itemId: config.rootItemId,
70
- index: -1,
71
- parentId: null,
72
- level: -1,
73
- posInSet: 0,
74
- setSize: 1,
75
- };
76
- for (const item of treeInstance.getItemsMeta()) {
77
- itemMetaMap[item.itemId] = item;
78
- if (!itemInstancesMap[item.itemId]) {
79
- const [instance, finalizeInstance] = buildInstance(features, "itemInstance", (instance) => ({
80
- item: instance,
81
- tree: treeInstance,
82
- itemId: item.itemId,
83
- }));
84
- finalizeInstance();
85
- itemInstancesMap[item.itemId] = instance;
86
- itemInstances.push(instance);
87
- }
88
- else {
89
- itemInstances.push(itemInstancesMap[item.itemId]);
90
- }
91
- }
92
- };
93
- const eachFeature = (fn) => {
94
- for (const feature of additionalFeatures) {
95
- fn(feature);
96
- }
97
- };
98
- const mainFeature = {
99
- key: "main",
100
- treeInstance: {
101
- getState: () => state,
102
- setState: ({}, updater) => {
103
- var _a;
104
- // Not necessary, since I think the subupdate below keeps the state fresh anyways?
105
- // state = typeof updater === "function" ? updater(state) : updater;
106
- (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state); // TODO this cant be right... This doesnt allow external state updates
107
- // TODO this is never used, remove
108
- },
109
- applySubStateUpdate: ({}, stateName, updater) => {
110
- state[stateName] =
111
- typeof updater === "function" ? updater(state[stateName]) : updater;
112
- const externalStateSetter = config[stateHandlerNames[stateName]];
113
- externalStateSetter === null || externalStateSetter === void 0 ? void 0 : externalStateSetter(state[stateName]);
114
- },
115
- buildItemInstance: ({}, itemId) => {
116
- const [instance, finalizeInstance] = buildInstance(features, "itemInstance", (instance) => ({
117
- item: instance,
118
- tree: treeInstance,
119
- itemId,
120
- }));
121
- finalizeInstance();
122
- return instance;
123
- },
124
- // TODO rebuildSubTree: (itemId: string) => void;
125
- rebuildTree: () => {
126
- var _a;
127
- rebuildItemMeta();
128
- (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
129
- },
130
- getConfig: () => config,
131
- setConfig: (_, updater) => {
132
- var _a, _b, _c;
133
- const newConfig = typeof updater === "function" ? updater(config) : updater;
134
- const hasChangedExpandedItems = ((_a = newConfig.state) === null || _a === void 0 ? void 0 : _a.expandedItems) &&
135
- ((_b = newConfig.state) === null || _b === void 0 ? void 0 : _b.expandedItems) !== state.expandedItems;
136
- config = newConfig;
137
- if (newConfig.state) {
138
- state = Object.assign(Object.assign({}, state), newConfig.state);
139
- }
140
- if (hasChangedExpandedItems) {
141
- // if expanded items where changed from the outside
142
- rebuildItemMeta();
143
- (_c = config.setState) === null || _c === void 0 ? void 0 : _c.call(config, state);
144
- }
145
- },
146
- getItemInstance: ({}, itemId) => itemInstancesMap[itemId],
147
- getItems: () => itemInstances,
148
- registerElement: ({}, element) => {
149
- if (treeElement === element) {
150
- return;
151
- }
152
- if (treeElement && !element) {
153
- eachFeature((feature) => { var _a; return (_a = feature.onTreeUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, treeElement); });
154
- }
155
- else if (!treeElement && element) {
156
- eachFeature((feature) => { var _a; return (_a = feature.onTreeMount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, element); });
157
- }
158
- treeElement = element;
159
- },
160
- getElement: () => treeElement,
161
- getDataRef: () => treeDataRef,
162
- getHotkeyPresets: () => hotkeyPresets,
163
- },
164
- itemInstance: {
165
- registerElement: ({ itemId, item }, element) => {
166
- if (itemElementsMap[itemId] === element) {
167
- return;
168
- }
169
- const oldElement = itemElementsMap[itemId];
170
- if (oldElement && !element) {
171
- eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, item, oldElement, treeInstance); });
172
- }
173
- else if (!oldElement && element) {
174
- eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature, item, element, treeInstance); });
175
- }
176
- itemElementsMap[itemId] = element;
177
- },
178
- getElement: ({ itemId }) => itemElementsMap[itemId],
179
- // eslint-disable-next-line no-return-assign
180
- getDataRef: ({ itemId }) => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); },
181
- getItemMeta: ({ itemId }) => itemMetaMap[itemId],
182
- },
183
- };
184
- features.unshift(mainFeature);
185
- for (const feature of features) {
186
- Object.assign(hotkeyPresets, (_d = feature.hotkeys) !== null && _d !== void 0 ? _d : {});
187
- }
188
- finalizeTree();
189
- return treeInstance;
190
- };
191
- exports.createTree = createTree;
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const asyncDataLoaderFeature: FeatureImplementation;
@@ -1,135 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.asyncDataLoaderFeature = void 0;
13
- const utils_1 = require("../../utils");
14
- const getDataRef = (tree) => {
15
- var _a, _b;
16
- var _c, _d;
17
- const dataRef = tree.getDataRef();
18
- (_a = (_c = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_c.itemData = {});
19
- (_b = (_d = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_d.childrenIds = {});
20
- return dataRef;
21
- };
22
- const loadItemData = (tree, itemId) => __awaiter(void 0, void 0, void 0, function* () {
23
- var _a;
24
- const config = tree.getConfig();
25
- const dataRef = getDataRef(tree);
26
- const item = yield config.dataLoader.getItem(itemId);
27
- dataRef.current.itemData[itemId] = item;
28
- (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, itemId, item);
29
- tree.applySubStateUpdate("loadingItemData", (loadingItemData) => loadingItemData.filter((id) => id !== itemId));
30
- return item;
31
- });
32
- const loadChildrenIds = (tree, itemId) => __awaiter(void 0, void 0, void 0, function* () {
33
- var _a, _b;
34
- const config = tree.getConfig();
35
- const dataRef = getDataRef(tree);
36
- let childrenIds;
37
- if ("getChildrenWithData" in config.dataLoader) {
38
- const children = yield config.dataLoader.getChildrenWithData(itemId);
39
- childrenIds = children.map((c) => c.id);
40
- dataRef.current.childrenIds[itemId] = childrenIds;
41
- children.forEach(({ id, data }) => {
42
- var _a;
43
- dataRef.current.itemData[id] = data;
44
- (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, id, data);
45
- });
46
- (_a = config.onLoadedChildren) === null || _a === void 0 ? void 0 : _a.call(config, itemId, childrenIds);
47
- tree.rebuildTree();
48
- tree.applySubStateUpdate("loadingItemData", (loadingItemData) => loadingItemData.filter((id) => !childrenIds.includes(id)));
49
- }
50
- else {
51
- childrenIds = yield config.dataLoader.getChildren(itemId);
52
- dataRef.current.childrenIds[itemId] = childrenIds;
53
- (_b = config.onLoadedChildren) === null || _b === void 0 ? void 0 : _b.call(config, itemId, childrenIds);
54
- tree.rebuildTree();
55
- }
56
- tree.applySubStateUpdate("loadingItemChildrens", (loadingItemChildrens) => loadingItemChildrens.filter((id) => id !== itemId));
57
- return childrenIds;
58
- });
59
- exports.asyncDataLoaderFeature = {
60
- key: "async-data-loader",
61
- getInitialState: (initialState) => (Object.assign({ loadingItemData: [], loadingItemChildrens: [] }, initialState)),
62
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItemData: (0, utils_1.makeStateUpdater)("loadingItemData", tree), setLoadingItemChildrens: (0, utils_1.makeStateUpdater)("loadingItemChildrens", tree) }, defaultConfig)),
63
- stateHandlerNames: {
64
- loadingItemData: "setLoadingItemData",
65
- loadingItemChildrens: "setLoadingItemChildrens",
66
- },
67
- treeInstance: {
68
- waitForItemDataLoaded: ({ tree }, itemId) => tree.loadItemData(itemId),
69
- waitForItemChildrenLoaded: ({ tree }, itemId) => tree.loadChildrenIds(itemId),
70
- loadItemData: (_a, itemId_1) => __awaiter(void 0, [_a, itemId_1], void 0, function* ({ tree }, itemId) {
71
- var _b;
72
- return ((_b = getDataRef(tree).current.itemData[itemId]) !== null && _b !== void 0 ? _b : (yield loadItemData(tree, itemId)));
73
- }),
74
- loadChildrenIds: (_a, itemId_1) => __awaiter(void 0, [_a, itemId_1], void 0, function* ({ tree }, itemId) {
75
- var _b;
76
- return ((_b = getDataRef(tree).current.childrenIds[itemId]) !== null && _b !== void 0 ? _b : (yield loadChildrenIds(tree, itemId)));
77
- }),
78
- retrieveItemData: ({ tree }, itemId, skipFetch = false) => {
79
- var _a, _b;
80
- const config = tree.getConfig();
81
- const dataRef = getDataRef(tree);
82
- if (dataRef.current.itemData[itemId]) {
83
- return dataRef.current.itemData[itemId];
84
- }
85
- if (!tree.getState().loadingItemData.includes(itemId) && !skipFetch) {
86
- tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
87
- ...loadingItemData,
88
- itemId,
89
- ]);
90
- loadItemData(tree, itemId);
91
- }
92
- return (_b = (_a = config.createLoadingItemData) === null || _a === void 0 ? void 0 : _a.call(config)) !== null && _b !== void 0 ? _b : null;
93
- },
94
- retrieveChildrenIds: ({ tree }, itemId, skipFetch = false) => {
95
- const dataRef = getDataRef(tree);
96
- if (dataRef.current.childrenIds[itemId]) {
97
- return dataRef.current.childrenIds[itemId];
98
- }
99
- if (tree.getState().loadingItemChildrens.includes(itemId) || skipFetch) {
100
- return [];
101
- }
102
- tree.applySubStateUpdate("loadingItemChildrens", (loadingItemChildrens) => [...loadingItemChildrens, itemId]);
103
- loadChildrenIds(tree, itemId);
104
- return [];
105
- },
106
- },
107
- itemInstance: {
108
- isLoading: ({ tree, item }) => tree.getState().loadingItemData.includes(item.getItemMeta().itemId) ||
109
- tree.getState().loadingItemChildrens.includes(item.getItemMeta().itemId),
110
- invalidateItemData: (_a, optimistic_1) => __awaiter(void 0, [_a, optimistic_1], void 0, function* ({ tree, itemId }, optimistic) {
111
- var _b;
112
- if (!optimistic) {
113
- (_b = getDataRef(tree).current.itemData) === null || _b === void 0 ? true : delete _b[itemId];
114
- tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
115
- ...loadingItemData,
116
- itemId,
117
- ]);
118
- }
119
- yield loadItemData(tree, itemId);
120
- }),
121
- invalidateChildrenIds: (_a, optimistic_1) => __awaiter(void 0, [_a, optimistic_1], void 0, function* ({ tree, itemId }, optimistic) {
122
- var _b;
123
- if (!optimistic) {
124
- (_b = getDataRef(tree).current.childrenIds) === null || _b === void 0 ? true : delete _b[itemId];
125
- tree.applySubStateUpdate("loadingItemChildrens", (loadingItemChildrens) => [...loadingItemChildrens, itemId]);
126
- }
127
- yield loadChildrenIds(tree, itemId);
128
- }),
129
- updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
130
- const dataRef = tree.getDataRef();
131
- dataRef.current.childrenIds[itemId] = childrenIds;
132
- tree.rebuildTree();
133
- },
134
- },
135
- };
@@ -1,47 +0,0 @@
1
- import { SetStateFn } from "../../types/core";
2
- import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
3
- export interface AsyncDataLoaderDataRef<T = any> {
4
- itemData: Record<string, T>;
5
- childrenIds: Record<string, string[]>;
6
- }
7
- /**
8
- * @category Async Data Loader/General
9
- * */
10
- export type AsyncDataLoaderFeatureDef<T> = {
11
- state: {
12
- loadingItemData: string[];
13
- loadingItemChildrens: string[];
14
- };
15
- config: {
16
- rootItemId: string;
17
- /** Will be called when HT retrieves item data for an item whose item data is asynchronously being loaded.
18
- * Can be used to create placeholder data to use for rendering the tree item while it is loaded. If not defined,
19
- * the tree item data will be null. */
20
- createLoadingItemData?: () => T;
21
- setLoadingItemData?: SetStateFn<string[]>;
22
- setLoadingItemChildrens?: SetStateFn<string[]>;
23
- onLoadedItem?: (itemId: string, item: T) => void;
24
- onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
25
- };
26
- treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"] & {
27
- /** @deprecated use loadItemData instead */
28
- waitForItemDataLoaded: (itemId: string) => Promise<void>;
29
- /** @deprecated use loadChildrenIds instead */
30
- waitForItemChildrenLoaded: (itemId: string) => Promise<void>;
31
- loadItemData: (itemId: string) => Promise<T>;
32
- loadChildrenIds: (itemId: string) => Promise<string[]>;
33
- };
34
- itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
35
- /** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible
36
- * @param optimistic If true, the item will not trigger a state update on `loadingItemData`, and
37
- * the tree will continue to display the old data until the new data has loaded. */
38
- invalidateItemData: (optimistic?: boolean) => Promise<void>;
39
- /** Invalidate fetched children ids for item, and triggers a refetch and subsequent rerender if the item is visible
40
- * @param optimistic If true, the item will not trigger a state update on `loadingItemChildrens`, and
41
- * the tree will continue to display the old data until the new data has loaded. */
42
- invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
43
- updateCachedChildrenIds: (childrenIds: string[]) => void;
44
- isLoading: () => boolean;
45
- };
46
- hotkeys: SyncDataLoaderFeatureDef<T>["hotkeys"];
47
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const checkboxesFeature: FeatureImplementation;
@@ -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
- };