@headless-tree/core 0.0.14 → 0.0.15

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 (125) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/lib/cjs/core/create-tree.js +13 -4
  3. package/lib/cjs/features/async-data-loader/feature.js +73 -48
  4. package/lib/cjs/features/async-data-loader/types.d.ts +17 -14
  5. package/lib/cjs/features/drag-and-drop/feature.js +98 -93
  6. package/lib/cjs/features/drag-and-drop/types.d.ts +17 -29
  7. package/lib/cjs/features/drag-and-drop/types.js +7 -7
  8. package/lib/cjs/features/drag-and-drop/utils.d.ts +18 -3
  9. package/lib/cjs/features/drag-and-drop/utils.js +49 -51
  10. package/lib/cjs/features/expand-all/feature.js +26 -3
  11. package/lib/cjs/features/expand-all/types.d.ts +3 -1
  12. package/lib/cjs/features/hotkeys-core/feature.js +7 -3
  13. package/lib/cjs/features/hotkeys-core/types.d.ts +4 -5
  14. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +2 -0
  15. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +207 -0
  16. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +27 -0
  17. package/lib/cjs/features/keyboard-drag-and-drop/types.js +11 -0
  18. package/lib/cjs/features/prop-memoization/feature.js +2 -2
  19. package/lib/cjs/features/prop-memoization/types.d.ts +2 -2
  20. package/lib/cjs/features/renaming/feature.js +1 -1
  21. package/lib/cjs/features/search/feature.js +2 -0
  22. package/lib/cjs/features/search/types.d.ts +2 -2
  23. package/lib/cjs/features/selection/feature.js +4 -4
  24. package/lib/cjs/features/selection/types.d.ts +1 -1
  25. package/lib/cjs/features/sync-data-loader/feature.js +31 -5
  26. package/lib/cjs/features/sync-data-loader/types.d.ts +5 -5
  27. package/lib/cjs/features/tree/feature.js +4 -7
  28. package/lib/cjs/features/tree/types.d.ts +7 -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 +2 -2
  33. package/lib/cjs/test-utils/test-tree-do.js +19 -6
  34. package/lib/cjs/test-utils/test-tree-expect.d.ts +5 -3
  35. package/lib/cjs/test-utils/test-tree-expect.js +3 -0
  36. package/lib/cjs/test-utils/test-tree.d.ts +2 -1
  37. package/lib/cjs/test-utils/test-tree.js +24 -21
  38. package/lib/cjs/types/core.d.ts +2 -1
  39. package/lib/cjs/utilities/create-on-drop-handler.d.ts +2 -2
  40. package/lib/cjs/utilities/create-on-drop-handler.js +13 -4
  41. package/lib/cjs/utilities/insert-items-at-target.d.ts +2 -2
  42. package/lib/cjs/utilities/insert-items-at-target.js +21 -12
  43. package/lib/cjs/utilities/remove-items-from-parents.d.ts +1 -1
  44. package/lib/cjs/utilities/remove-items-from-parents.js +12 -3
  45. package/lib/esm/core/create-tree.js +13 -4
  46. package/lib/esm/features/async-data-loader/feature.js +73 -48
  47. package/lib/esm/features/async-data-loader/types.d.ts +17 -14
  48. package/lib/esm/features/drag-and-drop/feature.js +99 -94
  49. package/lib/esm/features/drag-and-drop/types.d.ts +17 -29
  50. package/lib/esm/features/drag-and-drop/types.js +6 -6
  51. package/lib/esm/features/drag-and-drop/utils.d.ts +18 -3
  52. package/lib/esm/features/drag-and-drop/utils.js +44 -49
  53. package/lib/esm/features/expand-all/feature.js +26 -3
  54. package/lib/esm/features/expand-all/types.d.ts +3 -1
  55. package/lib/esm/features/hotkeys-core/feature.js +7 -3
  56. package/lib/esm/features/hotkeys-core/types.d.ts +4 -5
  57. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +2 -0
  58. package/lib/esm/features/keyboard-drag-and-drop/feature.js +204 -0
  59. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +27 -0
  60. package/lib/esm/features/keyboard-drag-and-drop/types.js +8 -0
  61. package/lib/esm/features/prop-memoization/feature.js +2 -2
  62. package/lib/esm/features/prop-memoization/types.d.ts +2 -2
  63. package/lib/esm/features/renaming/feature.js +1 -1
  64. package/lib/esm/features/search/feature.js +2 -0
  65. package/lib/esm/features/search/types.d.ts +2 -2
  66. package/lib/esm/features/selection/feature.js +4 -4
  67. package/lib/esm/features/selection/types.d.ts +1 -1
  68. package/lib/esm/features/sync-data-loader/feature.js +31 -5
  69. package/lib/esm/features/sync-data-loader/types.d.ts +5 -5
  70. package/lib/esm/features/tree/feature.js +4 -7
  71. package/lib/esm/features/tree/types.d.ts +7 -5
  72. package/lib/esm/index.d.ts +2 -0
  73. package/lib/esm/index.js +2 -0
  74. package/lib/esm/mddocs-entry.d.ts +10 -0
  75. package/lib/esm/test-utils/test-tree-do.d.ts +2 -2
  76. package/lib/esm/test-utils/test-tree-do.js +19 -6
  77. package/lib/esm/test-utils/test-tree-expect.d.ts +5 -3
  78. package/lib/esm/test-utils/test-tree-expect.js +3 -0
  79. package/lib/esm/test-utils/test-tree.d.ts +2 -1
  80. package/lib/esm/test-utils/test-tree.js +24 -21
  81. package/lib/esm/types/core.d.ts +2 -1
  82. package/lib/esm/utilities/create-on-drop-handler.d.ts +2 -2
  83. package/lib/esm/utilities/create-on-drop-handler.js +13 -4
  84. package/lib/esm/utilities/insert-items-at-target.d.ts +2 -2
  85. package/lib/esm/utilities/insert-items-at-target.js +21 -12
  86. package/lib/esm/utilities/remove-items-from-parents.d.ts +1 -1
  87. package/lib/esm/utilities/remove-items-from-parents.js +12 -3
  88. package/package.json +2 -2
  89. package/src/core/core.spec.ts +31 -0
  90. package/src/core/create-tree.ts +15 -5
  91. package/src/features/async-data-loader/async-data-loader.spec.ts +10 -6
  92. package/src/features/async-data-loader/feature.ts +76 -48
  93. package/src/features/async-data-loader/types.ts +18 -11
  94. package/src/features/drag-and-drop/drag-and-drop.spec.ts +75 -89
  95. package/src/features/drag-and-drop/feature.ts +21 -22
  96. package/src/features/drag-and-drop/types.ts +23 -35
  97. package/src/features/drag-and-drop/utils.ts +67 -57
  98. package/src/features/expand-all/feature.ts +29 -5
  99. package/src/features/expand-all/types.ts +3 -1
  100. package/src/features/hotkeys-core/feature.ts +4 -0
  101. package/src/features/hotkeys-core/types.ts +4 -13
  102. package/src/features/keyboard-drag-and-drop/feature.ts +255 -0
  103. package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +401 -0
  104. package/src/features/keyboard-drag-and-drop/types.ts +30 -0
  105. package/src/features/prop-memoization/feature.ts +2 -2
  106. package/src/features/prop-memoization/prop-memoization.spec.ts +2 -2
  107. package/src/features/prop-memoization/types.ts +2 -2
  108. package/src/features/renaming/feature.ts +8 -2
  109. package/src/features/search/feature.ts +2 -0
  110. package/src/features/search/types.ts +2 -2
  111. package/src/features/selection/feature.ts +4 -4
  112. package/src/features/selection/types.ts +1 -1
  113. package/src/features/sync-data-loader/feature.ts +26 -7
  114. package/src/features/sync-data-loader/types.ts +5 -5
  115. package/src/features/tree/feature.ts +8 -11
  116. package/src/features/tree/types.ts +7 -5
  117. package/src/index.ts +2 -0
  118. package/src/mddocs-entry.ts +16 -0
  119. package/src/test-utils/test-tree-do.ts +3 -3
  120. package/src/test-utils/test-tree-expect.ts +7 -2
  121. package/src/test-utils/test-tree.ts +26 -22
  122. package/src/types/core.ts +2 -0
  123. package/src/utilities/create-on-drop-handler.ts +4 -4
  124. package/src/utilities/insert-items-at-target.ts +18 -14
  125. package/src/utilities/remove-items-from-parents.ts +6 -3
@@ -1,17 +1,43 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.syncDataLoaderFeature = void 0;
4
13
  const utils_1 = require("../../utils");
14
+ const errors_1 = require("../../utilities/errors");
15
+ const promiseErrorMessage = "sync dataLoader returned promise";
5
16
  exports.syncDataLoaderFeature = {
6
17
  key: "sync-data-loader",
7
- getInitialState: (initialState) => (Object.assign({ loadingItems: [] }, initialState)),
8
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItems: (0, utils_1.makeStateUpdater)("loadingItems", tree) }, defaultConfig)),
18
+ getInitialState: (initialState) => (Object.assign({ loadingItemData: [], loadingItemChildrens: [] }, initialState)),
19
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItemData: (0, utils_1.makeStateUpdater)("loadingItemData", tree), setLoadingItemChildrens: (0, utils_1.makeStateUpdater)("loadingItemChildrens", tree) }, defaultConfig)),
9
20
  stateHandlerNames: {
10
- loadingItems: "setLoadingItems",
21
+ loadingItemData: "setLoadingItemData",
22
+ loadingItemChildrens: "setLoadingItemChildrens",
11
23
  },
12
24
  treeInstance: {
13
- retrieveItemData: ({ tree }, itemId) => tree.getConfig().dataLoader.getItem(itemId),
14
- retrieveChildrenIds: ({ tree }, itemId) => tree.getConfig().dataLoader.getChildren(itemId),
25
+ waitForItemDataLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
26
+ waitForItemChildrenLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
27
+ retrieveItemData: ({ tree }, itemId) => {
28
+ const data = tree.getConfig().dataLoader.getItem(itemId);
29
+ if (typeof data === "object" && "then" in data) {
30
+ throw (0, errors_1.throwError)(promiseErrorMessage);
31
+ }
32
+ return data;
33
+ },
34
+ retrieveChildrenIds: ({ tree }, itemId) => {
35
+ const data = tree.getConfig().dataLoader.getChildren(itemId);
36
+ if (typeof data === "object" && "then" in data) {
37
+ throw (0, errors_1.throwError)(promiseErrorMessage);
38
+ }
39
+ return data;
40
+ },
15
41
  },
16
42
  itemInstance: {
17
43
  isLoading: () => false,
@@ -1,12 +1,12 @@
1
- export type SyncTreeDataLoader<T> = {
2
- getItem: (itemId: string) => T;
3
- getChildren: (itemId: string) => string[];
4
- };
1
+ export interface TreeDataLoader<T> {
2
+ getItem: (itemId: string) => T | Promise<T>;
3
+ getChildren: (itemId: string) => string[] | Promise<string[]>;
4
+ }
5
5
  export type SyncDataLoaderFeatureDef<T> = {
6
6
  state: {};
7
7
  config: {
8
8
  rootItemId: string;
9
- dataLoader?: SyncTreeDataLoader<T>;
9
+ dataLoader: TreeDataLoader<T>;
10
10
  };
11
11
  treeInstance: {
12
12
  retrieveItemData: (itemId: string) => T;
@@ -24,7 +24,7 @@ exports.treeFeature = {
24
24
  const { rootItemId } = tree.getConfig();
25
25
  const { expandedItems } = tree.getState();
26
26
  const flatItems = [];
27
- const expandedItemsSet = new Set(expandedItems);
27
+ const expandedItemsSet = new Set(expandedItems); // TODO support setting state expandedItems as set instead of array
28
28
  const recursiveAdd = (itemId, parentId, level, setSize, posInSet) => {
29
29
  var _a;
30
30
  flatItems.push({
@@ -36,7 +36,6 @@ exports.treeFeature = {
36
36
  posInSet,
37
37
  });
38
38
  if (expandedItemsSet.has(itemId)) {
39
- // TODO THIS MADE A HUGE DIFFERENCE!
40
39
  const children = (_a = tree.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : [];
41
40
  let i = 0;
42
41
  for (const childId of children) {
@@ -82,7 +81,7 @@ exports.treeFeature = {
82
81
  }));
83
82
  },
84
83
  // TODO add label parameter
85
- getContainerProps: ({ prev, tree }) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": "", ref: tree.registerElement })),
84
+ getContainerProps: ({ prev, tree }, treeLabel) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": treeLabel !== null && treeLabel !== void 0 ? treeLabel : "", ref: tree.registerElement })),
86
85
  // relevant for hotkeys of this feature
87
86
  isSearchOpen: () => false,
88
87
  },
@@ -118,7 +117,7 @@ exports.treeFeature = {
118
117
  if (!item.isFolder()) {
119
118
  return;
120
119
  }
121
- if ((_a = tree.getState().loadingItems) === null || _a === void 0 ? void 0 : _a.includes(itemId)) {
120
+ if ((_a = tree.getState().loadingItemChildrens) === null || _a === void 0 ? void 0 : _a.includes(itemId)) {
122
121
  return;
123
122
  }
124
123
  tree.applySubStateUpdate("expandedItems", (expandedItems) => [
@@ -157,9 +156,7 @@ exports.treeFeature = {
157
156
  ? tree.getItemInstance(item.getItemMeta().parentId)
158
157
  : undefined,
159
158
  getIndexInParent: ({ item }) => item.getItemMeta().posInSet,
160
- getChildren: ({ tree, item }) => tree
161
- .retrieveChildrenIds(item.getItemMeta().itemId)
162
- .map((id) => tree.getItemInstance(id)),
159
+ getChildren: ({ tree, itemId }) => tree.retrieveChildrenIds(itemId).map((id) => tree.getItemInstance(id)),
163
160
  getTree: ({ tree }) => tree,
164
161
  getItemAbove: ({ tree, item }) => tree.getItems()[item.getItemMeta().index - 1],
165
162
  getItemBelow: ({ tree, item }) => tree.getItems()[item.getItemMeta().index + 1],
@@ -1,16 +1,16 @@
1
1
  import { ItemInstance, SetStateFn, TreeInstance } from "../../types/core";
2
- export type ItemMeta = {
2
+ export interface ItemMeta {
3
3
  itemId: string;
4
4
  parentId: string;
5
5
  level: number;
6
6
  index: number;
7
7
  setSize: number;
8
8
  posInSet: number;
9
- };
10
- export type TreeItemDataRef = {
9
+ }
10
+ export interface TreeItemDataRef {
11
11
  memoizedValues: Record<string, any>;
12
12
  memoizedDeps: Record<string, any[] | undefined>;
13
- };
13
+ }
14
14
  export type TreeFeatureDef<T> = {
15
15
  state: {
16
16
  expandedItems: string[];
@@ -31,7 +31,9 @@ export type TreeFeatureDef<T> = {
31
31
  focusNextItem: () => void;
32
32
  focusPreviousItem: () => void;
33
33
  updateDomFocus: () => void;
34
- getContainerProps: () => Record<string, any>;
34
+ /** Pass to the container rendering the tree children. The `treeLabel` parameter
35
+ * will be passed as `aria-label` parameter, and is recommended to be set. */
36
+ getContainerProps: (treeLabel?: string) => Record<string, any>;
35
37
  };
36
38
  itemInstance: {
37
39
  getId: () => string;
@@ -3,6 +3,7 @@ export * from "./core/create-tree";
3
3
  export * from "./features/tree/types";
4
4
  export { MainFeatureDef, InstanceBuilder } from "./features/main/types";
5
5
  export * from "./features/drag-and-drop/types";
6
+ export * from "./features/keyboard-drag-and-drop/types";
6
7
  export * from "./features/selection/types";
7
8
  export * from "./features/async-data-loader/types";
8
9
  export * from "./features/sync-data-loader/types";
@@ -16,6 +17,7 @@ export * from "./features/hotkeys-core/feature";
16
17
  export * from "./features/async-data-loader/feature";
17
18
  export * from "./features/sync-data-loader/feature";
18
19
  export * from "./features/drag-and-drop/feature";
20
+ export * from "./features/keyboard-drag-and-drop/feature";
19
21
  export * from "./features/search/feature";
20
22
  export * from "./features/renaming/feature";
21
23
  export * from "./features/expand-all/feature";
package/lib/cjs/index.js CHANGED
@@ -18,6 +18,7 @@ __exportStar(require("./types/core"), exports);
18
18
  __exportStar(require("./core/create-tree"), exports);
19
19
  __exportStar(require("./features/tree/types"), exports);
20
20
  __exportStar(require("./features/drag-and-drop/types"), exports);
21
+ __exportStar(require("./features/keyboard-drag-and-drop/types"), exports);
21
22
  __exportStar(require("./features/selection/types"), exports);
22
23
  __exportStar(require("./features/async-data-loader/types"), exports);
23
24
  __exportStar(require("./features/sync-data-loader/types"), exports);
@@ -31,6 +32,7 @@ __exportStar(require("./features/hotkeys-core/feature"), exports);
31
32
  __exportStar(require("./features/async-data-loader/feature"), exports);
32
33
  __exportStar(require("./features/sync-data-loader/feature"), exports);
33
34
  __exportStar(require("./features/drag-and-drop/feature"), exports);
35
+ __exportStar(require("./features/keyboard-drag-and-drop/feature"), exports);
34
36
  __exportStar(require("./features/search/feature"), exports);
35
37
  __exportStar(require("./features/renaming/feature"), exports);
36
38
  __exportStar(require("./features/expand-all/feature"), exports);
@@ -9,6 +9,7 @@ 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
11
  import { PropMemoizationFeatureDef } from "./features/prop-memoization/types";
12
+ import { KeyboardDragAndDropFeatureDef } from "./features/keyboard-drag-and-drop/types";
12
13
  export * from ".";
13
14
  /** @interface */
14
15
  export type AsyncDataLoaderFeatureConfig<T> = AsyncDataLoaderFeatureDef<T>["config"];
@@ -29,6 +30,15 @@ export type DragAndDropFeatureTreeInstance<T> = DragAndDropFeatureDef<T>["treeIn
29
30
  export type DragAndDropFeatureItemInstance<T> = DragAndDropFeatureDef<T>["itemInstance"];
30
31
  export type DragAndDropFeatureHotkeys<T> = DragAndDropFeatureDef<T>["hotkeys"];
31
32
  /** @interface */
33
+ export type KeyboardDragAndDropFeatureConfig<T> = KeyboardDragAndDropFeatureDef<T>["config"];
34
+ /** @interface */
35
+ export type KeyboardDragAndDropFeatureState<T> = KeyboardDragAndDropFeatureDef<T>["state"];
36
+ /** @interface */
37
+ export type KeyboardDragAndDropFeatureTreeInstance<T> = KeyboardDragAndDropFeatureDef<T>["treeInstance"];
38
+ /** @interface */
39
+ export type KeyboardDragAndDropFeatureItemInstance<T> = KeyboardDragAndDropFeatureDef<T>["itemInstance"];
40
+ export type KeyboardDragAndDropFeatureHotkeys<T> = KeyboardDragAndDropFeatureDef<T>["hotkeys"];
41
+ /** @interface */
32
42
  export type ExpandAllFeatureConfig = ExpandAllFeatureDef["config"];
33
43
  /** @interface */
34
44
  export type ExpandAllFeatureState = ExpandAllFeatureDef["state"];
@@ -17,7 +17,7 @@ export declare class TestTreeDo<T> {
17
17
  dragOverNotAllowed(itemId: string, event?: DragEvent): DragEvent<Element>;
18
18
  dragLeave(itemId: string): void;
19
19
  dragEnd(itemId: string, event?: DragEvent): DragEvent<Element>;
20
- drop(itemId: string, event?: DragEvent): DragEvent<Element>;
21
- dragOverAndDrop(itemId: string, event?: DragEvent): DragEvent<Element>;
20
+ drop(itemId: string, event?: DragEvent): Promise<DragEvent<Element>>;
21
+ dragOverAndDrop(itemId: string, event?: DragEvent): Promise<DragEvent<Element>>;
22
22
  private consistentCalls;
23
23
  }
@@ -1,4 +1,13 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.TestTreeDo = void 0;
4
13
  const vitest_1 = require("vitest");
@@ -79,14 +88,18 @@ class TestTreeDo {
79
88
  return e;
80
89
  }
81
90
  drop(itemId, event) {
82
- const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
83
- this.itemProps(itemId).onDrop(e);
84
- return e;
91
+ return __awaiter(this, void 0, void 0, function* () {
92
+ const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
93
+ yield this.itemProps(itemId).onDrop(e);
94
+ return e;
95
+ });
85
96
  }
86
97
  dragOverAndDrop(itemId, event) {
87
- const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
88
- this.dragOver(itemId, e);
89
- return this.drop(itemId, e);
98
+ return __awaiter(this, void 0, void 0, function* () {
99
+ const e = event !== null && event !== void 0 ? event : test_tree_1.TestTree.dragEvent();
100
+ this.dragOver(itemId, e);
101
+ return this.drop(itemId, e);
102
+ });
90
103
  }
91
104
  consistentCalls(fn) {
92
105
  if (!vitest_1.vi.isMockFunction(fn)) {
@@ -1,15 +1,17 @@
1
1
  import { DragEvent } from "react";
2
2
  import { TestTree } from "./test-tree";
3
- import { DropTarget } from "../features/drag-and-drop/types";
3
+ import { DragTarget } from "../features/drag-and-drop/types";
4
+ import { TreeState } from "../types/core";
4
5
  export declare class TestTreeExpect<T> {
5
6
  private tree;
6
- protected itemInstance(itemId: string): import("..").ItemInstance<T>;
7
+ protected itemInstance(itemId: string): import("../types/core").ItemInstance<T>;
7
8
  protected itemProps(itemId: string): Record<string, any>;
8
9
  constructor(tree: TestTree<T>);
9
10
  foldersExpanded(...itemIds: string[]): void;
10
11
  foldersCollapsed(...itemIds: string[]): void;
11
12
  hasChildren(itemId: string, children: string[]): void;
12
- dropped(draggedItems: string[], target: DropTarget<any>): void;
13
+ substate<K extends keyof TreeState<T>>(key: K, value: TreeState<T>[K]): void;
14
+ dropped(draggedItems: string[], target: DragTarget<any>): void;
13
15
  dragOverNotAllowed(itemId: string, event?: DragEvent): DragEvent<Element>;
14
16
  defaultDragLineProps(indent?: number): void;
15
17
  }
@@ -29,6 +29,9 @@ class TestTreeExpect {
29
29
  const itemChildren = item.getChildren().map((child) => child.getId());
30
30
  (0, vitest_1.expect)(itemChildren).toEqual(children);
31
31
  }
32
+ substate(key, value) {
33
+ (0, vitest_1.expect)(this.tree.instance.getState()[key]).toEqual(value);
34
+ }
32
35
  dropped(draggedItems, target) {
33
36
  (0, vitest_1.expect)(this.tree.instance.getConfig().onDrop).toBeCalledWith(draggedItems.map((id) => this.tree.item(id)), target);
34
37
  }
@@ -8,6 +8,7 @@ export declare class TestTree<T = string> {
8
8
  readonly expect: TestTreeExpect<T>;
9
9
  private treeInstance;
10
10
  private static asyncLoaderResolvers;
11
+ private asyncDataLoaderImp;
11
12
  suits: {
12
13
  sync: () => {
13
14
  tree: TestTree<T>;
@@ -41,7 +42,7 @@ export declare class TestTree<T = string> {
41
42
  reset(): void;
42
43
  debug(): void;
43
44
  setElementBoundingBox(itemId: string, bb?: Partial<DOMRect>): void;
44
- static dragEvent(pageX?: number, pageY?: number): DragEvent;
45
+ static dragEvent(clientX?: number, clientY?: number): DragEvent;
45
46
  createTopDragEvent(indent?: number): DragEvent<Element>;
46
47
  createBottomDragEvent(indent?: number): DragEvent<Element>;
47
48
  }
@@ -42,13 +42,31 @@ class TestTree {
42
42
  this.do = new test_tree_do_1.TestTreeDo(this);
43
43
  this.expect = new test_tree_expect_1.TestTreeExpect(this);
44
44
  this.treeInstance = null;
45
+ this.asyncDataLoaderImp = {
46
+ getItem: (id) => __awaiter(this, void 0, void 0, function* () {
47
+ yield new Promise((r) => {
48
+ r.debugName = `Loading getItem ${id}`;
49
+ TestTree.asyncLoaderResolvers.push(r);
50
+ });
51
+ return id;
52
+ }),
53
+ getChildren: (id) => __awaiter(this, void 0, void 0, function* () {
54
+ yield new Promise((r) => {
55
+ r.debugName = `Loading getChildren ${id}`;
56
+ TestTree.asyncLoaderResolvers.push(r);
57
+ });
58
+ return [`${id}1`, `${id}2`, `${id}3`, `${id}4`];
59
+ }),
60
+ };
45
61
  this.suits = {
46
62
  sync: () => ({
47
63
  tree: this.withFeatures(feature_1.syncDataLoaderFeature),
48
64
  title: "Synchronous Data Loader",
49
65
  }),
50
66
  async: () => ({
51
- tree: this.withFeatures(feature_2.asyncDataLoaderFeature),
67
+ tree: this.withFeatures(feature_2.asyncDataLoaderFeature).with({
68
+ dataLoader: this.asyncDataLoaderImp,
69
+ }),
52
70
  title: "Asynchronous Data Loader",
53
71
  }),
54
72
  proxifiedSync: () => ({
@@ -68,12 +86,12 @@ class TestTree {
68
86
  static resolveAsyncLoaders() {
69
87
  return __awaiter(this, void 0, void 0, function* () {
70
88
  var _a;
71
- while (TestTree.asyncLoaderResolvers.length) {
89
+ do {
72
90
  (_a = TestTree.asyncLoaderResolvers.shift()) === null || _a === void 0 ? void 0 : _a();
73
91
  yield new Promise((r) => {
74
92
  setTimeout(r);
75
93
  });
76
- }
94
+ } while (TestTree.asyncLoaderResolvers.length);
77
95
  });
78
96
  }
79
97
  resolveAsyncVisibleItems() {
@@ -88,21 +106,6 @@ class TestTree {
88
106
  return new TestTree(Object.assign({ rootItemId: "x", createLoadingItemData: () => "loading", dataLoader: {
89
107
  getItem: (id) => id,
90
108
  getChildren: (id) => [`${id}1`, `${id}2`, `${id}3`, `${id}4`],
91
- }, asyncDataLoader: {
92
- getItem: (id) => __awaiter(this, void 0, void 0, function* () {
93
- yield new Promise((r) => {
94
- r.debugName = `Loading getItem ${id}`;
95
- TestTree.asyncLoaderResolvers.push(r);
96
- });
97
- return id;
98
- }),
99
- getChildren: (id) => __awaiter(this, void 0, void 0, function* () {
100
- yield new Promise((r) => {
101
- r.debugName = `Loading getChildren ${id}`;
102
- TestTree.asyncLoaderResolvers.push(r);
103
- });
104
- return [`${id}1`, `${id}2`, `${id}3`, `${id}4`];
105
- }),
106
109
  }, getItemName: (item) => item.getItemData(), indent: 20, isItemFolder: (item) => item.getItemMeta().level < 2, initialState: {
107
110
  expandedItems: ["x1", "x11"],
108
111
  }, features: [] }, config));
@@ -179,7 +182,7 @@ class TestTree {
179
182
  getBoundingClientRect: () => bb,
180
183
  });
181
184
  }
182
- static dragEvent(pageX = 1000, pageY = 0) {
185
+ static dragEvent(clientX = 1000, clientY = 0) {
183
186
  return {
184
187
  preventDefault: vitest_1.vi.fn(),
185
188
  stopPropagation: vitest_1.vi.fn(),
@@ -188,8 +191,8 @@ class TestTree {
188
191
  getData: vitest_1.vi.fn(),
189
192
  dropEffect: "unchaged-from-test",
190
193
  },
191
- pageX,
192
- pageY,
194
+ clientX,
195
+ clientY,
193
196
  };
194
197
  }
195
198
  createTopDragEvent(indent = 0) {
@@ -9,6 +9,7 @@ import { SearchFeatureDef } from "../features/search/types";
9
9
  import { RenamingFeatureDef } from "../features/renaming/types";
10
10
  import { ExpandAllFeatureDef } from "../features/expand-all/types";
11
11
  import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
12
+ import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
12
13
  export type Updater<T> = T | ((old: T) => T);
13
14
  export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
14
15
  export type FeatureDef = {
@@ -33,7 +34,7 @@ type MergedFeatures<F extends FeatureDef> = {
33
34
  itemInstance: UnionToIntersection<F["itemInstance"]>;
34
35
  hotkeys: F["hotkeys"];
35
36
  };
36
- export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | DragAndDropFeatureDef<T> | HotkeysCoreFeatureDef<T> | SyncDataLoaderFeatureDef<T> | AsyncDataLoaderFeatureDef<T> | SearchFeatureDef<T> | RenamingFeatureDef<T> | ExpandAllFeatureDef | PropMemoizationFeatureDef;
37
+ export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | DragAndDropFeatureDef<T> | KeyboardDragAndDropFeatureDef<T> | HotkeysCoreFeatureDef<T> | SyncDataLoaderFeatureDef<T> | AsyncDataLoaderFeatureDef<T> | SearchFeatureDef<T> | RenamingFeatureDef<T> | ExpandAllFeatureDef | PropMemoizationFeatureDef;
37
38
  type TreeStateType<T> = MergedFeatures<RegisteredFeatures<T>>["state"];
38
39
  export interface TreeState<T> extends TreeStateType<T> {
39
40
  }
@@ -1,3 +1,3 @@
1
1
  import { ItemInstance } from "../types/core";
2
- import { DropTarget } from "../features/drag-and-drop/types";
3
- export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target: DropTarget<T>) => void;
2
+ import { DragTarget } from "../features/drag-and-drop/types";
3
+ export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target: DragTarget<T>) => Promise<void>;
@@ -1,11 +1,20 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.createOnDropHandler = void 0;
4
13
  const remove_items_from_parents_1 = require("./remove-items-from-parents");
5
14
  const insert_items_at_target_1 = require("./insert-items-at-target");
6
- const createOnDropHandler = (onChangeChildren) => (items, target) => {
15
+ const createOnDropHandler = (onChangeChildren) => (items, target) => __awaiter(void 0, void 0, void 0, function* () {
7
16
  const itemIds = items.map((item) => item.getId());
8
- (0, remove_items_from_parents_1.removeItemsFromParents)(items, onChangeChildren);
9
- (0, insert_items_at_target_1.insertItemsAtTarget)(itemIds, target, onChangeChildren);
10
- };
17
+ yield (0, remove_items_from_parents_1.removeItemsFromParents)(items, onChangeChildren);
18
+ yield (0, insert_items_at_target_1.insertItemsAtTarget)(itemIds, target, onChangeChildren);
19
+ });
11
20
  exports.createOnDropHandler = createOnDropHandler;
@@ -1,3 +1,3 @@
1
1
  import { ItemInstance } from "../types/core";
2
- import { DropTarget } from "../features/drag-and-drop/types";
3
- export declare const insertItemsAtTarget: <T>(itemIds: string[], target: DropTarget<T>, onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void) => void;
2
+ import { DragTarget } from "../features/drag-and-drop/types";
3
+ export declare const insertItemsAtTarget: <T>(itemIds: string[], target: DragTarget<T>, onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => Promise<void> | void) => Promise<void>;
@@ -1,14 +1,24 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.insertItemsAtTarget = void 0;
4
- const insertItemsAtTarget = (itemIds, target, onChangeChildren) => {
13
+ const insertItemsAtTarget = (itemIds, target, onChangeChildren) => __awaiter(void 0, void 0, void 0, function* () {
14
+ yield target.item.getTree().waitForItemChildrenLoaded(target.item.getId());
15
+ const oldChildrenIds = target.item
16
+ .getTree()
17
+ .retrieveChildrenIds(target.item.getId());
5
18
  // add moved items to new common parent, if dropped onto parent
6
- if (target.childIndex === null) {
7
- const newChildren = [
8
- ...target.item.getChildren().map((item) => item.getId()),
9
- ...itemIds,
10
- ];
11
- onChangeChildren(target.item, newChildren);
19
+ if (!("childIndex" in target)) {
20
+ const newChildren = [...oldChildrenIds, ...itemIds];
21
+ yield onChangeChildren(target.item, newChildren);
12
22
  if (target.item && "updateCachedChildrenIds" in target.item) {
13
23
  target.item.updateCachedChildrenIds(newChildren);
14
24
  }
@@ -16,16 +26,15 @@ const insertItemsAtTarget = (itemIds, target, onChangeChildren) => {
16
26
  return;
17
27
  }
18
28
  // add moved items to new common parent, if dropped between siblings
19
- const oldChildren = target.item.getChildren();
20
29
  const newChildren = [
21
- ...oldChildren.slice(0, target.insertionIndex).map((item) => item.getId()),
30
+ ...oldChildrenIds.slice(0, target.insertionIndex),
22
31
  ...itemIds,
23
- ...oldChildren.slice(target.insertionIndex).map((item) => item.getId()),
32
+ ...oldChildrenIds.slice(target.insertionIndex),
24
33
  ];
25
- onChangeChildren(target.item, newChildren);
34
+ yield onChangeChildren(target.item, newChildren);
26
35
  if (target.item && "updateCachedChildrenIds" in target.item) {
27
36
  target.item.updateCachedChildrenIds(newChildren);
28
37
  }
29
38
  target.item.getTree().rebuildTree();
30
- };
39
+ });
31
40
  exports.insertItemsAtTarget = insertItemsAtTarget;
@@ -1,2 +1,2 @@
1
1
  import { ItemInstance } from "../types/core";
2
- export declare const removeItemsFromParents: <T>(movedItems: ItemInstance<T>[], onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void) => void;
2
+ export declare const removeItemsFromParents: <T>(movedItems: ItemInstance<T>[], onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void | Promise<void>) => Promise<void>;
@@ -1,7 +1,16 @@
1
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
+ };
2
11
  Object.defineProperty(exports, "__esModule", { value: true });
3
12
  exports.removeItemsFromParents = void 0;
4
- const removeItemsFromParents = (movedItems, onChangeChildren) => {
13
+ const removeItemsFromParents = (movedItems, onChangeChildren) => __awaiter(void 0, void 0, void 0, function* () {
5
14
  const movedItemsIds = movedItems.map((item) => item.getId());
6
15
  const uniqueParents = [
7
16
  ...new Set(movedItems.map((item) => item.getParent())),
@@ -12,12 +21,12 @@ const removeItemsFromParents = (movedItems, onChangeChildren) => {
12
21
  const newChildren = siblings
13
22
  .filter((sibling) => !movedItemsIds.includes(sibling.getId()))
14
23
  .map((i) => i.getId());
15
- onChangeChildren(parent, newChildren);
24
+ yield onChangeChildren(parent, newChildren);
16
25
  if (parent && "updateCachedChildrenIds" in parent) {
17
26
  parent === null || parent === void 0 ? void 0 : parent.updateCachedChildrenIds(newChildren);
18
27
  }
19
28
  }
20
29
  }
21
30
  movedItems[0].getTree().rebuildTree();
22
- };
31
+ });
23
32
  exports.removeItemsFromParents = removeItemsFromParents;
@@ -89,6 +89,7 @@ export const createTree = (initialConfig) => {
89
89
  // Not necessary, since I think the subupdate below keeps the state fresh anyways?
90
90
  // state = typeof updater === "function" ? updater(state) : updater;
91
91
  (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state); // TODO this cant be right... This doesnt allow external state updates
92
+ // TODO this is never used, remove
92
93
  },
93
94
  applySubStateUpdate: ({}, stateName, updater) => {
94
95
  state[stateName] =
@@ -104,9 +105,18 @@ export const createTree = (initialConfig) => {
104
105
  },
105
106
  getConfig: () => config,
106
107
  setConfig: (_, updater) => {
107
- config = typeof updater === "function" ? updater(config) : updater;
108
- if (config.state) {
109
- state = Object.assign(Object.assign({}, state), config.state);
108
+ var _a, _b, _c;
109
+ const newConfig = typeof updater === "function" ? updater(config) : updater;
110
+ const hasChangedExpandedItems = ((_a = newConfig.state) === null || _a === void 0 ? void 0 : _a.expandedItems) &&
111
+ ((_b = newConfig.state) === null || _b === void 0 ? void 0 : _b.expandedItems) !== state.expandedItems;
112
+ config = newConfig;
113
+ if (newConfig.state) {
114
+ state = Object.assign(Object.assign({}, state), newConfig.state);
115
+ }
116
+ if (hasChangedExpandedItems) {
117
+ // if expanded items where changed from the outside
118
+ rebuildItemMeta();
119
+ (_c = config.setState) === null || _c === void 0 ? void 0 : _c.call(config, state);
110
120
  }
111
121
  },
112
122
  getItemInstance: ({}, itemId) => itemInstancesMap[itemId],
@@ -128,7 +138,6 @@ export const createTree = (initialConfig) => {
128
138
  getHotkeyPresets: () => hotkeyPresets,
129
139
  },
130
140
  itemInstance: {
131
- // TODO just change to a getRef method that memoizes, maybe as part of getProps
132
141
  registerElement: ({ itemId, item }, element) => {
133
142
  if (itemElementsMap[itemId] === element) {
134
143
  return;