@headless-tree/core 1.2.1 → 1.4.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 (190) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/index.d.mts +580 -0
  3. package/dist/index.d.ts +580 -0
  4. package/dist/index.js +2347 -0
  5. package/dist/index.mjs +2302 -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 +107 -24
  15. package/src/features/drag-and-drop/types.ts +21 -0
  16. package/src/features/drag-and-drop/utils.ts +8 -6
  17. package/src/features/keyboard-drag-and-drop/feature.ts +10 -1
  18. package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +34 -3
  19. package/src/features/main/types.ts +0 -2
  20. package/src/features/sync-data-loader/feature.ts +5 -1
  21. package/src/features/tree/feature.ts +4 -3
  22. package/src/features/tree/tree.spec.ts +14 -4
  23. package/src/test-utils/test-tree-do.ts +2 -0
  24. package/src/test-utils/test-tree.ts +1 -0
  25. package/tsconfig.json +1 -4
  26. package/vitest.config.ts +3 -1
  27. package/lib/cjs/core/build-proxified-instance.d.ts +0 -2
  28. package/lib/cjs/core/build-proxified-instance.js +0 -58
  29. package/lib/cjs/core/build-static-instance.d.ts +0 -2
  30. package/lib/cjs/core/build-static-instance.js +0 -26
  31. package/lib/cjs/core/create-tree.d.ts +0 -2
  32. package/lib/cjs/core/create-tree.js +0 -191
  33. package/lib/cjs/features/async-data-loader/feature.d.ts +0 -2
  34. package/lib/cjs/features/async-data-loader/feature.js +0 -135
  35. package/lib/cjs/features/async-data-loader/types.d.ts +0 -47
  36. package/lib/cjs/features/async-data-loader/types.js +0 -2
  37. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  38. package/lib/cjs/features/checkboxes/feature.js +0 -94
  39. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  40. package/lib/cjs/features/checkboxes/types.js +0 -9
  41. package/lib/cjs/features/drag-and-drop/feature.d.ts +0 -2
  42. package/lib/cjs/features/drag-and-drop/feature.js +0 -205
  43. package/lib/cjs/features/drag-and-drop/types.d.ts +0 -71
  44. package/lib/cjs/features/drag-and-drop/types.js +0 -9
  45. package/lib/cjs/features/drag-and-drop/utils.d.ts +0 -27
  46. package/lib/cjs/features/drag-and-drop/utils.js +0 -182
  47. package/lib/cjs/features/expand-all/feature.d.ts +0 -2
  48. package/lib/cjs/features/expand-all/feature.js +0 -70
  49. package/lib/cjs/features/expand-all/types.d.ts +0 -19
  50. package/lib/cjs/features/expand-all/types.js +0 -2
  51. package/lib/cjs/features/hotkeys-core/feature.d.ts +0 -2
  52. package/lib/cjs/features/hotkeys-core/feature.js +0 -107
  53. package/lib/cjs/features/hotkeys-core/types.d.ts +0 -27
  54. package/lib/cjs/features/hotkeys-core/types.js +0 -2
  55. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  56. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +0 -206
  57. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +0 -27
  58. package/lib/cjs/features/keyboard-drag-and-drop/types.js +0 -11
  59. package/lib/cjs/features/main/types.d.ts +0 -47
  60. package/lib/cjs/features/main/types.js +0 -2
  61. package/lib/cjs/features/prop-memoization/feature.d.ts +0 -2
  62. package/lib/cjs/features/prop-memoization/feature.js +0 -70
  63. package/lib/cjs/features/prop-memoization/types.d.ts +0 -15
  64. package/lib/cjs/features/prop-memoization/types.js +0 -2
  65. package/lib/cjs/features/renaming/feature.d.ts +0 -2
  66. package/lib/cjs/features/renaming/feature.js +0 -86
  67. package/lib/cjs/features/renaming/types.d.ts +0 -27
  68. package/lib/cjs/features/renaming/types.js +0 -2
  69. package/lib/cjs/features/search/feature.d.ts +0 -2
  70. package/lib/cjs/features/search/feature.js +0 -119
  71. package/lib/cjs/features/search/types.d.ts +0 -32
  72. package/lib/cjs/features/search/types.js +0 -2
  73. package/lib/cjs/features/selection/feature.d.ts +0 -2
  74. package/lib/cjs/features/selection/feature.js +0 -132
  75. package/lib/cjs/features/selection/types.d.ts +0 -21
  76. package/lib/cjs/features/selection/types.js +0 -2
  77. package/lib/cjs/features/sync-data-loader/feature.d.ts +0 -2
  78. package/lib/cjs/features/sync-data-loader/feature.js +0 -49
  79. package/lib/cjs/features/sync-data-loader/types.d.ts +0 -28
  80. package/lib/cjs/features/sync-data-loader/types.js +0 -2
  81. package/lib/cjs/features/tree/feature.d.ts +0 -2
  82. package/lib/cjs/features/tree/feature.js +0 -244
  83. package/lib/cjs/features/tree/types.d.ts +0 -63
  84. package/lib/cjs/features/tree/types.js +0 -2
  85. package/lib/cjs/index.d.ts +0 -33
  86. package/lib/cjs/index.js +0 -51
  87. package/lib/cjs/mddocs-entry.d.ts +0 -121
  88. package/lib/cjs/mddocs-entry.js +0 -17
  89. package/lib/cjs/test-utils/test-tree-do.d.ts +0 -23
  90. package/lib/cjs/test-utils/test-tree-do.js +0 -112
  91. package/lib/cjs/test-utils/test-tree-expect.d.ts +0 -17
  92. package/lib/cjs/test-utils/test-tree-expect.js +0 -66
  93. package/lib/cjs/test-utils/test-tree.d.ts +0 -48
  94. package/lib/cjs/test-utils/test-tree.js +0 -207
  95. package/lib/cjs/types/core.d.ts +0 -84
  96. package/lib/cjs/types/core.js +0 -2
  97. package/lib/cjs/types/deep-merge.d.ts +0 -13
  98. package/lib/cjs/types/deep-merge.js +0 -2
  99. package/lib/cjs/utilities/create-on-drop-handler.d.ts +0 -3
  100. package/lib/cjs/utilities/create-on-drop-handler.js +0 -20
  101. package/lib/cjs/utilities/errors.d.ts +0 -2
  102. package/lib/cjs/utilities/errors.js +0 -9
  103. package/lib/cjs/utilities/insert-items-at-target.d.ts +0 -3
  104. package/lib/cjs/utilities/insert-items-at-target.js +0 -40
  105. package/lib/cjs/utilities/remove-items-from-parents.d.ts +0 -2
  106. package/lib/cjs/utilities/remove-items-from-parents.js +0 -32
  107. package/lib/cjs/utils.d.ts +0 -6
  108. package/lib/cjs/utils.js +0 -53
  109. package/lib/esm/core/build-proxified-instance.d.ts +0 -2
  110. package/lib/esm/core/build-proxified-instance.js +0 -54
  111. package/lib/esm/core/build-static-instance.d.ts +0 -2
  112. package/lib/esm/core/build-static-instance.js +0 -22
  113. package/lib/esm/core/create-tree.d.ts +0 -2
  114. package/lib/esm/core/create-tree.js +0 -187
  115. package/lib/esm/features/async-data-loader/feature.d.ts +0 -2
  116. package/lib/esm/features/async-data-loader/feature.js +0 -132
  117. package/lib/esm/features/async-data-loader/types.d.ts +0 -47
  118. package/lib/esm/features/async-data-loader/types.js +0 -1
  119. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  120. package/lib/esm/features/checkboxes/feature.js +0 -91
  121. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  122. package/lib/esm/features/checkboxes/types.js +0 -6
  123. package/lib/esm/features/drag-and-drop/feature.d.ts +0 -2
  124. package/lib/esm/features/drag-and-drop/feature.js +0 -202
  125. package/lib/esm/features/drag-and-drop/types.d.ts +0 -71
  126. package/lib/esm/features/drag-and-drop/types.js +0 -6
  127. package/lib/esm/features/drag-and-drop/utils.d.ts +0 -27
  128. package/lib/esm/features/drag-and-drop/utils.js +0 -172
  129. package/lib/esm/features/expand-all/feature.d.ts +0 -2
  130. package/lib/esm/features/expand-all/feature.js +0 -67
  131. package/lib/esm/features/expand-all/types.d.ts +0 -19
  132. package/lib/esm/features/expand-all/types.js +0 -1
  133. package/lib/esm/features/hotkeys-core/feature.d.ts +0 -2
  134. package/lib/esm/features/hotkeys-core/feature.js +0 -104
  135. package/lib/esm/features/hotkeys-core/types.d.ts +0 -27
  136. package/lib/esm/features/hotkeys-core/types.js +0 -1
  137. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  138. package/lib/esm/features/keyboard-drag-and-drop/feature.js +0 -203
  139. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +0 -27
  140. package/lib/esm/features/keyboard-drag-and-drop/types.js +0 -8
  141. package/lib/esm/features/main/types.d.ts +0 -47
  142. package/lib/esm/features/main/types.js +0 -1
  143. package/lib/esm/features/prop-memoization/feature.d.ts +0 -2
  144. package/lib/esm/features/prop-memoization/feature.js +0 -67
  145. package/lib/esm/features/prop-memoization/types.d.ts +0 -15
  146. package/lib/esm/features/prop-memoization/types.js +0 -1
  147. package/lib/esm/features/renaming/feature.d.ts +0 -2
  148. package/lib/esm/features/renaming/feature.js +0 -83
  149. package/lib/esm/features/renaming/types.d.ts +0 -27
  150. package/lib/esm/features/renaming/types.js +0 -1
  151. package/lib/esm/features/search/feature.d.ts +0 -2
  152. package/lib/esm/features/search/feature.js +0 -116
  153. package/lib/esm/features/search/types.d.ts +0 -32
  154. package/lib/esm/features/search/types.js +0 -1
  155. package/lib/esm/features/selection/feature.d.ts +0 -2
  156. package/lib/esm/features/selection/feature.js +0 -129
  157. package/lib/esm/features/selection/types.d.ts +0 -21
  158. package/lib/esm/features/selection/types.js +0 -1
  159. package/lib/esm/features/sync-data-loader/feature.d.ts +0 -2
  160. package/lib/esm/features/sync-data-loader/feature.js +0 -46
  161. package/lib/esm/features/sync-data-loader/types.d.ts +0 -28
  162. package/lib/esm/features/sync-data-loader/types.js +0 -1
  163. package/lib/esm/features/tree/feature.d.ts +0 -2
  164. package/lib/esm/features/tree/feature.js +0 -241
  165. package/lib/esm/features/tree/types.d.ts +0 -63
  166. package/lib/esm/features/tree/types.js +0 -1
  167. package/lib/esm/index.d.ts +0 -33
  168. package/lib/esm/index.js +0 -32
  169. package/lib/esm/mddocs-entry.d.ts +0 -121
  170. package/lib/esm/mddocs-entry.js +0 -1
  171. package/lib/esm/test-utils/test-tree-do.d.ts +0 -23
  172. package/lib/esm/test-utils/test-tree-do.js +0 -108
  173. package/lib/esm/test-utils/test-tree-expect.d.ts +0 -17
  174. package/lib/esm/test-utils/test-tree-expect.js +0 -62
  175. package/lib/esm/test-utils/test-tree.d.ts +0 -48
  176. package/lib/esm/test-utils/test-tree.js +0 -203
  177. package/lib/esm/types/core.d.ts +0 -84
  178. package/lib/esm/types/core.js +0 -1
  179. package/lib/esm/types/deep-merge.d.ts +0 -13
  180. package/lib/esm/types/deep-merge.js +0 -1
  181. package/lib/esm/utilities/create-on-drop-handler.d.ts +0 -3
  182. package/lib/esm/utilities/create-on-drop-handler.js +0 -16
  183. package/lib/esm/utilities/errors.d.ts +0 -2
  184. package/lib/esm/utilities/errors.js +0 -4
  185. package/lib/esm/utilities/insert-items-at-target.d.ts +0 -3
  186. package/lib/esm/utilities/insert-items-at-target.js +0 -36
  187. package/lib/esm/utilities/remove-items-from-parents.d.ts +0 -2
  188. package/lib/esm/utilities/remove-items-from-parents.js +0 -28
  189. package/lib/esm/utils.d.ts +0 -6
  190. package/lib/esm/utils.js +0 -46
@@ -7,14 +7,14 @@ export enum ItemDropCategory {
7
7
  LastInGroup,
8
8
  }
9
9
 
10
- enum PlacementType {
10
+ export enum PlacementType {
11
11
  ReorderAbove,
12
12
  ReorderBelow,
13
13
  MakeChild,
14
14
  Reparent,
15
15
  }
16
16
 
17
- type TargetPlacement =
17
+ export type TargetPlacement =
18
18
  | {
19
19
  type:
20
20
  | PlacementType.ReorderAbove
@@ -95,7 +95,7 @@ export const getInsertionIndex = <T>(
95
95
  return childIndex - numberOfDragItemsBeforeTarget;
96
96
  };
97
97
 
98
- const getTargetPlacement = (
98
+ export const getTargetPlacement = (
99
99
  e: any,
100
100
  item: ItemInstance<any>,
101
101
  tree: TreeInstance<any>,
@@ -153,11 +153,9 @@ const getTargetPlacement = (
153
153
  };
154
154
 
155
155
  export const getDragCode = (
156
- e: any,
157
156
  item: ItemInstance<any>,
158
- tree: TreeInstance<any>,
157
+ placement: TargetPlacement,
159
158
  ) => {
160
- const placement = getTargetPlacement(e, item, tree, true);
161
159
  return [
162
160
  item.getId(),
163
161
  placement.type,
@@ -222,6 +220,10 @@ export const getDragTarget = (
222
220
  canBecomeSibling &&
223
221
  placement.type !== PlacementType.MakeChild
224
222
  ) {
223
+ if (draggedItems?.some((item) => item.isDescendentOf(parent.getId()))) {
224
+ // dropping on itself should be illegal, return item, canDrop will then return false
225
+ return itemTarget;
226
+ }
225
227
  return parentTarget;
226
228
  }
227
229
 
@@ -191,7 +191,16 @@ export const keyboardDragAndDropFeature: FeatureImplementation = {
191
191
  preventDefault: true,
192
192
  isEnabled: (tree) => !tree.getState().dnd,
193
193
  handler: (_, tree) => {
194
- tree.startKeyboardDrag(tree.getSelectedItems());
194
+ const selectedItems = tree.getSelectedItems?.() ?? [
195
+ tree.getFocusedItem(),
196
+ ];
197
+ const focusedItem = tree.getFocusedItem();
198
+
199
+ tree.startKeyboardDrag(
200
+ selectedItems.includes(focusedItem)
201
+ ? selectedItems
202
+ : selectedItems.concat(focusedItem),
203
+ );
195
204
  },
196
205
  },
197
206
  dragUp: {
@@ -49,6 +49,37 @@ describe("core-feature/keyboard-drag-and-drop", () => {
49
49
  tree.expect.substate("assistiveDndState", AssistiveDndState.Started);
50
50
  });
51
51
 
52
+ it("starts dragging only focused item", () => {
53
+ tree.item("x3").setFocused();
54
+ tree.do.hotkey("startDrag");
55
+ tree.expect.substate("dnd", {
56
+ draggedItems: [tree.item("x3")],
57
+ dragTarget: {
58
+ childIndex: 3,
59
+ dragLineIndex: 19,
60
+ dragLineLevel: 0,
61
+ insertionIndex: 2,
62
+ item: tree.item("x"),
63
+ },
64
+ });
65
+ });
66
+
67
+ it("starts dragging both selected and focused item", () => {
68
+ tree.do.selectMultiple("x111", "x112");
69
+ tree.item("x3").setFocused();
70
+ tree.do.hotkey("startDrag");
71
+ tree.expect.substate("dnd", {
72
+ draggedItems: [tree.item("x111"), tree.item("x112"), tree.item("x3")],
73
+ dragTarget: {
74
+ childIndex: 3,
75
+ dragLineIndex: 19,
76
+ dragLineLevel: 0,
77
+ insertionIndex: 2,
78
+ item: tree.item("x"),
79
+ },
80
+ });
81
+ });
82
+
52
83
  it("moves down 1", () => {
53
84
  tree.do.selectMultiple("x111", "x112");
54
85
  tree.do.hotkey("startDrag");
@@ -355,13 +386,13 @@ describe("core-feature/keyboard-drag-and-drop", () => {
355
386
 
356
387
  it("doesnt go below end of tree", () => {
357
388
  const lastState = {
358
- draggedItems: [tree.item("x111")],
389
+ draggedItems: [tree.item("x111"), tree.item("x3")],
359
390
  dragTarget: {
360
391
  item: tree.item("x"),
361
392
  childIndex: 4,
362
393
  dragLineIndex: 20,
363
394
  dragLineLevel: 0,
364
- insertionIndex: 4,
395
+ insertionIndex: 3,
365
396
  },
366
397
  };
367
398
 
@@ -378,7 +409,7 @@ describe("core-feature/keyboard-drag-and-drop", () => {
378
409
 
379
410
  it("doesnt go above top of tree", () => {
380
411
  const firstState = {
381
- draggedItems: [tree.item("x111")],
412
+ draggedItems: [tree.item("x111"), tree.item("x1")],
382
413
  dragTarget: {
383
414
  item: tree.item("x"),
384
415
  childIndex: 0,
@@ -36,8 +36,6 @@ export type MainFeatureDef<T = any> = {
36
36
  stateName: K,
37
37
  updater: Updater<TreeState<T>[K]>,
38
38
  ) => void;
39
- /** @internal */
40
- buildItemInstance: (itemId: string) => ItemInstance<T>;
41
39
  setState: SetStateFn<TreeState<T>>;
42
40
  getState: () => TreeState<T>;
43
41
  setConfig: SetStateFn<TreeConfig<T>>;
@@ -2,9 +2,13 @@ import { FeatureImplementation } from "../../types/core";
2
2
  import { makeStateUpdater } from "../../utils";
3
3
  import { throwError } from "../../utilities/errors";
4
4
 
5
+ const undefErrorMessage = "sync dataLoader returned undefined";
5
6
  const promiseErrorMessage = "sync dataLoader returned promise";
6
7
  const unpromise = <T>(data: T | Promise<T>): T => {
7
- if (!data || (typeof data === "object" && "then" in data)) {
8
+ if (!data) {
9
+ throw throwError(undefErrorMessage);
10
+ }
11
+ if (typeof data === "object" && "then" in data) {
8
12
  throw throwError(promiseErrorMessage);
9
13
  }
10
14
  return data;
@@ -76,8 +76,9 @@ export const treeFeature: FeatureImplementation<any> = {
76
76
  },
77
77
 
78
78
  getFocusedItem: ({ tree }) => {
79
+ const focusedItemId = tree.getState().focusedItem;
79
80
  return (
80
- tree.getItemInstance(tree.getState().focusedItem ?? "") ??
81
+ (focusedItemId !== null ? tree.getItemInstance(focusedItemId) : null) ??
81
82
  tree.getItems()[0]
82
83
  );
83
84
  },
@@ -139,10 +140,10 @@ export const treeFeature: FeatureImplementation<any> = {
139
140
  ref: item.registerElement,
140
141
  role: "treeitem",
141
142
  "aria-setsize": itemMeta.setSize,
142
- "aria-posinset": itemMeta.posInSet,
143
+ "aria-posinset": itemMeta.posInSet + 1,
143
144
  "aria-selected": "false",
144
145
  "aria-label": item.getItemName(),
145
- "aria-level": itemMeta.level,
146
+ "aria-level": itemMeta.level + 1,
146
147
  tabIndex: item.isFocused() ? 0 : -1,
147
148
  onClick: (e: MouseEvent) => {
148
149
  item.setFocused();
@@ -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;