@headless-tree/core 0.0.5 → 0.0.6

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 (90) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/cjs/core/create-tree.js +7 -6
  3. package/lib/cjs/features/async-data-loader/feature.js +30 -21
  4. package/lib/cjs/features/drag-and-drop/feature.js +29 -17
  5. package/lib/cjs/features/drag-and-drop/types.d.ts +14 -1
  6. package/lib/cjs/features/drag-and-drop/utils.d.ts +1 -1
  7. package/lib/cjs/features/drag-and-drop/utils.js +34 -17
  8. package/lib/cjs/features/expand-all/feature.js +12 -9
  9. package/lib/cjs/features/expand-all/types.d.ts +2 -2
  10. package/lib/cjs/features/main/types.d.ts +3 -1
  11. package/lib/cjs/features/renaming/feature.js +10 -9
  12. package/lib/cjs/features/search/feature.js +21 -7
  13. package/lib/cjs/features/search/types.d.ts +1 -1
  14. package/lib/cjs/features/selection/feature.js +5 -3
  15. package/lib/cjs/features/sync-data-loader/feature.js +6 -0
  16. package/lib/cjs/features/sync-data-loader/types.d.ts +1 -1
  17. package/lib/cjs/features/tree/feature.js +23 -23
  18. package/lib/cjs/features/tree/types.d.ts +2 -2
  19. package/lib/cjs/index.d.ts +3 -1
  20. package/lib/cjs/index.js +3 -1
  21. package/lib/cjs/types/core.d.ts +1 -3
  22. package/lib/cjs/utilities/create-on-drop-handler.d.ts +3 -0
  23. package/lib/cjs/utilities/create-on-drop-handler.js +11 -0
  24. package/lib/cjs/utilities/insert-items-at-target.d.ts +3 -0
  25. package/lib/cjs/utilities/insert-items-at-target.js +24 -0
  26. package/lib/cjs/utilities/remove-items-from-parents.d.ts +2 -0
  27. package/lib/cjs/utilities/remove-items-from-parents.js +17 -0
  28. package/lib/cjs/utils.d.ts +1 -4
  29. package/lib/cjs/utils.js +1 -53
  30. package/lib/esm/core/create-tree.js +7 -6
  31. package/lib/esm/features/async-data-loader/feature.js +30 -21
  32. package/lib/esm/features/drag-and-drop/feature.js +29 -17
  33. package/lib/esm/features/drag-and-drop/types.d.ts +14 -1
  34. package/lib/esm/features/drag-and-drop/utils.d.ts +1 -1
  35. package/lib/esm/features/drag-and-drop/utils.js +35 -18
  36. package/lib/esm/features/expand-all/feature.js +12 -9
  37. package/lib/esm/features/expand-all/types.d.ts +2 -2
  38. package/lib/esm/features/main/types.d.ts +3 -1
  39. package/lib/esm/features/renaming/feature.js +10 -9
  40. package/lib/esm/features/search/feature.js +21 -7
  41. package/lib/esm/features/search/types.d.ts +1 -1
  42. package/lib/esm/features/selection/feature.js +5 -3
  43. package/lib/esm/features/sync-data-loader/feature.js +6 -0
  44. package/lib/esm/features/sync-data-loader/types.d.ts +1 -1
  45. package/lib/esm/features/tree/feature.js +23 -23
  46. package/lib/esm/features/tree/types.d.ts +2 -2
  47. package/lib/esm/index.d.ts +3 -1
  48. package/lib/esm/index.js +3 -1
  49. package/lib/esm/types/core.d.ts +1 -3
  50. package/lib/esm/utilities/create-on-drop-handler.d.ts +3 -0
  51. package/lib/esm/utilities/create-on-drop-handler.js +7 -0
  52. package/lib/esm/utilities/insert-items-at-target.d.ts +3 -0
  53. package/lib/esm/utilities/insert-items-at-target.js +20 -0
  54. package/lib/esm/utilities/remove-items-from-parents.d.ts +2 -0
  55. package/lib/esm/utilities/remove-items-from-parents.js +13 -0
  56. package/lib/esm/utils.d.ts +1 -4
  57. package/lib/esm/utils.js +0 -50
  58. package/package.json +1 -1
  59. package/src/core/create-tree.ts +11 -7
  60. package/src/features/async-data-loader/feature.ts +15 -5
  61. package/src/features/drag-and-drop/feature.ts +34 -12
  62. package/src/features/drag-and-drop/types.ts +23 -6
  63. package/src/features/drag-and-drop/utils.ts +53 -24
  64. package/src/features/expand-all/feature.ts +10 -8
  65. package/src/features/expand-all/types.ts +2 -2
  66. package/src/features/main/types.ts +6 -0
  67. package/src/features/renaming/feature.ts +10 -5
  68. package/src/features/search/feature.ts +22 -5
  69. package/src/features/search/types.ts +1 -0
  70. package/src/features/selection/feature.ts +6 -1
  71. package/src/features/sync-data-loader/feature.ts +17 -2
  72. package/src/features/sync-data-loader/types.ts +1 -1
  73. package/src/features/tree/feature.ts +23 -21
  74. package/src/features/tree/types.ts +4 -2
  75. package/src/index.ts +4 -1
  76. package/src/types/core.ts +4 -4
  77. package/src/utilities/create-on-drop-handler.ts +14 -0
  78. package/src/utilities/insert-items-at-target.ts +30 -0
  79. package/src/utilities/remove-items-from-parents.ts +21 -0
  80. package/src/utils.ts +1 -69
  81. package/lib/cjs/data-adapters/nested-data-adapter.d.ts +0 -9
  82. package/lib/cjs/data-adapters/nested-data-adapter.js +0 -32
  83. package/lib/cjs/data-adapters/types.d.ts +0 -7
  84. package/lib/cjs/data-adapters/types.js +0 -2
  85. package/lib/esm/data-adapters/nested-data-adapter.d.ts +0 -9
  86. package/lib/esm/data-adapters/nested-data-adapter.js +0 -28
  87. package/lib/esm/data-adapters/types.d.ts +0 -7
  88. package/lib/esm/data-adapters/types.js +0 -1
  89. package/src/data-adapters/nested-data-adapter.ts +0 -48
  90. package/src/data-adapters/types.ts +0 -9
@@ -28,6 +28,11 @@ export const treeFeature: FeatureImplementation<
28
28
  ...defaultConfig,
29
29
  }),
30
30
 
31
+ stateHandlerNames: {
32
+ expandedItems: "setExpandedItems",
33
+ focusedItem: "setFocusedItem",
34
+ },
35
+
31
36
  createTreeInstance: (prev, instance) => ({
32
37
  ...prev,
33
38
 
@@ -45,7 +50,6 @@ export const treeFeature: FeatureImplementation<
45
50
  getItemsMeta: () => {
46
51
  const { rootItemId } = instance.getConfig();
47
52
  const { expandedItems } = instance.getState();
48
- // console.log("!", instance.getConfig());
49
53
  const flatItems: ItemMeta[] = [];
50
54
 
51
55
  const recursiveAdd = (
@@ -91,9 +95,10 @@ export const treeFeature: FeatureImplementation<
91
95
  return;
92
96
  }
93
97
 
94
- instance
95
- .getConfig()
96
- .setExpandedItems?.((expandedItems) => [...expandedItems, itemId]);
98
+ instance.applySubStateUpdate("expandedItems", (expandedItems) => [
99
+ ...expandedItems,
100
+ itemId,
101
+ ]);
97
102
  instance.rebuildTree();
98
103
  },
99
104
 
@@ -102,11 +107,9 @@ export const treeFeature: FeatureImplementation<
102
107
  return;
103
108
  }
104
109
 
105
- instance
106
- .getConfig()
107
- .setExpandedItems?.((expandedItems) =>
108
- expandedItems.filter((id) => id !== itemId)
109
- );
110
+ instance.applySubStateUpdate("expandedItems", (expandedItems) =>
111
+ expandedItems.filter((id) => id !== itemId)
112
+ );
110
113
  instance.rebuildTree();
111
114
  },
112
115
 
@@ -119,7 +122,7 @@ export const treeFeature: FeatureImplementation<
119
122
  },
120
123
 
121
124
  focusItem: (itemId) => {
122
- instance.getConfig().setFocusedItem?.(itemId);
125
+ instance.applySubStateUpdate("focusedItem", itemId);
123
126
  },
124
127
 
125
128
  focusNextItem: () => {
@@ -134,7 +137,7 @@ export const treeFeature: FeatureImplementation<
134
137
  instance.focusItem(instance.getItems()[nextIndex].getId());
135
138
  },
136
139
 
137
- updateDomFocus: (scrollIntoView) => {
140
+ updateDomFocus: () => {
138
141
  // Required because if the state is managed outside in react, the state only updated during next render
139
142
  setTimeout(async () => {
140
143
  const focusedItem = instance.getFocusedItem();
@@ -143,9 +146,6 @@ export const treeFeature: FeatureImplementation<
143
146
  const focusedElement = focusedItem.getElement();
144
147
  if (!focusedElement) return;
145
148
  focusedElement.focus();
146
- // if (scrollIntoView) {
147
- // focusedElement.scrollIntoView();
148
- // }
149
149
  });
150
150
  },
151
151
 
@@ -162,6 +162,11 @@ export const treeFeature: FeatureImplementation<
162
162
  isLoading: () => {
163
163
  throw new Error("No data-loader registered");
164
164
  },
165
+ scrollTo: async (scrollIntoViewArg) => {
166
+ tree.getConfig().scrollToItem?.(item as any);
167
+ await poll(() => item.getElement() !== null, 20);
168
+ item.getElement()!.scrollIntoView(scrollIntoViewArg);
169
+ },
165
170
  getId: () => item.getItemMeta().itemId,
166
171
  getProps: () => {
167
172
  const itemMeta = item.getItemMeta();
@@ -170,12 +175,11 @@ export const treeFeature: FeatureImplementation<
170
175
  role: "treeitem",
171
176
  "aria-setsize": itemMeta.setSize,
172
177
  "aria-posinset": itemMeta.posInSet,
173
- "aria-selected": false,
178
+ "aria-selected": "false",
174
179
  "aria-label": item.getItemName(),
175
180
  "aria-level": itemMeta.level,
176
181
  tabIndex: item.isFocused() ? 0 : -1,
177
182
  onClick: item.getMemoizedProp("tree/onClick", () => (e) => {
178
- console.log("onClick", item.getId());
179
183
  item.setFocused();
180
184
  item.primaryAction();
181
185
 
@@ -225,10 +229,8 @@ export const treeFeature: FeatureImplementation<
225
229
  },
226
230
  () => [item.getItemMeta()]
227
231
  ),
228
- getIndexInParent: () =>
229
- item.getItemMeta().index -
230
- (item.getParent()?.getItemMeta().index ?? 0) -
231
- 1,
232
+ // TODO remove
233
+ getIndexInParent: () => item.getItemMeta().posInSet,
232
234
  getChildren: () =>
233
235
  tree
234
236
  .retrieveChildrenIds(item.getItemMeta().itemId)
@@ -301,7 +303,7 @@ export const treeFeature: FeatureImplementation<
301
303
  item.getItemMeta().level !== 0
302
304
  ) {
303
305
  item.getParent()?.setFocused();
304
- tree.updateDomFocus(true);
306
+ tree.updateDomFocus();
305
307
  } else {
306
308
  item.collapse();
307
309
  }
@@ -41,8 +41,7 @@ export type TreeFeatureDef<T> = {
41
41
  getFocusedItem: () => ItemInstance<any>;
42
42
  focusNextItem: () => void;
43
43
  focusPreviousItem: () => void;
44
- scrollToItem: (item: ItemInstance<any>) => void;
45
- updateDomFocus: (scrollIntoView?: boolean) => void;
44
+ updateDomFocus: () => void;
46
45
 
47
46
  getContainerProps: () => Record<string, any>;
48
47
  };
@@ -65,6 +64,9 @@ export type TreeFeatureDef<T> = {
65
64
  getItemAbove: () => ItemInstance<T> | null;
66
65
  getItemBelow: () => ItemInstance<T> | null;
67
66
  getMemoizedProp: <X>(name: string, create: () => X, deps?: any[]) => X;
67
+ scrollTo: (
68
+ scrollIntoViewArg?: boolean | ScrollIntoViewOptions
69
+ ) => Promise<void>;
68
70
  };
69
71
  hotkeys:
70
72
  | "focusNextItem"
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./types/core";
2
2
  export * from "./core/create-tree";
3
+
3
4
  export * from "./features/tree/types";
4
5
  export * from "./features/main/types";
5
6
  export * from "./features/drag-and-drop/types";
@@ -20,4 +21,6 @@ export * from "./features/search/feature";
20
21
  export * from "./features/renaming/feature";
21
22
  export * from "./features/expand-all/feature";
22
23
 
23
- export * from "./data-adapters/nested-data-adapter";
24
+ export * from "./utilities/create-on-drop-handler";
25
+ export * from "./utilities/insert-items-at-target";
26
+ export * from "./utilities/remove-items-from-parents";
package/src/types/core.ts CHANGED
@@ -130,6 +130,10 @@ export type FeatureImplementation<
130
130
  key?: string;
131
131
  dependingFeatures?: string[];
132
132
 
133
+ stateHandlerNames?: Partial<
134
+ Record<keyof MergedFeatures<F>["state"], keyof MergedFeatures<F>["config"]>
135
+ >;
136
+
133
137
  getInitialState?: (
134
138
  initialState: Partial<MergedFeatures<F>["state"]>,
135
139
  tree: MergedFeatures<F>["treeInstance"]
@@ -174,9 +178,5 @@ export type FeatureImplementation<
174
178
  tree: MergedFeatures<F>["treeInstance"]
175
179
  ) => void;
176
180
 
177
- setState?: (instance: MergedFeatures<F>["treeInstance"]) => void;
178
- onConfigChange?: (instance: MergedFeatures<F>["treeInstance"]) => void;
179
- onStateOrConfigChange?: (instance: MergedFeatures<F>["treeInstance"]) => void;
180
-
181
181
  hotkeys?: HotkeysConfig<T, D>;
182
182
  };
@@ -0,0 +1,14 @@
1
+ import { ItemInstance } from "../types/core";
2
+ import { DropTarget } from "../features/drag-and-drop/types";
3
+ import { removeItemsFromParents } from "./remove-items-from-parents";
4
+ import { insertItemsAtTarget } from "./insert-items-at-target";
5
+
6
+ export const createOnDropHandler =
7
+ <T>(
8
+ onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void
9
+ ) =>
10
+ (items: ItemInstance<T>[], target: DropTarget<T>) => {
11
+ const itemIds = items.map((item) => item.getId());
12
+ removeItemsFromParents(items, onChangeChildren);
13
+ insertItemsAtTarget(itemIds, target, onChangeChildren);
14
+ };
@@ -0,0 +1,30 @@
1
+ import { ItemInstance } from "../types/core";
2
+ import { DropTarget } from "../features/drag-and-drop/types";
3
+
4
+ export const insertItemsAtTarget = <T>(
5
+ itemIds: string[],
6
+ target: DropTarget<T>,
7
+ onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void
8
+ ) => {
9
+ // add moved items to new common parent, if dropped onto parent
10
+ if (target.childIndex === null) {
11
+ onChangeChildren(target.item, [
12
+ ...target.item.getChildren().map((item) => item.getId()),
13
+ ...itemIds,
14
+ ]);
15
+ // TODO items[0].getTree().rebuildTree();
16
+ return;
17
+ }
18
+
19
+ // add moved items to new common parent, if dropped between siblings
20
+ const oldChildren = target.item.getChildren();
21
+ const newChildren = [
22
+ ...oldChildren.slice(0, target.insertionIndex).map((item) => item.getId()),
23
+ ...itemIds,
24
+ ...oldChildren.slice(target.insertionIndex).map((item) => item.getId()),
25
+ ];
26
+
27
+ onChangeChildren(target.item, newChildren);
28
+
29
+ target.item.getTree().rebuildTree();
30
+ };
@@ -0,0 +1,21 @@
1
+ import { ItemInstance } from "../types/core";
2
+
3
+ export const removeItemsFromParents = <T>(
4
+ movedItems: ItemInstance<T>[],
5
+ onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => void
6
+ ) => {
7
+ // TODO bulk sibling changes together
8
+ for (const item of movedItems) {
9
+ const siblings = item.getParent()?.getChildren();
10
+ if (siblings) {
11
+ onChangeChildren(
12
+ item.getParent(),
13
+ siblings
14
+ .filter((sibling) => sibling.getId() !== item.getId())
15
+ .map((i) => i.getId())
16
+ );
17
+ }
18
+ }
19
+
20
+ movedItems[0].getTree().rebuildTree();
21
+ };
package/src/utils.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { ItemInstance, TreeState, Updater } from "./types/core";
2
- import { DropTarget } from "./features/drag-and-drop/types";
1
+ import { TreeState, Updater } from "./types/core";
3
2
 
4
3
  export type NoInfer<T> = [T][T extends any ? 0 : never];
5
4
 
@@ -53,73 +52,6 @@ export function makeStateUpdater<K extends keyof TreeState<any>>(
53
52
  };
54
53
  }
55
54
 
56
- export const scrollIntoView = (element: Element | undefined | null) => {
57
- if (!element) {
58
- return;
59
- }
60
-
61
- if ((element as any).scrollIntoViewIfNeeded) {
62
- (element as any).scrollIntoViewIfNeeded();
63
- } else {
64
- const boundingBox = element.getBoundingClientRect();
65
- const isElementInViewport =
66
- boundingBox.top >= 0 &&
67
- boundingBox.left >= 0 &&
68
- boundingBox.bottom <=
69
- (window.innerHeight || document.documentElement.clientHeight) &&
70
- boundingBox.right <=
71
- (window.innerWidth || document.documentElement.clientWidth);
72
- if (!isElementInViewport) {
73
- element.scrollIntoView();
74
- }
75
- }
76
- };
77
-
78
- export const performItemsMove = <T>(
79
- items: ItemInstance<T>[],
80
- target: DropTarget<T>,
81
- onChangeChildren: (
82
- item: ItemInstance<T>,
83
- newChildren: ItemInstance<T>[]
84
- ) => void
85
- ) => {
86
- const numberOfDragItemsBeforeTarget = !target.childIndex
87
- ? 0
88
- : target.item
89
- .getChildren()
90
- .slice(0, target.childIndex)
91
- .filter((child) => items.some((item) => item.getId() === child.getId()))
92
- .length;
93
-
94
- // TODO bulk sibling changes together
95
- for (const item of items) {
96
- const siblings = item.getParent()?.getChildren();
97
- if (siblings) {
98
- onChangeChildren(
99
- item.getParent(),
100
- siblings.filter((sibling) => sibling.getId() !== item.getId())
101
- );
102
- }
103
- }
104
-
105
- if (target.childIndex === null) {
106
- onChangeChildren(target.item, [...target.item.getChildren(), ...items]);
107
- items[0].getTree().rebuildTree();
108
- return;
109
- }
110
-
111
- const oldChildren = target.item.getChildren();
112
- const newChildren = [
113
- ...oldChildren.slice(0, target.childIndex - numberOfDragItemsBeforeTarget),
114
- ...items,
115
- ...oldChildren.slice(target.childIndex - numberOfDragItemsBeforeTarget),
116
- ];
117
-
118
- onChangeChildren(target.item, newChildren);
119
-
120
- items[0].getTree().rebuildTree();
121
- };
122
-
123
55
  export const poll = (fn: () => boolean, interval = 100, timeout = 1000) =>
124
56
  new Promise<void>((resolve) => {
125
57
  let clear: ReturnType<typeof setTimeout>;
@@ -1,9 +0,0 @@
1
- import { DataAdapterConfig } from "./types";
2
- interface NestedDataAdapterProps<T> {
3
- rootItem: T;
4
- getItemId: (item: T) => string;
5
- getChildren: (item: T) => T[] | undefined;
6
- changeChildren?: (item: T, children: T[]) => void;
7
- }
8
- export declare const nestedDataAdapter: <T = any>(props: NestedDataAdapterProps<T>) => DataAdapterConfig<T>;
9
- export {};
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.nestedDataAdapter = void 0;
4
- const utils_1 = require("../utils");
5
- const createItemMap = (props, item, map = {}) => {
6
- var _a;
7
- map[props.getItemId(item)] = item;
8
- (_a = props.getChildren(item)) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
9
- createItemMap(props, child, map);
10
- });
11
- return map;
12
- };
13
- const nestedDataAdapter = (props) => {
14
- const itemMap = createItemMap(props, props.rootItem);
15
- return {
16
- rootItemId: props.getItemId(props.rootItem),
17
- dataLoader: {
18
- getItem: (itemId) => itemMap[itemId],
19
- getChildren: (itemId) => { var _a, _b; return (_b = (_a = props.getChildren(itemMap[itemId])) === null || _a === void 0 ? void 0 : _a.map(props.getItemId)) !== null && _b !== void 0 ? _b : []; },
20
- },
21
- onDrop: (items, target) => {
22
- if (!props.changeChildren) {
23
- return;
24
- }
25
- (0, utils_1.performItemsMove)(items, target, (item, newChildren) => {
26
- var _a;
27
- (_a = props.changeChildren) === null || _a === void 0 ? void 0 : _a.call(props, item.getItemData(), newChildren.map((child) => child.getItemData()));
28
- });
29
- },
30
- };
31
- };
32
- exports.nestedDataAdapter = nestedDataAdapter;
@@ -1,7 +0,0 @@
1
- import { DragAndDropFeatureDef } from "../features/drag-and-drop/types";
2
- import { SyncDataLoaderFeatureDef } from "../features/sync-data-loader/types";
3
- export type DataAdapterConfig<T> = {
4
- rootItemId: SyncDataLoaderFeatureDef<T>["config"]["rootItemId"];
5
- dataLoader: SyncDataLoaderFeatureDef<T>["config"]["dataLoader"];
6
- onDrop: DragAndDropFeatureDef<T>["config"]["onDrop"];
7
- };
@@ -1,2 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,9 +0,0 @@
1
- import { DataAdapterConfig } from "./types";
2
- interface NestedDataAdapterProps<T> {
3
- rootItem: T;
4
- getItemId: (item: T) => string;
5
- getChildren: (item: T) => T[] | undefined;
6
- changeChildren?: (item: T, children: T[]) => void;
7
- }
8
- export declare const nestedDataAdapter: <T = any>(props: NestedDataAdapterProps<T>) => DataAdapterConfig<T>;
9
- export {};
@@ -1,28 +0,0 @@
1
- import { performItemsMove } from "../utils";
2
- const createItemMap = (props, item, map = {}) => {
3
- var _a;
4
- map[props.getItemId(item)] = item;
5
- (_a = props.getChildren(item)) === null || _a === void 0 ? void 0 : _a.forEach((child) => {
6
- createItemMap(props, child, map);
7
- });
8
- return map;
9
- };
10
- export const nestedDataAdapter = (props) => {
11
- const itemMap = createItemMap(props, props.rootItem);
12
- return {
13
- rootItemId: props.getItemId(props.rootItem),
14
- dataLoader: {
15
- getItem: (itemId) => itemMap[itemId],
16
- getChildren: (itemId) => { var _a, _b; return (_b = (_a = props.getChildren(itemMap[itemId])) === null || _a === void 0 ? void 0 : _a.map(props.getItemId)) !== null && _b !== void 0 ? _b : []; },
17
- },
18
- onDrop: (items, target) => {
19
- if (!props.changeChildren) {
20
- return;
21
- }
22
- performItemsMove(items, target, (item, newChildren) => {
23
- var _a;
24
- (_a = props.changeChildren) === null || _a === void 0 ? void 0 : _a.call(props, item.getItemData(), newChildren.map((child) => child.getItemData()));
25
- });
26
- },
27
- };
28
- };
@@ -1,7 +0,0 @@
1
- import { DragAndDropFeatureDef } from "../features/drag-and-drop/types";
2
- import { SyncDataLoaderFeatureDef } from "../features/sync-data-loader/types";
3
- export type DataAdapterConfig<T> = {
4
- rootItemId: SyncDataLoaderFeatureDef<T>["config"]["rootItemId"];
5
- dataLoader: SyncDataLoaderFeatureDef<T>["config"]["dataLoader"];
6
- onDrop: DragAndDropFeatureDef<T>["config"]["onDrop"];
7
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,48 +0,0 @@
1
- import { DataAdapterConfig } from "./types";
2
- import { ItemInstance } from "../types/core";
3
- import { DropTarget } from "../features/drag-and-drop/types";
4
- import { performItemsMove } from "../utils";
5
-
6
- interface NestedDataAdapterProps<T> {
7
- rootItem: T;
8
- getItemId: (item: T) => string;
9
- getChildren: (item: T) => T[] | undefined;
10
- changeChildren?: (item: T, children: T[]) => void;
11
- }
12
-
13
- const createItemMap = <T>(
14
- props: NestedDataAdapterProps<T>,
15
- item: T,
16
- map: Record<string, T> = {}
17
- ) => {
18
- map[props.getItemId(item)] = item;
19
- props.getChildren(item)?.forEach((child) => {
20
- createItemMap(props, child, map);
21
- });
22
- return map;
23
- };
24
-
25
- export const nestedDataAdapter = <T = any>(
26
- props: NestedDataAdapterProps<T>
27
- ): DataAdapterConfig<T> => {
28
- const itemMap = createItemMap(props, props.rootItem);
29
- return {
30
- rootItemId: props.getItemId(props.rootItem),
31
- dataLoader: {
32
- getItem: (itemId) => itemMap[itemId],
33
- getChildren: (itemId) =>
34
- props.getChildren(itemMap[itemId])?.map(props.getItemId) ?? [],
35
- },
36
- onDrop: (items: ItemInstance<T>[], target: DropTarget<T>) => {
37
- if (!props.changeChildren) {
38
- return;
39
- }
40
- performItemsMove(items, target, (item, newChildren) => {
41
- props.changeChildren?.(
42
- item.getItemData(),
43
- newChildren.map((child) => child.getItemData())
44
- );
45
- });
46
- },
47
- };
48
- };
@@ -1,9 +0,0 @@
1
- import { DragAndDropFeatureDef } from "../features/drag-and-drop/types";
2
- import { SyncDataLoaderFeatureDef } from "../features/sync-data-loader/types";
3
-
4
- export type DataAdapterConfig<T> = {
5
- rootItemId: SyncDataLoaderFeatureDef<T>["config"]["rootItemId"];
6
- dataLoader: SyncDataLoaderFeatureDef<T>["config"]["dataLoader"];
7
- onDrop: DragAndDropFeatureDef<T>["config"]["onDrop"];
8
- // TODO onDropForeignDragObject: DragAndDropFeatureDef<T>["config"]["onDropForeignDragObject"];
9
- };