@headless-tree/core 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/cjs/core/build-static-instance.js +1 -2
  3. package/lib/cjs/core/create-tree.js +7 -4
  4. package/lib/cjs/features/async-data-loader/feature.d.ts +1 -4
  5. package/lib/cjs/features/async-data-loader/feature.js +5 -7
  6. package/lib/cjs/features/async-data-loader/types.d.ts +2 -5
  7. package/lib/cjs/features/drag-and-drop/feature.d.ts +2 -3
  8. package/lib/cjs/features/drag-and-drop/feature.js +27 -24
  9. package/lib/cjs/features/drag-and-drop/types.d.ts +3 -3
  10. package/lib/cjs/features/drag-and-drop/utils.d.ts +1 -1
  11. package/lib/cjs/features/drag-and-drop/utils.js +4 -4
  12. package/lib/cjs/features/expand-all/feature.d.ts +1 -5
  13. package/lib/cjs/features/hotkeys-core/feature.d.ts +1 -3
  14. package/lib/cjs/features/prop-memoization/feature.d.ts +2 -0
  15. package/lib/cjs/features/prop-memoization/feature.js +48 -0
  16. package/lib/cjs/features/prop-memoization/types.d.ts +10 -0
  17. package/lib/cjs/features/prop-memoization/types.js +2 -0
  18. package/lib/cjs/features/renaming/feature.d.ts +1 -4
  19. package/lib/cjs/features/renaming/feature.js +8 -9
  20. package/lib/cjs/features/renaming/types.d.ts +1 -1
  21. package/lib/cjs/features/search/feature.d.ts +1 -4
  22. package/lib/cjs/features/selection/feature.d.ts +1 -4
  23. package/lib/cjs/features/selection/feature.js +35 -25
  24. package/lib/cjs/features/selection/types.d.ts +1 -1
  25. package/lib/cjs/features/sync-data-loader/feature.d.ts +1 -3
  26. package/lib/cjs/features/tree/feature.d.ts +1 -6
  27. package/lib/cjs/features/tree/feature.js +40 -57
  28. package/lib/cjs/features/tree/types.d.ts +0 -5
  29. package/lib/cjs/index.d.ts +2 -0
  30. package/lib/cjs/index.js +2 -0
  31. package/lib/cjs/mddocs-entry.d.ts +10 -0
  32. package/lib/cjs/test-utils/test-tree-do.d.ts +1 -1
  33. package/lib/cjs/test-utils/test-tree-expect.d.ts +1 -1
  34. package/lib/cjs/test-utils/test-tree-expect.js +1 -1
  35. package/lib/cjs/test-utils/test-tree.d.ts +1 -1
  36. package/lib/cjs/test-utils/test-tree.js +9 -1
  37. package/lib/cjs/types/core.d.ts +29 -30
  38. package/lib/esm/core/build-static-instance.js +1 -2
  39. package/lib/esm/core/create-tree.js +7 -4
  40. package/lib/esm/features/async-data-loader/feature.d.ts +1 -4
  41. package/lib/esm/features/async-data-loader/feature.js +5 -7
  42. package/lib/esm/features/async-data-loader/types.d.ts +2 -5
  43. package/lib/esm/features/drag-and-drop/feature.d.ts +2 -3
  44. package/lib/esm/features/drag-and-drop/feature.js +27 -24
  45. package/lib/esm/features/drag-and-drop/types.d.ts +3 -3
  46. package/lib/esm/features/drag-and-drop/utils.d.ts +1 -1
  47. package/lib/esm/features/drag-and-drop/utils.js +4 -4
  48. package/lib/esm/features/expand-all/feature.d.ts +1 -5
  49. package/lib/esm/features/hotkeys-core/feature.d.ts +1 -3
  50. package/lib/esm/features/prop-memoization/feature.d.ts +2 -0
  51. package/lib/esm/features/prop-memoization/feature.js +45 -0
  52. package/lib/esm/features/prop-memoization/types.d.ts +10 -0
  53. package/lib/esm/features/prop-memoization/types.js +1 -0
  54. package/lib/esm/features/renaming/feature.d.ts +1 -4
  55. package/lib/esm/features/renaming/feature.js +8 -9
  56. package/lib/esm/features/renaming/types.d.ts +1 -1
  57. package/lib/esm/features/search/feature.d.ts +1 -4
  58. package/lib/esm/features/selection/feature.d.ts +1 -4
  59. package/lib/esm/features/selection/feature.js +35 -25
  60. package/lib/esm/features/selection/types.d.ts +1 -1
  61. package/lib/esm/features/sync-data-loader/feature.d.ts +1 -3
  62. package/lib/esm/features/tree/feature.d.ts +1 -6
  63. package/lib/esm/features/tree/feature.js +40 -57
  64. package/lib/esm/features/tree/types.d.ts +0 -5
  65. package/lib/esm/index.d.ts +2 -0
  66. package/lib/esm/index.js +2 -0
  67. package/lib/esm/mddocs-entry.d.ts +10 -0
  68. package/lib/esm/test-utils/test-tree-do.d.ts +1 -1
  69. package/lib/esm/test-utils/test-tree-expect.d.ts +1 -1
  70. package/lib/esm/test-utils/test-tree-expect.js +1 -1
  71. package/lib/esm/test-utils/test-tree.d.ts +1 -1
  72. package/lib/esm/test-utils/test-tree.js +9 -1
  73. package/lib/esm/types/core.d.ts +29 -30
  74. package/package.json +1 -1
  75. package/src/core/build-proxified-instance.ts +5 -3
  76. package/src/core/build-static-instance.ts +1 -2
  77. package/src/core/core.spec.ts +210 -0
  78. package/src/core/create-tree.ts +13 -16
  79. package/src/features/async-data-loader/async-data-loader.spec.ts +12 -31
  80. package/src/features/async-data-loader/feature.ts +8 -20
  81. package/src/features/async-data-loader/types.ts +2 -6
  82. package/src/features/drag-and-drop/drag-and-drop.spec.ts +4 -3
  83. package/src/features/drag-and-drop/feature.ts +87 -86
  84. package/src/features/drag-and-drop/types.ts +4 -4
  85. package/src/features/drag-and-drop/utils.ts +4 -4
  86. package/src/features/expand-all/expand-all.spec.ts +5 -1
  87. package/src/features/expand-all/feature.ts +1 -12
  88. package/src/features/hotkeys-core/feature.ts +4 -13
  89. package/src/features/prop-memoization/feature.ts +51 -0
  90. package/src/features/prop-memoization/prop-memoization.spec.ts +68 -0
  91. package/src/features/prop-memoization/types.ts +11 -0
  92. package/src/features/renaming/feature.ts +11 -20
  93. package/src/features/renaming/renaming.spec.ts +11 -9
  94. package/src/features/renaming/types.ts +1 -1
  95. package/src/features/search/feature.ts +2 -8
  96. package/src/features/search/search.spec.ts +3 -1
  97. package/src/features/selection/feature.ts +45 -47
  98. package/src/features/selection/selection.spec.ts +13 -14
  99. package/src/features/selection/types.ts +0 -2
  100. package/src/features/sync-data-loader/feature.ts +1 -7
  101. package/src/features/tree/feature.ts +47 -85
  102. package/src/features/tree/tree.spec.ts +24 -64
  103. package/src/features/tree/types.ts +0 -6
  104. package/src/index.ts +2 -0
  105. package/src/mddocs-entry.ts +13 -0
  106. package/src/test-utils/test-tree-expect.ts +1 -1
  107. package/src/test-utils/test-tree.ts +11 -1
  108. package/src/types/core.ts +56 -147
@@ -1,14 +1,15 @@
1
1
  import { describe, expect, it, vi } from "vitest";
2
2
  import { TestTree } from "../../test-utils/test-tree";
3
+ import { propMemoizationFeature } from "../prop-memoization/feature";
3
4
 
4
- const factory = TestTree.default({});
5
+ const factory = TestTree.default({}).withFeatures(propMemoizationFeature);
5
6
 
6
7
  describe("core-feature/selections", () => {
7
8
  factory.forSuits((tree) => {
8
9
  describe("expanded items", () => {
9
10
  it("can expand via tree instance", () => {
10
11
  const setExpandedItems = tree.mockedHandler("setExpandedItems");
11
- tree.instance.expandItem("x2");
12
+ tree.item("x2").expand();
12
13
  expect(setExpandedItems).toHaveBeenCalledWith(["x1", "x11", "x2"]);
13
14
  });
14
15
 
@@ -19,14 +20,14 @@ describe("core-feature/selections", () => {
19
20
  });
20
21
 
21
22
  it("returns correct isItemExpanded value", () => {
22
- expect(tree.instance.isItemExpanded("x2")).toBe(false);
23
- tree.instance.expandItem("x2");
24
- expect(tree.instance.isItemExpanded("x2")).toBe(true);
23
+ expect(tree.item("x2").isExpanded()).toBe(false);
24
+ tree.item("x2").expand();
25
+ expect(tree.item("x2").isExpanded()).toBe(true);
25
26
  });
26
27
 
27
28
  it("calls setState", () => {
28
29
  const setState = tree.mockedHandler("setState");
29
- tree.instance.expandItem("x2");
30
+ tree.item("x2").expand();
30
31
  expect(setState).toBeCalledWith(
31
32
  expect.objectContaining({ expandedItems: ["x1", "x11", "x2"] }),
32
33
  );
@@ -42,7 +43,7 @@ describe("core-feature/selections", () => {
42
43
  describe("collapsed items", () => {
43
44
  it("can collapse via tree instance", () => {
44
45
  const setExpandedItems = tree.mockedHandler("setExpandedItems");
45
- tree.instance.collapseItem("x1");
46
+ tree.item("x1").collapse();
46
47
  expect(setExpandedItems).toHaveBeenCalledWith(["x11"]);
47
48
  });
48
49
 
@@ -53,14 +54,14 @@ describe("core-feature/selections", () => {
53
54
  });
54
55
 
55
56
  it("returns correct isItemExpanded value", () => {
56
- expect(tree.instance.isItemExpanded("x1")).toBe(true);
57
- tree.instance.collapseItem("x1");
58
- expect(tree.instance.isItemExpanded("x1")).toBe(false);
57
+ expect(tree.item("x1").isExpanded()).toBe(true);
58
+ tree.item("x1").collapse();
59
+ expect(tree.item("x1").isExpanded()).toBe(false);
59
60
  });
60
61
 
61
62
  it("calls setState", () => {
62
63
  const setState = tree.mockedHandler("setState");
63
- tree.instance.collapseItem("x1");
64
+ tree.item("x1").collapse();
64
65
  expect(setState).toBeCalledWith(
65
66
  expect.objectContaining({ expandedItems: ["x11"] }),
66
67
  );
@@ -74,15 +75,9 @@ describe("core-feature/selections", () => {
74
75
  });
75
76
 
76
77
  describe("focused item", () => {
77
- it("focuses item on tree instance", () => {
78
+ it("focuses item", () => {
78
79
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
79
- tree.instance.focusItem("x11");
80
- expect(setFocusedItem).toHaveBeenCalledWith("x11");
81
- });
82
-
83
- it("focuses item on item instance", () => {
84
- const setFocusedItem = tree.mockedHandler("setFocusedItem");
85
- tree.instance.getItemInstance("x11").setFocused();
80
+ tree.item("x11").setFocused();
86
81
  expect(setFocusedItem).toHaveBeenCalledWith("x11");
87
82
  });
88
83
 
@@ -91,13 +86,13 @@ describe("core-feature/selections", () => {
91
86
  });
92
87
 
93
88
  it("returns correct focused item", () => {
94
- tree.instance.focusItem("x11");
89
+ tree.item("x11").setFocused();
95
90
  expect(tree.instance.getFocusedItem().getId()).toBe("x11");
96
91
  });
97
92
 
98
93
  it("calls setState", () => {
99
94
  const setState = tree.mockedHandler("setState");
100
- tree.instance.focusItem("x1");
95
+ tree.item("x1").setFocused();
101
96
  expect(setState).toBeCalledWith(
102
97
  expect.objectContaining({ focusedItem: "x1" }),
103
98
  );
@@ -107,7 +102,7 @@ describe("core-feature/selections", () => {
107
102
  const scrollToItem = tree.mockedHandler("scrollToItem");
108
103
  const element = { focus: vi.fn() };
109
104
  tree.instance.getItemInstance("x2").registerElement(element as any);
110
- tree.instance.focusItem("x2");
105
+ tree.item("x2").setFocused();
111
106
  tree.instance.updateDomFocus();
112
107
  vi.runAllTimers();
113
108
  await vi.waitFor(() =>
@@ -118,21 +113,21 @@ describe("core-feature/selections", () => {
118
113
 
119
114
  describe("move focus", () => {
120
115
  it("focuses next item", () => {
121
- tree.instance.focusItem("x2");
116
+ tree.item("x2").setFocused();
122
117
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
123
118
  tree.instance.focusNextItem();
124
119
  expect(setFocusedItem).toHaveBeenCalledWith("x3");
125
120
  });
126
121
 
127
122
  it("focuses previous item", () => {
128
- tree.instance.focusItem("x2");
123
+ tree.item("x2").setFocused();
129
124
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
130
125
  tree.instance.focusPreviousItem();
131
126
  expect(setFocusedItem).toHaveBeenCalledWith("x14");
132
127
  });
133
128
 
134
129
  it("remains at last item when focus is at bottom", () => {
135
- tree.instance.focusItem("x4");
130
+ tree.item("x4").setFocused();
136
131
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
137
132
  tree.instance.focusNextItem();
138
133
  expect(setFocusedItem).toHaveBeenCalledWith("x4");
@@ -140,7 +135,7 @@ describe("core-feature/selections", () => {
140
135
  });
141
136
 
142
137
  it("remains at first item when focus is at top", () => {
143
- tree.instance.focusItem("x1");
138
+ tree.item("x1").setFocused();
144
139
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
145
140
  tree.instance.focusPreviousItem();
146
141
  expect(setFocusedItem).toHaveBeenCalledWith("x1");
@@ -245,6 +240,7 @@ describe("core-feature/selections", () => {
245
240
  "aria-selected": "false",
246
241
  "aria-setsize": 4,
247
242
  onClick: expect.any(Function),
243
+ ref: expect.any(Function),
248
244
  role: "treeitem",
249
245
  tabIndex: -1,
250
246
  });
@@ -258,6 +254,7 @@ describe("core-feature/selections", () => {
258
254
  "aria-selected": "false",
259
255
  "aria-setsize": 4,
260
256
  onClick: expect.any(Function),
257
+ ref: expect.any(Function),
261
258
  role: "treeitem",
262
259
  tabIndex: 0,
263
260
  });
@@ -320,7 +317,7 @@ describe("core-feature/selections", () => {
320
317
  });
321
318
 
322
319
  it("returns correctly for getParent()", () => {
323
- expect(tree.instance.getItemInstance("x111").getParent().getId()).toBe(
320
+ expect(tree.instance.getItemInstance("x111").getParent()?.getId()).toBe(
324
321
  "x11",
325
322
  );
326
323
  });
@@ -383,43 +380,6 @@ describe("core-feature/selections", () => {
383
380
  });
384
381
  });
385
382
 
386
- describe("memoized props", () => {
387
- it("runs memoized props correctly", () => {
388
- const fn = vi.fn().mockReturnValue("result");
389
- const memoizedProp = tree.instance
390
- .getItemInstance("x1")
391
- .getMemoizedProp("fn", () => fn);
392
- expect(memoizedProp(1, 2, 3)).toBe("result");
393
- expect(fn).toBeCalledWith(1, 2, 3);
394
- });
395
-
396
- it("runs just once", () => {
397
- const fn = vi.fn().mockImplementation(() => () => "result");
398
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn)(1);
399
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn)(1);
400
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn)(1);
401
- expect(fn).toBeCalledTimes(1);
402
- });
403
-
404
- it("reruns if dependencies changed", () => {
405
- const fn = vi.fn().mockImplementation(() => () => "result");
406
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn, [1])(1);
407
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn, [1])(1);
408
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn, [2])(1);
409
- expect(fn).toBeCalledTimes(2);
410
- });
411
-
412
- it("seperates functions by name", () => {
413
- const fn1 = vi.fn().mockImplementation(() => () => "result");
414
- const fn2 = vi.fn().mockImplementation(() => () => "result");
415
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn1, [1])(1);
416
- tree.instance.getItemInstance("x1").getMemoizedProp("fn", fn1, [1])(1);
417
- tree.instance.getItemInstance("x1").getMemoizedProp("fn2", fn2, [1])(1);
418
- expect(fn1).toBeCalledTimes(1);
419
- expect(fn2).toBeCalledTimes(1);
420
- });
421
- });
422
-
423
383
  describe("hotkeys", () => {
424
384
  it("focuses next item", () => {
425
385
  const setFocusedItem = tree.mockedHandler("setFocusedItem");
@@ -33,11 +33,6 @@ export type TreeFeatureDef<T> = {
33
33
  /** @internal */
34
34
  getItemsMeta: () => ItemMeta[];
35
35
 
36
- expandItem: (itemId: string) => void;
37
- collapseItem: (itemId: string) => void;
38
- isItemExpanded: (itemId: string) => boolean;
39
-
40
- focusItem: (itemId: string) => void;
41
36
  getFocusedItem: () => ItemInstance<any>;
42
37
  focusNextItem: () => void;
43
38
  focusPreviousItem: () => void;
@@ -65,7 +60,6 @@ export type TreeFeatureDef<T> = {
65
60
  getTree: () => TreeInstance<T>;
66
61
  getItemAbove: () => ItemInstance<T> | undefined;
67
62
  getItemBelow: () => ItemInstance<T> | undefined;
68
- getMemoizedProp: <X>(name: string, create: () => X, deps?: any[]) => X;
69
63
  scrollTo: (
70
64
  scrollIntoViewArg?: boolean | ScrollIntoViewOptions,
71
65
  ) => Promise<void>;
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export * from "./features/hotkeys-core/types";
11
11
  export * from "./features/search/types";
12
12
  export * from "./features/renaming/types";
13
13
  export * from "./features/expand-all/types";
14
+ export * from "./features/prop-memoization/types";
14
15
 
15
16
  export * from "./features/selection/feature";
16
17
  export * from "./features/hotkeys-core/feature";
@@ -20,6 +21,7 @@ export * from "./features/drag-and-drop/feature";
20
21
  export * from "./features/search/feature";
21
22
  export * from "./features/renaming/feature";
22
23
  export * from "./features/expand-all/feature";
24
+ export * from "./features/prop-memoization/feature";
23
25
 
24
26
  export * from "./utilities/create-on-drop-handler";
25
27
  export * from "./utilities/insert-items-at-target";
@@ -8,6 +8,7 @@ import { SearchFeatureDef } from "./features/search/types";
8
8
  import { SelectionFeatureDef } from "./features/selection/types";
9
9
  import { SyncDataLoaderFeatureDef } from "./features/sync-data-loader/types";
10
10
  import { TreeFeatureDef } from "./features/tree/types";
11
+ import { PropMemoizationFeatureDef } from "./features/prop-memoization/types";
11
12
 
12
13
  export * from ".";
13
14
 
@@ -80,6 +81,18 @@ export type MainFeatureTreeInstance = MainFeatureDef["treeInstance"];
80
81
  export type MainFeatureItemInstance = MainFeatureDef["itemInstance"];
81
82
  export type MainFeatureHotkeys = MainFeatureDef["hotkeys"];
82
83
 
84
+ /** @interface */
85
+ export type PropMemoizationConfig = PropMemoizationFeatureDef["config"];
86
+ /** @interface */
87
+ export type PropMemoizationState = PropMemoizationFeatureDef["state"];
88
+ /** @interface */
89
+ export type PropMemoizationTreeInstance =
90
+ PropMemoizationFeatureDef["treeInstance"];
91
+ /** @interface */
92
+ export type PropMemoizationItemInstance =
93
+ PropMemoizationFeatureDef["itemInstance"];
94
+ export type PropMemoizationHotkeys = PropMemoizationFeatureDef["hotkeys"];
95
+
83
96
  /** @interface */
84
97
  export type RenamingFeatureConfig<T> = RenamingFeatureDef<T>["config"];
85
98
  /** @interface */
@@ -73,7 +73,7 @@ export class TestTreeExpect<T> {
73
73
  expect(this.tree.instance.getDragLineData()).toEqual({
74
74
  indent,
75
75
  left: indent * 20,
76
- right: 100,
76
+ width: 100 - indent * 20,
77
77
  top: 0,
78
78
  });
79
79
  expect(this.tree.instance.getDragLineStyle(0, 0)).toEqual({
@@ -183,11 +183,21 @@ export class TestTree<T = string> {
183
183
  itemId: string,
184
184
  bb: Partial<DOMRect> = {
185
185
  left: 0,
186
- right: 100,
186
+ width: 100,
187
187
  top: 0,
188
188
  height: 20,
189
189
  },
190
190
  ) {
191
+ this.instance.registerElement({
192
+ getBoundingClientRect: () =>
193
+ ({
194
+ left: 0,
195
+ width: 100,
196
+ top: 0,
197
+ height: 10000,
198
+ }) as DOMRect,
199
+ } as HTMLElement);
200
+
191
201
  this.instance.getItemInstance(itemId).registerElement({
192
202
  getBoundingClientRect: () => bb as DOMRect,
193
203
  } as HTMLElement);
package/src/types/core.ts CHANGED
@@ -11,17 +11,16 @@ import { AsyncDataLoaderFeatureDef } from "../features/async-data-loader/types";
11
11
  import { SearchFeatureDef } from "../features/search/types";
12
12
  import { RenamingFeatureDef } from "../features/renaming/types";
13
13
  import { ExpandAllFeatureDef } from "../features/expand-all/types";
14
+ import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
14
15
 
15
16
  export type Updater<T> = T | ((old: T) => T);
16
17
  export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
17
18
 
18
- type FunctionMap = Record<string, (...args: any[]) => any>;
19
-
20
19
  export type FeatureDef = {
21
20
  state: any;
22
21
  config: any;
23
- treeInstance: FunctionMap;
24
- itemInstance: FunctionMap;
22
+ treeInstance: any;
23
+ itemInstance: any;
25
24
  hotkeys: string;
26
25
  };
27
26
 
@@ -39,20 +38,6 @@ type UnionToIntersection<T> = (T extends any ? (x: T) => any : never) extends (
39
38
  ? R
40
39
  : never;
41
40
 
42
- export type DefaultFeatures<T> = MainFeatureDef | TreeFeatureDef<T>;
43
-
44
- export type FeatureDefs<T> =
45
- | MainFeatureDef
46
- | TreeFeatureDef<T>
47
- | SelectionFeatureDef<T>
48
- | DragAndDropFeatureDef<T>
49
- | HotkeysCoreFeatureDef<T>
50
- | SyncDataLoaderFeatureDef<T>
51
- | AsyncDataLoaderFeatureDef<T>
52
- | SearchFeatureDef<T>
53
- | RenamingFeatureDef<T>
54
- | ExpandAllFeatureDef;
55
-
56
41
  type MergedFeatures<F extends FeatureDef> = {
57
42
  // type can't be removed because it's used for individual feature sets as feature deps in feature implementations
58
43
  // to my future self, yes I'm already aware this sounds dumb when I first write this
@@ -63,181 +48,105 @@ type MergedFeatures<F extends FeatureDef> = {
63
48
  hotkeys: F["hotkeys"];
64
49
  };
65
50
 
66
- type TreeStateType<T> = MainFeatureDef["state"] &
67
- TreeFeatureDef<T>["state"] &
68
- SelectionFeatureDef<T>["state"] &
69
- DragAndDropFeatureDef<T>["state"] &
70
- HotkeysCoreFeatureDef<T>["state"] &
71
- SyncDataLoaderFeatureDef<T>["state"] &
72
- AsyncDataLoaderFeatureDef<T>["state"] &
73
- SearchFeatureDef<T>["state"] &
74
- RenamingFeatureDef<T>["state"] &
75
- ExpandAllFeatureDef["state"];
51
+ export type RegisteredFeatures<T> =
52
+ | MainFeatureDef<T>
53
+ | TreeFeatureDef<T>
54
+ | SelectionFeatureDef<T>
55
+ | DragAndDropFeatureDef<T>
56
+ | HotkeysCoreFeatureDef<T>
57
+ | SyncDataLoaderFeatureDef<T>
58
+ | AsyncDataLoaderFeatureDef<T>
59
+ | SearchFeatureDef<T>
60
+ | RenamingFeatureDef<T>
61
+ | ExpandAllFeatureDef
62
+ | PropMemoizationFeatureDef;
63
+
64
+ type TreeStateType<T> = MergedFeatures<RegisteredFeatures<T>>["state"];
76
65
  export interface TreeState<T> extends TreeStateType<T> {}
77
66
 
78
- type TreeConfigType<T> = MainFeatureDef["config"] &
79
- TreeFeatureDef<T>["config"] &
80
- SelectionFeatureDef<T>["config"] &
81
- DragAndDropFeatureDef<T>["config"] &
82
- HotkeysCoreFeatureDef<T>["config"] &
83
- SyncDataLoaderFeatureDef<T>["config"] &
84
- AsyncDataLoaderFeatureDef<T>["config"] &
85
- SearchFeatureDef<T>["config"] &
86
- RenamingFeatureDef<T>["config"] &
87
- ExpandAllFeatureDef["config"];
67
+ type TreeConfigType<T> = MergedFeatures<RegisteredFeatures<T>>["config"];
88
68
  export interface TreeConfig<T> extends TreeConfigType<T> {}
89
69
 
90
- type TreeInstanceType<T> = MainFeatureDef["treeInstance"] &
91
- TreeFeatureDef<T>["treeInstance"] &
92
- SelectionFeatureDef<T>["treeInstance"] &
93
- DragAndDropFeatureDef<T>["treeInstance"] &
94
- HotkeysCoreFeatureDef<T>["treeInstance"] &
95
- SyncDataLoaderFeatureDef<T>["treeInstance"] &
96
- AsyncDataLoaderFeatureDef<T>["treeInstance"] &
97
- SearchFeatureDef<T>["treeInstance"] &
98
- RenamingFeatureDef<T>["treeInstance"] &
99
- ExpandAllFeatureDef["treeInstance"];
70
+ type TreeInstanceType<T> = MergedFeatures<
71
+ RegisteredFeatures<T>
72
+ >["treeInstance"];
100
73
  export interface TreeInstance<T> extends TreeInstanceType<T> {}
101
74
 
102
- type ItemInstanceType<T> = MainFeatureDef["itemInstance"] &
103
- TreeFeatureDef<T>["itemInstance"] &
104
- SelectionFeatureDef<T>["itemInstance"] &
105
- DragAndDropFeatureDef<T>["itemInstance"] &
106
- HotkeysCoreFeatureDef<T>["itemInstance"] &
107
- SyncDataLoaderFeatureDef<T>["itemInstance"] &
108
- AsyncDataLoaderFeatureDef<T>["itemInstance"] &
109
- SearchFeatureDef<T>["itemInstance"] &
110
- RenamingFeatureDef<T>["itemInstance"] &
111
- ExpandAllFeatureDef["itemInstance"];
75
+ type ItemInstanceType<T> = MergedFeatures<
76
+ RegisteredFeatures<T>
77
+ >["itemInstance"];
112
78
  export interface ItemInstance<T> extends ItemInstanceType<T> {}
113
79
 
114
- export type HotkeyName<F extends FeatureDef = FeatureDefs<any>> =
115
- MergedFeatures<F>["hotkeys"];
80
+ export type HotkeyName = MergedFeatures<RegisteredFeatures<any>>["hotkeys"];
116
81
 
117
- export type HotkeysConfig<T, F extends FeatureDef = FeatureDefs<T>> = Record<
118
- HotkeyName<F>,
119
- HotkeyConfig<T>
120
- >;
82
+ export type HotkeysConfig<T> = Record<HotkeyName, HotkeyConfig<T>>;
121
83
 
122
- export type CustomHotkeysConfig<
123
- T,
124
- F extends FeatureDef = FeatureDefs<T>,
125
- > = Partial<
126
- Record<HotkeyName<F> | `custom${string}`, Partial<HotkeyConfig<T>>>
84
+ export type CustomHotkeysConfig<T> = Partial<
85
+ Record<HotkeyName | `custom${string}`, Partial<HotkeyConfig<T>>>
127
86
  >;
128
87
 
129
88
  type MayReturnNull<T extends (...x: any[]) => any> = (
130
89
  ...args: Parameters<T>
131
90
  ) => ReturnType<T> | null;
132
91
 
133
- export type ItemInstanceOpts<
134
- ItemInstance extends FunctionMap = FunctionMap,
135
- TreeInstance extends FunctionMap = FunctionMap,
136
- Key extends keyof ItemInstance = any,
137
- > = {
138
- item: ItemInstance;
139
- tree: TreeInstance;
92
+ export type ItemInstanceOpts<Key extends keyof ItemInstance<any>> = {
93
+ item: ItemInstance<any>;
94
+ tree: TreeInstance<any>;
140
95
  itemId: string;
141
- prev?: MayReturnNull<ItemInstance[Key]>;
96
+ prev?: MayReturnNull<ItemInstance<any>[Key]>;
142
97
  };
143
98
 
144
- export type TreeInstanceOpts<
145
- TreeInstance extends FunctionMap = FunctionMap,
146
- Key extends keyof TreeInstance = any,
147
- > = {
148
- tree: TreeInstance;
149
- prev?: MayReturnNull<TreeInstance[Key]>;
99
+ export type TreeInstanceOpts<Key extends keyof TreeInstance<any>> = {
100
+ tree: TreeInstance<any>;
101
+ prev?: MayReturnNull<TreeInstance<any>[Key]>;
150
102
  };
151
103
 
152
- export type FeatureImplementation<
153
- T = any,
154
- SelfFeatureDef extends FeatureDef = any,
155
- DepFeaturesDef extends FeatureDef = any,
156
- // /** @internal */
157
- // AllFeatures extends FeatureDef = MergedFeatures<
158
- // DepFeaturesDef | SelfFeatureDef
159
- // >,
160
- // /** @internal */
161
- // DepFeatures extends FeatureDef = MergedFeatures<DepFeaturesDef>,
162
- > = {
104
+ export type FeatureImplementation<T = any> = {
163
105
  key?: string;
164
106
  deps?: string[];
165
107
  overwrites?: string[];
166
108
 
167
- stateHandlerNames?: Partial<
168
- Record<
169
- keyof MergedFeatures<DepFeaturesDef>["state"],
170
- keyof MergedFeatures<DepFeaturesDef>["config"]
171
- >
172
- >;
109
+ stateHandlerNames?: Partial<Record<keyof TreeState<T>, keyof TreeConfig<T>>>;
173
110
 
174
111
  getInitialState?: (
175
- initialState: Partial<MergedFeatures<DepFeaturesDef>["state"]>,
176
- tree: MergedFeatures<DepFeaturesDef>["treeInstance"],
177
- ) => Partial<
178
- SelfFeatureDef["state"] & MergedFeatures<DepFeaturesDef>["state"]
179
- >;
112
+ initialState: Partial<TreeState<T>>,
113
+ tree: TreeInstance<T>,
114
+ ) => Partial<TreeState<T>>;
180
115
 
181
116
  getDefaultConfig?: (
182
- defaultConfig: Partial<MergedFeatures<DepFeaturesDef>["config"]>,
183
- tree: MergedFeatures<DepFeaturesDef>["treeInstance"],
184
- ) => Partial<
185
- SelfFeatureDef["config"] & MergedFeatures<DepFeaturesDef>["config"]
186
- >;
117
+ defaultConfig: Partial<TreeConfig<T>>,
118
+ tree: TreeInstance<T>,
119
+ ) => Partial<TreeConfig<T>>;
187
120
 
188
121
  treeInstance?: {
189
- [key in keyof (SelfFeatureDef["treeInstance"] &
190
- MergedFeatures<DepFeaturesDef>["treeInstance"])]?: (
191
- opts: TreeInstanceOpts<
192
- SelfFeatureDef["treeInstance"] &
193
- MergedFeatures<DepFeaturesDef>["treeInstance"],
194
- key
195
- >,
196
- ...args: Parameters<
197
- (SelfFeatureDef["treeInstance"] &
198
- MergedFeatures<DepFeaturesDef>["treeInstance"])[key]
199
- >
122
+ [key in keyof TreeInstance<T>]?: (
123
+ opts: TreeInstanceOpts<key>,
124
+ ...args: Parameters<TreeInstance<T>[key]>
200
125
  ) => void;
201
126
  };
202
127
 
203
128
  itemInstance?: {
204
- [key in keyof (SelfFeatureDef["itemInstance"] &
205
- MergedFeatures<DepFeaturesDef>["itemInstance"])]?: (
206
- opts: ItemInstanceOpts<
207
- SelfFeatureDef["itemInstance"] &
208
- MergedFeatures<DepFeaturesDef>["itemInstance"],
209
- SelfFeatureDef["treeInstance"] &
210
- MergedFeatures<DepFeaturesDef>["treeInstance"],
211
- key
212
- >,
213
- ...args: Parameters<
214
- (SelfFeatureDef["itemInstance"] &
215
- MergedFeatures<DepFeaturesDef>["itemInstance"])[key]
216
- >
129
+ [key in keyof ItemInstance<T>]?: (
130
+ opts: ItemInstanceOpts<key>,
131
+ ...args: Parameters<ItemInstance<T>[key]>
217
132
  ) => void;
218
133
  };
219
134
 
220
- onTreeMount?: (
221
- instance: MergedFeatures<DepFeaturesDef>["treeInstance"],
222
- treeElement: HTMLElement,
223
- ) => void;
135
+ onTreeMount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
224
136
 
225
- onTreeUnmount?: (
226
- instance: MergedFeatures<DepFeaturesDef>["treeInstance"],
227
- treeElement: HTMLElement,
228
- ) => void;
137
+ onTreeUnmount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
229
138
 
230
139
  onItemMount?: (
231
- instance: MergedFeatures<DepFeaturesDef>["itemInstance"],
140
+ instance: ItemInstance<T>,
232
141
  itemElement: HTMLElement,
233
- tree: MergedFeatures<DepFeaturesDef>["treeInstance"],
142
+ tree: TreeInstance<T>,
234
143
  ) => void;
235
144
 
236
145
  onItemUnmount?: (
237
- instance: MergedFeatures<DepFeaturesDef>["itemInstance"],
146
+ instance: ItemInstance<T>,
238
147
  itemElement: HTMLElement,
239
- tree: MergedFeatures<DepFeaturesDef>["treeInstance"],
148
+ tree: TreeInstance<T>,
240
149
  ) => void;
241
150
 
242
- hotkeys?: HotkeysConfig<T, SelfFeatureDef>;
151
+ hotkeys?: Partial<HotkeysConfig<T>>;
243
152
  };