@headless-tree/core 0.0.13 → 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 +13 -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
@@ -41,11 +41,17 @@ describe("core-feature/selections", () => {
41
41
 
42
42
  describe("calls handlers", () => {
43
43
  it("updates setLoadingItems", async () => {
44
- const setLoadingItems = tree.mockedHandler("setLoadingItems");
44
+ const setLoadingItemChildrens = tree.mockedHandler(
45
+ "setLoadingItemChildrens",
46
+ );
47
+ const setLoadingItemData = tree.mockedHandler("setLoadingItemData");
45
48
  tree.do.selectItem("x12");
46
- expect(setLoadingItems).toHaveBeenCalledWith(["x12"]);
49
+ expect(setLoadingItemChildrens).toHaveBeenCalledWith(["x12"]);
50
+ expect(setLoadingItemData).not.toHaveBeenCalled();
47
51
  await tree.resolveAsyncVisibleItems();
48
- expect(setLoadingItems).toHaveBeenCalledWith([]);
52
+ expect(setLoadingItemChildrens).toHaveBeenCalledWith([]);
53
+ expect(setLoadingItemData).toHaveBeenCalledWith(["x121"]);
54
+ expect(setLoadingItemData).toHaveBeenCalledWith([]);
49
55
  });
50
56
 
51
57
  it("calls onLoadedItem", async () => {
@@ -76,7 +82,7 @@ describe("core-feature/selections", () => {
76
82
  `${id}3`,
77
83
  `${id}4`,
78
84
  ]);
79
- const suiteTree = tree.with({ asyncDataLoader: { getItem, getChildren } });
85
+ const suiteTree = tree.with({ dataLoader: { getItem, getChildren } });
80
86
  suiteTree.resetBeforeEach();
81
87
 
82
88
  it("invalidates item data on item instance", async () => {
@@ -119,6 +125,4 @@ describe("core-feature/selections", () => {
119
125
  expect(getChildren).toHaveBeenCalledTimes(1);
120
126
  });
121
127
  });
122
-
123
- describe.todo("getChildrenWithData");
124
128
  });
@@ -1,28 +1,57 @@
1
1
  import { FeatureImplementation } from "../../types/core";
2
- import { AsyncDataLoaderRef } from "./types";
2
+ import { AsyncDataLoaderDataRef } from "./types";
3
3
  import { makeStateUpdater } from "../../utils";
4
4
 
5
5
  export const asyncDataLoaderFeature: FeatureImplementation = {
6
6
  key: "async-data-loader",
7
7
 
8
8
  getInitialState: (initialState) => ({
9
- loadingItems: [],
9
+ loadingItemData: [],
10
+ loadingItemChildrens: [],
10
11
  ...initialState,
11
12
  }),
12
13
 
13
14
  getDefaultConfig: (defaultConfig, tree) => ({
14
- setLoadingItems: makeStateUpdater("loadingItems", tree),
15
+ setLoadingItemData: makeStateUpdater("loadingItemData", tree),
16
+ setLoadingItemChildrens: makeStateUpdater("loadingItemChildrens", tree),
15
17
  ...defaultConfig,
16
18
  }),
17
19
 
18
20
  stateHandlerNames: {
19
- loadingItems: "setLoadingItems",
21
+ loadingItemData: "setLoadingItemData",
22
+ loadingItemChildrens: "setLoadingItemChildrens",
20
23
  },
21
24
 
22
25
  treeInstance: {
26
+ waitForItemDataLoaded: async ({ tree }, itemId) => {
27
+ tree.retrieveItemData(itemId);
28
+ if (!tree.getState().loadingItemData.includes(itemId)) {
29
+ return;
30
+ }
31
+ await new Promise<void>((resolve) => {
32
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
33
+ dataRef.current.awaitingItemDataLoading ??= {};
34
+ dataRef.current.awaitingItemDataLoading[itemId] ??= [];
35
+ dataRef.current.awaitingItemDataLoading[itemId].push(resolve);
36
+ });
37
+ },
38
+
39
+ waitForItemChildrenLoaded: async ({ tree }, itemId) => {
40
+ tree.retrieveChildrenIds(itemId);
41
+ if (!tree.getState().loadingItemChildrens.includes(itemId)) {
42
+ return;
43
+ }
44
+ await new Promise<void>((resolve) => {
45
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
46
+ dataRef.current.awaitingItemChildrensLoading ??= {};
47
+ dataRef.current.awaitingItemChildrensLoading[itemId] ??= [];
48
+ dataRef.current.awaitingItemChildrensLoading[itemId].push(resolve);
49
+ });
50
+ },
51
+
23
52
  retrieveItemData: ({ tree }, itemId) => {
24
53
  const config = tree.getConfig();
25
- const dataRef = tree.getDataRef<AsyncDataLoaderRef>();
54
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
26
55
  dataRef.current.itemData ??= {};
27
56
  dataRef.current.childrenIds ??= {};
28
57
 
@@ -30,18 +59,25 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
30
59
  return dataRef.current.itemData[itemId];
31
60
  }
32
61
 
33
- if (!tree.getState().loadingItems.includes(itemId)) {
34
- tree.applySubStateUpdate("loadingItems", (loadingItems) => [
35
- ...loadingItems,
62
+ if (!tree.getState().loadingItemData.includes(itemId)) {
63
+ tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
64
+ ...loadingItemData,
36
65
  itemId,
37
66
  ]);
38
- config.asyncDataLoader?.getItem(itemId).then((item) => {
67
+
68
+ (async () => {
69
+ const item = await config.dataLoader.getItem(itemId);
39
70
  dataRef.current.itemData[itemId] = item;
40
71
  config.onLoadedItem?.(itemId, item);
41
- tree.applySubStateUpdate("loadingItems", (loadingItems) =>
42
- loadingItems.filter((id) => id !== itemId),
72
+ tree.applySubStateUpdate("loadingItemData", (loadingItemData) =>
73
+ loadingItemData.filter((id) => id !== itemId),
43
74
  );
44
- });
75
+
76
+ dataRef.current.awaitingItemDataLoading?.[itemId].forEach((cb) =>
77
+ cb(),
78
+ );
79
+ delete dataRef.current.awaitingItemDataLoading?.[itemId];
80
+ })();
45
81
  }
46
82
 
47
83
  return config.createLoadingItemData?.() ?? null;
@@ -49,46 +85,37 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
49
85
 
50
86
  retrieveChildrenIds: ({ tree }, itemId) => {
51
87
  const config = tree.getConfig();
52
- const dataRef = tree.getDataRef<AsyncDataLoaderRef>();
53
- dataRef.current.itemData ??= {};
88
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
54
89
  dataRef.current.childrenIds ??= {};
55
90
  if (dataRef.current.childrenIds[itemId]) {
56
91
  return dataRef.current.childrenIds[itemId];
57
92
  }
58
93
 
59
- if (tree.getState().loadingItems.includes(itemId)) {
94
+ if (tree.getState().loadingItemChildrens.includes(itemId)) {
60
95
  return [];
61
96
  }
62
97
 
63
- tree.applySubStateUpdate("loadingItems", (loadingItems) => [
64
- ...loadingItems,
65
- itemId,
66
- ]);
67
-
68
- if (config.asyncDataLoader?.getChildrenWithData) {
69
- config.asyncDataLoader?.getChildrenWithData(itemId).then((children) => {
70
- for (const { id, data } of children) {
71
- dataRef.current.itemData[id] = data;
72
- config.onLoadedItem?.(id, data);
73
- }
74
- const childrenIds = children.map(({ id }) => id);
75
- dataRef.current.childrenIds[itemId] = childrenIds;
76
- config.onLoadedChildren?.(itemId, childrenIds);
77
- tree.applySubStateUpdate("loadingItems", (loadingItems) =>
78
- loadingItems.filter((id) => id !== itemId),
79
- );
80
- tree.rebuildTree();
81
- });
82
- } else {
83
- config.asyncDataLoader?.getChildren(itemId).then((childrenIds) => {
84
- dataRef.current.childrenIds[itemId] = childrenIds;
85
- config.onLoadedChildren?.(itemId, childrenIds);
86
- tree.applySubStateUpdate("loadingItems", (loadingItems) =>
87
- loadingItems.filter((id) => id !== itemId),
88
- );
89
- tree.rebuildTree();
90
- });
91
- }
98
+ tree.applySubStateUpdate(
99
+ "loadingItemChildrens",
100
+ (loadingItemChildrens) => [...loadingItemChildrens, itemId],
101
+ );
102
+
103
+ (async () => {
104
+ const childrenIds = await config.dataLoader.getChildren(itemId);
105
+ dataRef.current.childrenIds[itemId] = childrenIds;
106
+ config.onLoadedChildren?.(itemId, childrenIds);
107
+ tree.applySubStateUpdate(
108
+ "loadingItemChildrens",
109
+ (loadingItemChildrens) =>
110
+ loadingItemChildrens.filter((id) => id !== itemId),
111
+ );
112
+ tree.rebuildTree();
113
+
114
+ dataRef.current.awaitingItemChildrensLoading?.[itemId]?.forEach((cb) =>
115
+ cb(),
116
+ );
117
+ delete dataRef.current.awaitingItemChildrensLoading?.[itemId];
118
+ })();
92
119
 
93
120
  return [];
94
121
  },
@@ -96,19 +123,20 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
96
123
 
97
124
  itemInstance: {
98
125
  isLoading: ({ tree, item }) =>
99
- tree.getState().loadingItems.includes(item.getItemMeta().itemId),
126
+ tree.getState().loadingItemData.includes(item.getItemMeta().itemId) ||
127
+ tree.getState().loadingItemChildrens.includes(item.getItemMeta().itemId),
100
128
  invalidateItemData: ({ tree, itemId }) => {
101
- const dataRef = tree.getDataRef<AsyncDataLoaderRef>();
129
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
102
130
  delete dataRef.current.itemData?.[itemId];
103
131
  tree.retrieveItemData(itemId);
104
132
  },
105
133
  invalidateChildrenIds: ({ tree, itemId }) => {
106
- const dataRef = tree.getDataRef<AsyncDataLoaderRef>();
134
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
107
135
  delete dataRef.current.childrenIds?.[itemId];
108
136
  tree.retrieveChildrenIds(itemId);
109
137
  },
110
138
  updateCachedChildrenIds: ({ tree, itemId }, childrenIds) => {
111
- const dataRef = tree.getDataRef<AsyncDataLoaderRef>();
139
+ const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
112
140
  dataRef.current.childrenIds[itemId] = childrenIds;
113
141
  tree.rebuildTree();
114
142
  },
@@ -1,33 +1,40 @@
1
1
  import { SetStateFn } from "../../types/core";
2
2
  import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
3
3
 
4
- export type AsyncTreeDataLoader<T> = {
5
- getItem: (itemId: string) => Promise<T>;
6
- getChildren: (itemId: string) => Promise<string[]>;
7
- getChildrenWithData?: (itemId: string) => Promise<{ id: string; data: T }[]>;
8
- };
4
+ type AwaitingLoaderCallbacks = Record<string, (() => void)[]>;
9
5
 
10
- export type AsyncDataLoaderRef<T = any> = {
6
+ export interface AsyncDataLoaderDataRef<T = any> {
11
7
  itemData: Record<string, T>;
12
8
  childrenIds: Record<string, string[]>;
13
- };
9
+ awaitingItemDataLoading: AwaitingLoaderCallbacks;
10
+ awaitingItemChildrensLoading: AwaitingLoaderCallbacks;
11
+ }
14
12
 
15
13
  /**
16
14
  * @category Async Data Loader/General
17
15
  * */
18
16
  export type AsyncDataLoaderFeatureDef<T> = {
19
17
  state: {
20
- loadingItems: string[];
18
+ loadingItemData: string[];
19
+ loadingItemChildrens: string[];
21
20
  };
22
21
  config: {
23
22
  rootItemId: string;
23
+
24
+ /** Will be called when HT retrieves item data for an item whose item data is asynchronously being loaded.
25
+ * Can be used to create placeholder data to use for rendering the tree item while it is loaded. If not defined,
26
+ * the tree item data will be null. */
24
27
  createLoadingItemData?: () => T;
25
- setLoadingItems?: SetStateFn<string[]>;
28
+
29
+ setLoadingItemData?: SetStateFn<string[]>;
30
+ setLoadingItemChildrens?: SetStateFn<string[]>;
26
31
  onLoadedItem?: (itemId: string, item: T) => void;
27
32
  onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
28
- asyncDataLoader?: AsyncTreeDataLoader<T>;
29
33
  };
30
- treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"];
34
+ treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"] & {
35
+ waitForItemDataLoaded: (itemId: string) => Promise<void>;
36
+ waitForItemChildrenLoaded: (itemId: string) => Promise<void>;
37
+ };
31
38
  itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
32
39
  /** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible */
33
40
  invalidateItemData: () => void;
@@ -31,10 +31,6 @@ describe("core-feature/drag-and-drop", () => {
31
31
  tree.do.startDrag("x111");
32
32
  tree.do.dragOverAndDrop("x21");
33
33
  tree.expect.dropped(["x111"], {
34
- dragLineIndex: null,
35
- dragLineLevel: null,
36
- childIndex: null,
37
- insertionIndex: null,
38
34
  item: tree.item("x21"),
39
35
  });
40
36
  });
@@ -44,10 +40,6 @@ describe("core-feature/drag-and-drop", () => {
44
40
  tree.do.startDrag("x111");
45
41
  tree.do.dragOverAndDrop("x2");
46
42
  tree.expect.dropped(["x111"], {
47
- dragLineIndex: null,
48
- dragLineLevel: null,
49
- childIndex: null,
50
- insertionIndex: null,
51
43
  item: tree.item("x2"),
52
44
  });
53
45
  });
@@ -57,10 +49,6 @@ describe("core-feature/drag-and-drop", () => {
57
49
  tree.do.startDrag("x111");
58
50
  tree.do.dragOverAndDrop("x12");
59
51
  tree.expect.dropped(["x111"], {
60
- dragLineIndex: null,
61
- dragLineLevel: null,
62
- childIndex: null,
63
- insertionIndex: null,
64
52
  item: tree.item("x12"),
65
53
  });
66
54
  });
@@ -109,33 +97,52 @@ describe("core-feature/drag-and-drop", () => {
109
97
  });
110
98
  });
111
99
 
112
- it("drop reparented one level", () => {
100
+ it("drop reparented one level", async () => {
101
+ tree.item("x14").expand();
102
+ await tree.resolveAsyncVisibleItems();
113
103
  tree.do.ctrlSelectItem("x111");
114
104
  tree.do.startDrag("x111");
115
- tree.setElementBoundingBox("x114");
105
+ tree.setElementBoundingBox("x144");
116
106
  const event = tree.createBottomDragEvent(1);
117
- tree.do.dragOverAndDrop("x114", event);
107
+ tree.do.dragOverAndDrop("x144", event);
118
108
  tree.expect.dropped(["x111"], {
119
- dragLineIndex: 6,
109
+ dragLineIndex: 13,
120
110
  dragLineLevel: 1,
111
+ childIndex: 4,
112
+ insertionIndex: 4,
113
+ item: tree.item("x1"),
114
+ });
115
+ });
116
+
117
+ it("drop reparented two levels", async () => {
118
+ tree.item("x14").expand();
119
+ await tree.resolveAsyncVisibleItems();
120
+ tree.do.ctrlSelectItem("x111");
121
+ tree.do.startDrag("x111");
122
+ tree.setElementBoundingBox("x144");
123
+ const event = tree.createBottomDragEvent(0);
124
+ tree.do.dragOverAndDrop("x144", event);
125
+ tree.expect.dropped(["x111"], {
126
+ dragLineIndex: 13,
127
+ dragLineLevel: 0,
121
128
  childIndex: 1,
122
129
  insertionIndex: 1,
123
- item: tree.item("x1"),
130
+ item: tree.item("x"),
124
131
  });
125
132
  });
126
133
 
127
- it("drop reparented two levels", () => {
128
- // TODO reparenting two levels should work at x144, but not at x114
134
+ it("doesnt drop reparented higher than it can", () => {
129
135
  tree.do.ctrlSelectItem("x111");
130
136
  tree.do.startDrag("x111");
137
+ tree.setElementBoundingBox("x114");
131
138
  const event = tree.createBottomDragEvent(0);
132
139
  tree.do.dragOverAndDrop("x114", event);
133
140
  tree.expect.dropped(["x111"], {
134
141
  dragLineIndex: 6,
135
- dragLineLevel: 0,
142
+ dragLineLevel: 1,
136
143
  childIndex: 1,
137
144
  insertionIndex: 1,
138
- item: tree.item("x"),
145
+ item: tree.item("x1"),
139
146
  });
140
147
  });
141
148
 
@@ -147,10 +154,6 @@ describe("core-feature/drag-and-drop", () => {
147
154
  tree.do.startDrag("x111");
148
155
  tree.do.dragOverAndDrop("x21");
149
156
  tree.expect.dropped(["x111", "x112", "x113", "x114"], {
150
- dragLineIndex: null,
151
- dragLineLevel: null,
152
- childIndex: null,
153
- insertionIndex: null,
154
157
  item: tree.item("x21"),
155
158
  });
156
159
  });
@@ -163,10 +166,6 @@ describe("core-feature/drag-and-drop", () => {
163
166
  tree.do.startDrag("x111");
164
167
  tree.do.dragOverAndDrop("x21");
165
168
  tree.expect.dropped(["x111", "x112", "x113", "x114"], {
166
- dragLineIndex: null,
167
- dragLineLevel: null,
168
- childIndex: null,
169
- insertionIndex: null,
170
169
  item: tree.item("x21"),
171
170
  });
172
171
  });
@@ -179,10 +178,6 @@ describe("core-feature/drag-and-drop", () => {
179
178
  tree.do.startDrag("x111");
180
179
  tree.do.dragOverAndDrop("x21");
181
180
  tree.expect.dropped(["x111", "x112", "x113", "x114"], {
182
- dragLineIndex: null,
183
- dragLineLevel: null,
184
- childIndex: null,
185
- insertionIndex: null,
186
181
  item: tree.item("x21"),
187
182
  });
188
183
  });
@@ -199,10 +194,6 @@ describe("core-feature/drag-and-drop", () => {
199
194
  draggedItems: [tree.item("x111")],
200
195
  draggingOverItem: tree.item("x21"),
201
196
  dragTarget: {
202
- childIndex: null,
203
- dragLineIndex: null,
204
- dragLineLevel: null,
205
- insertionIndex: null,
206
197
  item: tree.item("x21"),
207
198
  },
208
199
  });
@@ -270,13 +261,15 @@ describe("core-feature/drag-and-drop", () => {
270
261
  tree.expect.defaultDragLineProps(1);
271
262
  });
272
263
 
273
- it("drop reparented two levels", () => {
264
+ it("drop reparented two levels", async () => {
265
+ tree.item("x14").expand();
266
+ await tree.resolveAsyncVisibleItems();
274
267
  tree.do.ctrlSelectItem("x111");
275
268
  tree.do.startDrag("x111");
276
269
  const event = tree.createBottomDragEvent(0);
277
- tree.setElementBoundingBox("x12");
278
- tree.setElementBoundingBox("x114");
279
- tree.do.dragOver("x114", event);
270
+ tree.setElementBoundingBox("x2");
271
+ tree.setElementBoundingBox("x144");
272
+ tree.do.dragOver("x144", event);
280
273
  tree.expect.defaultDragLineProps(0);
281
274
  });
282
275
  });
@@ -316,10 +309,6 @@ describe("core-feature/drag-and-drop", () => {
316
309
  expect(onDropForeignDragObject).toHaveBeenCalledWith(
317
310
  event.dataTransfer,
318
311
  {
319
- childIndex: null,
320
- dragLineIndex: null,
321
- dragLineLevel: null,
322
- insertionIndex: null,
323
312
  item: tree.item("x11"),
324
313
  },
325
314
  );
@@ -371,10 +360,10 @@ describe("core-feature/drag-and-drop", () => {
371
360
 
372
361
  suiteTree.resetBeforeEach();
373
362
 
374
- it("drags within same tree on folder", () => {
363
+ it("drags within same tree on expanded folder", async () => {
375
364
  suiteTree.do.selectMultiple("x111", "x112");
376
365
  suiteTree.do.startDrag("x111");
377
- suiteTree.do.dragOverAndDrop("x21");
366
+ await suiteTree.do.dragOverAndDrop("x21");
378
367
  expect(changeChildren).toHaveBeenCalledWith("x11", ["x113", "x114"]);
379
368
  expect(changeChildren).toHaveBeenCalledWith("x21", [
380
369
  "x211",
@@ -386,10 +375,26 @@ describe("core-feature/drag-and-drop", () => {
386
375
  ]);
387
376
  });
388
377
 
389
- it("drags within same tree inside folder", () => {
378
+ it("drags within same tree on collapsed folder", async () => {
390
379
  suiteTree.do.selectMultiple("x111", "x112");
391
380
  suiteTree.do.startDrag("x111");
392
- suiteTree.do.dragOverAndDrop(
381
+ suiteTree.do.dragOverAndDrop("x22");
382
+ await suiteTree.resolveAsyncVisibleItems();
383
+ expect(changeChildren).toHaveBeenCalledWith("x11", ["x113", "x114"]);
384
+ expect(changeChildren).toHaveBeenCalledWith("x22", [
385
+ "x221",
386
+ "x222",
387
+ "x223",
388
+ "x224",
389
+ "x111",
390
+ "x112",
391
+ ]);
392
+ });
393
+
394
+ it("drags within same tree inside folder", async () => {
395
+ suiteTree.do.selectMultiple("x111", "x112");
396
+ suiteTree.do.startDrag("x111");
397
+ await suiteTree.do.dragOverAndDrop(
393
398
  "x212",
394
399
  suiteTree.createBottomDragEvent(2),
395
400
  );
@@ -456,10 +461,6 @@ describe("core-feature/drag-and-drop", () => {
456
461
  const e = TestTree.dragEvent();
457
462
  suiteTree.do.drop("x21", e);
458
463
  expect(onDropForeignDragObject).toBeCalledWith(e.dataTransfer, {
459
- childIndex: null,
460
- dragLineIndex: null,
461
- dragLineLevel: null,
462
- insertionIndex: null,
463
464
  item: suiteTree.item("x21"),
464
465
  });
465
466
  });
@@ -476,10 +477,13 @@ describe("core-feature/drag-and-drop", () => {
476
477
  expect(onDropForeignDragObject).not.toHaveBeenCalled();
477
478
  });
478
479
 
479
- it("drags multiple within in retained order (correct order)", () => {
480
+ it("drags multiple within in retained order (correct order)", async () => {
480
481
  suiteTree.do.selectMultiple("x111", "x112", "x113", "x114");
481
482
  suiteTree.do.startDrag("x111");
482
- suiteTree.do.dragOverAndDrop("x212", suiteTree.createBottomDragEvent());
483
+ await suiteTree.do.dragOverAndDrop(
484
+ "x212",
485
+ suiteTree.createBottomDragEvent(),
486
+ );
483
487
  expect(changeChildren).toHaveBeenCalledWith("x11", []);
484
488
  expect(changeChildren).toHaveBeenCalledWith("x21", [
485
489
  "x211",
@@ -493,10 +497,13 @@ describe("core-feature/drag-and-drop", () => {
493
497
  ]);
494
498
  });
495
499
 
496
- it("drags multiple within in retained order (inverse order)", () => {
500
+ it("drags multiple within in retained order (inverse order)", async () => {
497
501
  suiteTree.do.selectMultiple("x114", "x113", "x112", "x111");
498
502
  suiteTree.do.startDrag("x111");
499
- suiteTree.do.dragOverAndDrop("x212", suiteTree.createBottomDragEvent());
503
+ await suiteTree.do.dragOverAndDrop(
504
+ "x212",
505
+ suiteTree.createBottomDragEvent(),
506
+ );
500
507
  expect(changeChildren).toHaveBeenCalledWith("x11", []);
501
508
  expect(changeChildren).toHaveBeenCalledWith("x21", [
502
509
  "x211",
@@ -510,10 +517,13 @@ describe("core-feature/drag-and-drop", () => {
510
517
  ]);
511
518
  });
512
519
 
513
- it("drags multiple within in retained order (scrambled order)", () => {
520
+ it("drags multiple within in retained order (scrambled order)", async () => {
514
521
  suiteTree.do.selectMultiple("x111", "x114", "x112", "x113");
515
522
  suiteTree.do.startDrag("x111");
516
- suiteTree.do.dragOverAndDrop("x212", suiteTree.createBottomDragEvent());
523
+ await suiteTree.do.dragOverAndDrop(
524
+ "x212",
525
+ suiteTree.createBottomDragEvent(),
526
+ );
517
527
  expect(changeChildren).toHaveBeenCalledWith("x11", []);
518
528
  expect(changeChildren).toHaveBeenCalledWith("x21", [
519
529
  "x211",
@@ -540,10 +550,6 @@ describe("core-feature/drag-and-drop", () => {
540
550
  testTree.do.startDrag("x111");
541
551
  testTree.do.dragOverAndDrop("x212", testTree.createBottomDragEvent(2));
542
552
  testTree.expect.dropped(["x111"], {
543
- dragLineIndex: null,
544
- dragLineLevel: null,
545
- childIndex: null,
546
- insertionIndex: null,
547
553
  item: tree.item("x21"),
548
554
  });
549
555
  });
@@ -603,21 +609,9 @@ describe("core-feature/drag-and-drop", () => {
603
609
  tree.expect.dragOverNotAllowed("x2");
604
610
  expect(canDrop).toHaveBeenCalledWith([tree.item("x111")], {
605
611
  item: tree.item("x2"),
606
- childIndex: null,
607
- dragLineIndex: null,
608
- dragLineLevel: null,
609
- insertionIndex: null,
610
612
  });
611
613
  });
612
614
 
613
- it.todo("item with canDrag=false is not draggable", () => {
614
- const canDrag = tree.mockedHandler("canDrag").mockReturnValue(false);
615
- expect(tree.instance.getItemInstance("x111").getProps().draggable).toBe(
616
- false,
617
- );
618
- expect(canDrag).toHaveBeenCalledWith([tree.item("x111")]);
619
- });
620
-
621
615
  it("item with canDrag=false does not invoke drag handler when dragged", () => {
622
616
  const canDrag = tree.mockedHandler("canDrag").mockReturnValue(false);
623
617
  const setDndState = tree.mockedHandler("setDndState");
@@ -637,10 +631,6 @@ describe("core-feature/drag-and-drop", () => {
637
631
  tree.do.startDrag("x111");
638
632
  tree.do.dragOverAndDrop("x21");
639
633
  tree.expect.dropped(["x111", "x112", "x113"], {
640
- dragLineIndex: null,
641
- dragLineLevel: null,
642
- childIndex: null,
643
- insertionIndex: null,
644
634
  item: tree.item("x21"),
645
635
  });
646
636
  });
@@ -652,30 +642,26 @@ describe("core-feature/drag-and-drop", () => {
652
642
  tree.do.startDrag("x114");
653
643
  tree.do.dragOverAndDrop("x21");
654
644
  tree.expect.dropped(["x114"], {
655
- dragLineIndex: null,
656
- dragLineLevel: null,
657
- childIndex: null,
658
- insertionIndex: null,
659
645
  item: tree.item("x21"),
660
646
  });
661
647
  });
662
648
  });
663
649
 
664
650
  describe("item instance methods", () => {
665
- it("returns isDropTarget() correct for folders", () => {
651
+ it("returns isDragTarget() correct for folders", () => {
666
652
  tree.do.startDrag("x111");
667
653
  tree.do.dragOver("x21");
668
- expect(tree.instance.getItemInstance("x21").isDropTarget()).toBe(true);
669
- expect(tree.instance.getItemInstance("x211").isDropTarget()).toBe(
654
+ expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
655
+ expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
670
656
  false,
671
657
  );
672
658
  });
673
659
 
674
- it("returns isDropTarget() correct for items", () => {
660
+ it("returns isDragTarget() correct for items", () => {
675
661
  tree.do.startDrag("x111");
676
662
  tree.do.dragOver("x211");
677
- expect(tree.instance.getItemInstance("x21").isDropTarget()).toBe(true);
678
- expect(tree.instance.getItemInstance("x211").isDropTarget()).toBe(
663
+ expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
664
+ expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
679
665
  false,
680
666
  );
681
667
  });