@headless-tree/core 0.0.0-20250723222210 → 0.0.0-20250726130412

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 (174) hide show
  1. package/CHANGELOG.md +4 -1
  2. package/dist/index.d.mts +568 -0
  3. package/dist/index.d.ts +568 -0
  4. package/dist/index.js +2284 -0
  5. package/dist/index.mjs +2239 -0
  6. package/package.json +18 -10
  7. package/src/features/checkboxes/checkboxes.spec.ts +20 -5
  8. package/src/features/checkboxes/feature.ts +30 -15
  9. package/src/features/checkboxes/types.ts +1 -0
  10. package/tsconfig.json +1 -4
  11. package/lib/cjs/core/build-proxified-instance.d.ts +0 -2
  12. package/lib/cjs/core/build-proxified-instance.js +0 -58
  13. package/lib/cjs/core/build-static-instance.d.ts +0 -2
  14. package/lib/cjs/core/build-static-instance.js +0 -26
  15. package/lib/cjs/core/create-tree.d.ts +0 -2
  16. package/lib/cjs/core/create-tree.js +0 -191
  17. package/lib/cjs/features/async-data-loader/feature.d.ts +0 -2
  18. package/lib/cjs/features/async-data-loader/feature.js +0 -135
  19. package/lib/cjs/features/async-data-loader/types.d.ts +0 -47
  20. package/lib/cjs/features/async-data-loader/types.js +0 -2
  21. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  22. package/lib/cjs/features/checkboxes/feature.js +0 -94
  23. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  24. package/lib/cjs/features/checkboxes/types.js +0 -9
  25. package/lib/cjs/features/drag-and-drop/feature.d.ts +0 -2
  26. package/lib/cjs/features/drag-and-drop/feature.js +0 -215
  27. package/lib/cjs/features/drag-and-drop/types.d.ts +0 -72
  28. package/lib/cjs/features/drag-and-drop/types.js +0 -9
  29. package/lib/cjs/features/drag-and-drop/utils.d.ts +0 -27
  30. package/lib/cjs/features/drag-and-drop/utils.js +0 -182
  31. package/lib/cjs/features/expand-all/feature.d.ts +0 -2
  32. package/lib/cjs/features/expand-all/feature.js +0 -70
  33. package/lib/cjs/features/expand-all/types.d.ts +0 -19
  34. package/lib/cjs/features/expand-all/types.js +0 -2
  35. package/lib/cjs/features/hotkeys-core/feature.d.ts +0 -2
  36. package/lib/cjs/features/hotkeys-core/feature.js +0 -107
  37. package/lib/cjs/features/hotkeys-core/types.d.ts +0 -27
  38. package/lib/cjs/features/hotkeys-core/types.js +0 -2
  39. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  40. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +0 -206
  41. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +0 -27
  42. package/lib/cjs/features/keyboard-drag-and-drop/types.js +0 -11
  43. package/lib/cjs/features/main/types.d.ts +0 -47
  44. package/lib/cjs/features/main/types.js +0 -2
  45. package/lib/cjs/features/prop-memoization/feature.d.ts +0 -2
  46. package/lib/cjs/features/prop-memoization/feature.js +0 -70
  47. package/lib/cjs/features/prop-memoization/types.d.ts +0 -15
  48. package/lib/cjs/features/prop-memoization/types.js +0 -2
  49. package/lib/cjs/features/renaming/feature.d.ts +0 -2
  50. package/lib/cjs/features/renaming/feature.js +0 -86
  51. package/lib/cjs/features/renaming/types.d.ts +0 -27
  52. package/lib/cjs/features/renaming/types.js +0 -2
  53. package/lib/cjs/features/search/feature.d.ts +0 -2
  54. package/lib/cjs/features/search/feature.js +0 -119
  55. package/lib/cjs/features/search/types.d.ts +0 -32
  56. package/lib/cjs/features/search/types.js +0 -2
  57. package/lib/cjs/features/selection/feature.d.ts +0 -2
  58. package/lib/cjs/features/selection/feature.js +0 -132
  59. package/lib/cjs/features/selection/types.d.ts +0 -21
  60. package/lib/cjs/features/selection/types.js +0 -2
  61. package/lib/cjs/features/sync-data-loader/feature.d.ts +0 -2
  62. package/lib/cjs/features/sync-data-loader/feature.js +0 -53
  63. package/lib/cjs/features/sync-data-loader/types.d.ts +0 -28
  64. package/lib/cjs/features/sync-data-loader/types.js +0 -2
  65. package/lib/cjs/features/tree/feature.d.ts +0 -2
  66. package/lib/cjs/features/tree/feature.js +0 -245
  67. package/lib/cjs/features/tree/types.d.ts +0 -63
  68. package/lib/cjs/features/tree/types.js +0 -2
  69. package/lib/cjs/index.d.ts +0 -33
  70. package/lib/cjs/index.js +0 -51
  71. package/lib/cjs/mddocs-entry.d.ts +0 -121
  72. package/lib/cjs/mddocs-entry.js +0 -17
  73. package/lib/cjs/test-utils/test-tree-do.d.ts +0 -23
  74. package/lib/cjs/test-utils/test-tree-do.js +0 -114
  75. package/lib/cjs/test-utils/test-tree-expect.d.ts +0 -17
  76. package/lib/cjs/test-utils/test-tree-expect.js +0 -66
  77. package/lib/cjs/test-utils/test-tree.d.ts +0 -48
  78. package/lib/cjs/test-utils/test-tree.js +0 -208
  79. package/lib/cjs/types/core.d.ts +0 -84
  80. package/lib/cjs/types/core.js +0 -2
  81. package/lib/cjs/types/deep-merge.d.ts +0 -13
  82. package/lib/cjs/types/deep-merge.js +0 -2
  83. package/lib/cjs/utilities/create-on-drop-handler.d.ts +0 -3
  84. package/lib/cjs/utilities/create-on-drop-handler.js +0 -20
  85. package/lib/cjs/utilities/errors.d.ts +0 -2
  86. package/lib/cjs/utilities/errors.js +0 -9
  87. package/lib/cjs/utilities/insert-items-at-target.d.ts +0 -3
  88. package/lib/cjs/utilities/insert-items-at-target.js +0 -40
  89. package/lib/cjs/utilities/remove-items-from-parents.d.ts +0 -2
  90. package/lib/cjs/utilities/remove-items-from-parents.js +0 -32
  91. package/lib/cjs/utils.d.ts +0 -6
  92. package/lib/cjs/utils.js +0 -53
  93. package/lib/esm/core/build-proxified-instance.d.ts +0 -2
  94. package/lib/esm/core/build-proxified-instance.js +0 -54
  95. package/lib/esm/core/build-static-instance.d.ts +0 -2
  96. package/lib/esm/core/build-static-instance.js +0 -22
  97. package/lib/esm/core/create-tree.d.ts +0 -2
  98. package/lib/esm/core/create-tree.js +0 -187
  99. package/lib/esm/features/async-data-loader/feature.d.ts +0 -2
  100. package/lib/esm/features/async-data-loader/feature.js +0 -132
  101. package/lib/esm/features/async-data-loader/types.d.ts +0 -47
  102. package/lib/esm/features/async-data-loader/types.js +0 -1
  103. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  104. package/lib/esm/features/checkboxes/feature.js +0 -91
  105. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  106. package/lib/esm/features/checkboxes/types.js +0 -6
  107. package/lib/esm/features/drag-and-drop/feature.d.ts +0 -2
  108. package/lib/esm/features/drag-and-drop/feature.js +0 -212
  109. package/lib/esm/features/drag-and-drop/types.d.ts +0 -72
  110. package/lib/esm/features/drag-and-drop/types.js +0 -6
  111. package/lib/esm/features/drag-and-drop/utils.d.ts +0 -27
  112. package/lib/esm/features/drag-and-drop/utils.js +0 -172
  113. package/lib/esm/features/expand-all/feature.d.ts +0 -2
  114. package/lib/esm/features/expand-all/feature.js +0 -67
  115. package/lib/esm/features/expand-all/types.d.ts +0 -19
  116. package/lib/esm/features/expand-all/types.js +0 -1
  117. package/lib/esm/features/hotkeys-core/feature.d.ts +0 -2
  118. package/lib/esm/features/hotkeys-core/feature.js +0 -104
  119. package/lib/esm/features/hotkeys-core/types.d.ts +0 -27
  120. package/lib/esm/features/hotkeys-core/types.js +0 -1
  121. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  122. package/lib/esm/features/keyboard-drag-and-drop/feature.js +0 -203
  123. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +0 -27
  124. package/lib/esm/features/keyboard-drag-and-drop/types.js +0 -8
  125. package/lib/esm/features/main/types.d.ts +0 -47
  126. package/lib/esm/features/main/types.js +0 -1
  127. package/lib/esm/features/prop-memoization/feature.d.ts +0 -2
  128. package/lib/esm/features/prop-memoization/feature.js +0 -67
  129. package/lib/esm/features/prop-memoization/types.d.ts +0 -15
  130. package/lib/esm/features/prop-memoization/types.js +0 -1
  131. package/lib/esm/features/renaming/feature.d.ts +0 -2
  132. package/lib/esm/features/renaming/feature.js +0 -83
  133. package/lib/esm/features/renaming/types.d.ts +0 -27
  134. package/lib/esm/features/renaming/types.js +0 -1
  135. package/lib/esm/features/search/feature.d.ts +0 -2
  136. package/lib/esm/features/search/feature.js +0 -116
  137. package/lib/esm/features/search/types.d.ts +0 -32
  138. package/lib/esm/features/search/types.js +0 -1
  139. package/lib/esm/features/selection/feature.d.ts +0 -2
  140. package/lib/esm/features/selection/feature.js +0 -129
  141. package/lib/esm/features/selection/types.d.ts +0 -21
  142. package/lib/esm/features/selection/types.js +0 -1
  143. package/lib/esm/features/sync-data-loader/feature.d.ts +0 -2
  144. package/lib/esm/features/sync-data-loader/feature.js +0 -50
  145. package/lib/esm/features/sync-data-loader/types.d.ts +0 -28
  146. package/lib/esm/features/sync-data-loader/types.js +0 -1
  147. package/lib/esm/features/tree/feature.d.ts +0 -2
  148. package/lib/esm/features/tree/feature.js +0 -242
  149. package/lib/esm/features/tree/types.d.ts +0 -63
  150. package/lib/esm/features/tree/types.js +0 -1
  151. package/lib/esm/index.d.ts +0 -33
  152. package/lib/esm/index.js +0 -32
  153. package/lib/esm/mddocs-entry.d.ts +0 -121
  154. package/lib/esm/mddocs-entry.js +0 -1
  155. package/lib/esm/test-utils/test-tree-do.d.ts +0 -23
  156. package/lib/esm/test-utils/test-tree-do.js +0 -110
  157. package/lib/esm/test-utils/test-tree-expect.d.ts +0 -17
  158. package/lib/esm/test-utils/test-tree-expect.js +0 -62
  159. package/lib/esm/test-utils/test-tree.d.ts +0 -48
  160. package/lib/esm/test-utils/test-tree.js +0 -204
  161. package/lib/esm/types/core.d.ts +0 -84
  162. package/lib/esm/types/core.js +0 -1
  163. package/lib/esm/types/deep-merge.d.ts +0 -13
  164. package/lib/esm/types/deep-merge.js +0 -1
  165. package/lib/esm/utilities/create-on-drop-handler.d.ts +0 -3
  166. package/lib/esm/utilities/create-on-drop-handler.js +0 -16
  167. package/lib/esm/utilities/errors.d.ts +0 -2
  168. package/lib/esm/utilities/errors.js +0 -4
  169. package/lib/esm/utilities/insert-items-at-target.d.ts +0 -3
  170. package/lib/esm/utilities/insert-items-at-target.js +0 -36
  171. package/lib/esm/utilities/remove-items-from-parents.d.ts +0 -2
  172. package/lib/esm/utilities/remove-items-from-parents.js +0 -28
  173. package/lib/esm/utils.d.ts +0 -6
  174. package/lib/esm/utils.js +0 -46
package/package.json CHANGED
@@ -1,19 +1,26 @@
1
1
  {
2
2
  "name": "@headless-tree/core",
3
- "version": "0.0.0-20250723222210",
4
- "main": "lib/cjs/index.js",
5
- "module": "lib/esm/index.js",
6
- "types": "lib/esm/index.d.ts",
3
+ "version": "0.0.0-20250726130412",
4
+ "main": "dist/index.d.ts",
5
+ "module": "dist/index.mjs",
6
+ "types": "dist/index.d.mts",
7
7
  "exports": {
8
- "types": "./lib/esm/index.d.ts",
9
- "import": "./lib/esm/index.js",
10
- "default": "./lib/cjs/index.js"
8
+ ".": {
9
+ "import": {
10
+ "types": "./dist/index.d.mts",
11
+ "default": "./dist/index.mjs"
12
+ },
13
+ "require": {
14
+ "types": "./dist/index.js",
15
+ "default": "./dist/index.d.ts"
16
+ }
17
+ },
18
+ "./package.json": "./package.json"
11
19
  },
12
20
  "sideEffects": false,
13
21
  "scripts": {
14
- "build:cjs": "tsc -m commonjs --outDir lib/cjs",
15
- "build:esm": "tsc",
16
- "start": "tsc -w",
22
+ "build": "tsup ./src/index.ts --format esm,cjs --dts",
23
+ "start": "tsup ./src/index.ts --format esm,cjs --dts --watch",
17
24
  "test": "vitest run"
18
25
  },
19
26
  "repository": {
@@ -26,6 +33,7 @@
26
33
  "license": "MIT",
27
34
  "devDependencies": {
28
35
  "jsdom": "^26.0.0",
36
+ "tsup": "^8.5.0",
29
37
  "typescript": "^5.7.2",
30
38
  "vitest": "^3.0.3"
31
39
  }
@@ -74,17 +74,28 @@ describe("core-feature/checkboxes", () => {
74
74
  });
75
75
  });
76
76
 
77
- it("should handle folder checking when canCheckFolders is true", async () => {
77
+ it("should handle folder checking", async () => {
78
78
  const tree = await factory
79
- .with({ canCheckFolders: true })
79
+ .with({ canCheckFolders: true, propagateCheckedState: false })
80
80
  .createTestCaseTree();
81
81
 
82
82
  tree.item("x11").setChecked();
83
83
  expect(tree.instance.getState().checkedItems).toContain("x11");
84
84
  });
85
85
 
86
- it("should handle folder checking when canCheckFolders is false", async () => {
87
- const tree = await factory.createTestCaseTree();
86
+ it("should not check folders if disabled", async () => {
87
+ const tree = await factory
88
+ .with({ canCheckFolders: false, propagateCheckedState: false })
89
+ .createTestCaseTree();
90
+
91
+ tree.item("x11").setChecked();
92
+ expect(tree.instance.getState().checkedItems.length).toBe(0);
93
+ });
94
+
95
+ it("should propagate checked state", async () => {
96
+ const tree = await factory
97
+ .with({ propagateCheckedState: true })
98
+ .createTestCaseTree();
88
99
 
89
100
  tree.item("x11").setChecked();
90
101
  expect(tree.instance.getState().checkedItems).toEqual(
@@ -93,7 +104,9 @@ describe("core-feature/checkboxes", () => {
93
104
  });
94
105
 
95
106
  it("should turn folder indeterminate", async () => {
96
- const tree = await factory.createTestCaseTree();
107
+ const tree = await factory
108
+ .with({ propagateCheckedState: true })
109
+ .createTestCaseTree();
97
110
 
98
111
  tree.item("x111").setChecked();
99
112
  expect(tree.item("x11").getCheckedState()).toBe(CheckedState.Indeterminate);
@@ -103,6 +116,8 @@ describe("core-feature/checkboxes", () => {
103
116
  const tree = await factory
104
117
  .with({
105
118
  isItemFolder: (item) => item.getItemData().length < 4,
119
+ propagateCheckedState: true,
120
+ canCheckFolders: false,
106
121
  })
107
122
  .createTestCaseTree();
108
123
 
@@ -6,14 +6,16 @@ import { throwError } from "../../utilities/errors";
6
6
  const getAllLoadedDescendants = <T>(
7
7
  tree: TreeInstance<T>,
8
8
  itemId: string,
9
+ includeFolders = false,
9
10
  ): string[] => {
10
11
  if (!tree.getConfig().isItemFolder(tree.buildItemInstance(itemId))) {
11
12
  return [itemId];
12
13
  }
13
- return tree
14
+ const descendants = tree
14
15
  .retrieveChildrenIds(itemId)
15
- .map((child) => getAllLoadedDescendants(tree, child))
16
+ .map((child) => getAllLoadedDescendants(tree, child, includeFolders))
16
17
  .flat();
18
+ return includeFolders ? [itemId, ...descendants] : descendants;
17
19
  };
18
20
 
19
21
  export const checkboxesFeature: FeatureImplementation = {
@@ -30,12 +32,17 @@ export const checkboxesFeature: FeatureImplementation = {
30
32
  const hasAsyncLoader = defaultConfig.features?.some(
31
33
  (f) => f.key === "async-data-loader",
32
34
  );
33
- if (hasAsyncLoader && !defaultConfig.canCheckFolders) {
34
- throwError(`!canCheckFolders not supported with async trees`);
35
+ if (hasAsyncLoader && defaultConfig.propagateCheckedState) {
36
+ throwError(`propagateCheckedState not supported with async trees`);
35
37
  }
38
+ const propagateCheckedState =
39
+ defaultConfig.propagateCheckedState ?? !hasAsyncLoader;
40
+ const canCheckFolders =
41
+ defaultConfig.canCheckFolders ?? !propagateCheckedState;
36
42
  return {
37
43
  setCheckedItems: makeStateUpdater("checkedItems", tree),
38
- canCheckFolders: hasAsyncLoader ?? false,
44
+ propagateCheckedState,
45
+ canCheckFolders,
39
46
  ...defaultConfig,
40
47
  };
41
48
  },
@@ -72,14 +79,16 @@ export const checkboxesFeature: FeatureImplementation = {
72
79
  }
73
80
  },
74
81
 
75
- getCheckedState: ({ item, tree, itemId }) => {
82
+ getCheckedState: ({ item, tree }) => {
76
83
  const { checkedItems } = tree.getState();
84
+ const { propagateCheckedState } = tree.getConfig();
85
+ const itemId = item.getId();
77
86
 
78
87
  if (checkedItems.includes(itemId)) {
79
88
  return CheckedState.Checked;
80
89
  }
81
90
 
82
- if (item.isFolder() && !tree.getConfig().canCheckFolders) {
91
+ if (item.isFolder() && propagateCheckedState) {
83
92
  const descendants = getAllLoadedDescendants(tree, itemId);
84
93
  if (descendants.every((d) => checkedItems.includes(d))) {
85
94
  return CheckedState.Checked;
@@ -93,25 +102,31 @@ export const checkboxesFeature: FeatureImplementation = {
93
102
  },
94
103
 
95
104
  setChecked: ({ item, tree, itemId }) => {
96
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
97
- tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
98
- } else {
105
+ const { propagateCheckedState, canCheckFolders } = tree.getConfig();
106
+ if (item.isFolder() && propagateCheckedState) {
99
107
  tree.applySubStateUpdate("checkedItems", (items) => [
100
108
  ...items,
101
- ...getAllLoadedDescendants(tree, itemId),
109
+ ...getAllLoadedDescendants(tree, itemId, canCheckFolders),
102
110
  ]);
111
+ } else if (!item.isFolder() || canCheckFolders) {
112
+ tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
103
113
  }
104
114
  },
105
115
 
106
116
  setUnchecked: ({ item, tree, itemId }) => {
107
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
117
+ const { propagateCheckedState, canCheckFolders } = tree.getConfig();
118
+ if (item.isFolder() && propagateCheckedState) {
119
+ const descendants = getAllLoadedDescendants(
120
+ tree,
121
+ itemId,
122
+ canCheckFolders,
123
+ );
108
124
  tree.applySubStateUpdate("checkedItems", (items) =>
109
- items.filter((id) => id !== itemId),
125
+ items.filter((id) => !descendants.includes(id) && id !== itemId),
110
126
  );
111
127
  } else {
112
- const descendants = getAllLoadedDescendants(tree, itemId);
113
128
  tree.applySubStateUpdate("checkedItems", (items) =>
114
- items.filter((id) => !descendants.includes(id)),
129
+ items.filter((id) => id !== itemId),
115
130
  );
116
131
  }
117
132
  },
@@ -13,6 +13,7 @@ export type CheckboxesFeatureDef<T> = {
13
13
  config: {
14
14
  setCheckedItems?: SetStateFn<string[]>;
15
15
  canCheckFolders?: boolean;
16
+ propagateCheckedState?: boolean;
16
17
  };
17
18
  treeInstance: {
18
19
  setCheckedItems: (checkedItems: string[]) => void;
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
  }
@@ -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
- };