@headless-tree/core 0.0.5 → 0.0.7

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 (93) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/cjs/core/create-tree.js +34 -12
  3. package/lib/cjs/features/async-data-loader/feature.js +30 -22
  4. package/lib/cjs/features/drag-and-drop/feature.js +58 -18
  5. package/lib/cjs/features/drag-and-drop/types.d.ts +21 -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 -10
  9. package/lib/cjs/features/expand-all/types.d.ts +2 -2
  10. package/lib/cjs/features/hotkeys-core/feature.js +0 -1
  11. package/lib/cjs/features/main/types.d.ts +3 -1
  12. package/lib/cjs/features/renaming/feature.js +10 -11
  13. package/lib/cjs/features/search/feature.js +21 -8
  14. package/lib/cjs/features/search/types.d.ts +1 -1
  15. package/lib/cjs/features/selection/feature.js +6 -5
  16. package/lib/cjs/features/sync-data-loader/feature.js +6 -1
  17. package/lib/cjs/features/sync-data-loader/types.d.ts +1 -1
  18. package/lib/cjs/features/tree/feature.js +23 -24
  19. package/lib/cjs/features/tree/types.d.ts +2 -2
  20. package/lib/cjs/index.d.ts +3 -1
  21. package/lib/cjs/index.js +3 -1
  22. package/lib/cjs/types/core.d.ts +3 -4
  23. package/lib/cjs/utilities/create-on-drop-handler.d.ts +3 -0
  24. package/lib/cjs/utilities/create-on-drop-handler.js +11 -0
  25. package/lib/cjs/utilities/insert-items-at-target.d.ts +3 -0
  26. package/lib/cjs/utilities/insert-items-at-target.js +24 -0
  27. package/lib/cjs/utilities/remove-items-from-parents.d.ts +2 -0
  28. package/lib/cjs/utilities/remove-items-from-parents.js +17 -0
  29. package/lib/cjs/utils.d.ts +1 -4
  30. package/lib/cjs/utils.js +1 -53
  31. package/lib/esm/core/create-tree.js +34 -12
  32. package/lib/esm/features/async-data-loader/feature.js +30 -22
  33. package/lib/esm/features/drag-and-drop/feature.js +58 -18
  34. package/lib/esm/features/drag-and-drop/types.d.ts +21 -1
  35. package/lib/esm/features/drag-and-drop/utils.d.ts +1 -1
  36. package/lib/esm/features/drag-and-drop/utils.js +35 -18
  37. package/lib/esm/features/expand-all/feature.js +12 -10
  38. package/lib/esm/features/expand-all/types.d.ts +2 -2
  39. package/lib/esm/features/hotkeys-core/feature.js +0 -1
  40. package/lib/esm/features/main/types.d.ts +3 -1
  41. package/lib/esm/features/renaming/feature.js +10 -11
  42. package/lib/esm/features/search/feature.js +21 -8
  43. package/lib/esm/features/search/types.d.ts +1 -1
  44. package/lib/esm/features/selection/feature.js +6 -5
  45. package/lib/esm/features/sync-data-loader/feature.js +6 -1
  46. package/lib/esm/features/sync-data-loader/types.d.ts +1 -1
  47. package/lib/esm/features/tree/feature.js +23 -24
  48. package/lib/esm/features/tree/types.d.ts +2 -2
  49. package/lib/esm/index.d.ts +3 -1
  50. package/lib/esm/index.js +3 -1
  51. package/lib/esm/types/core.d.ts +3 -4
  52. package/lib/esm/utilities/create-on-drop-handler.d.ts +3 -0
  53. package/lib/esm/utilities/create-on-drop-handler.js +7 -0
  54. package/lib/esm/utilities/insert-items-at-target.d.ts +3 -0
  55. package/lib/esm/utilities/insert-items-at-target.js +20 -0
  56. package/lib/esm/utilities/remove-items-from-parents.d.ts +2 -0
  57. package/lib/esm/utilities/remove-items-from-parents.js +13 -0
  58. package/lib/esm/utils.d.ts +1 -4
  59. package/lib/esm/utils.js +0 -50
  60. package/package.json +1 -1
  61. package/src/core/create-tree.ts +42 -9
  62. package/src/features/async-data-loader/feature.ts +15 -6
  63. package/src/features/drag-and-drop/feature.ts +75 -14
  64. package/src/features/drag-and-drop/types.ts +30 -5
  65. package/src/features/drag-and-drop/utils.ts +53 -24
  66. package/src/features/expand-all/feature.ts +10 -9
  67. package/src/features/expand-all/types.ts +2 -2
  68. package/src/features/hotkeys-core/feature.ts +0 -1
  69. package/src/features/main/types.ts +6 -0
  70. package/src/features/renaming/feature.ts +10 -7
  71. package/src/features/search/feature.ts +22 -6
  72. package/src/features/search/types.ts +1 -0
  73. package/src/features/selection/feature.ts +7 -3
  74. package/src/features/sync-data-loader/feature.ts +17 -3
  75. package/src/features/sync-data-loader/types.ts +1 -1
  76. package/src/features/tree/feature.ts +23 -22
  77. package/src/features/tree/types.ts +4 -2
  78. package/src/index.ts +4 -1
  79. package/src/types/core.ts +6 -5
  80. package/src/utilities/create-on-drop-handler.ts +14 -0
  81. package/src/utilities/insert-items-at-target.ts +30 -0
  82. package/src/utilities/remove-items-from-parents.ts +21 -0
  83. package/src/utils.ts +1 -69
  84. package/lib/cjs/data-adapters/nested-data-adapter.d.ts +0 -9
  85. package/lib/cjs/data-adapters/nested-data-adapter.js +0 -32
  86. package/lib/cjs/data-adapters/types.d.ts +0 -7
  87. package/lib/cjs/data-adapters/types.js +0 -2
  88. package/lib/esm/data-adapters/nested-data-adapter.d.ts +0 -9
  89. package/lib/esm/data-adapters/nested-data-adapter.js +0 -28
  90. package/lib/esm/data-adapters/types.d.ts +0 -7
  91. package/lib/esm/data-adapters/types.js +0 -1
  92. package/src/data-adapters/nested-data-adapter.ts +0 -48
  93. package/src/data-adapters/types.ts +0 -9
package/src/types/core.ts CHANGED
@@ -128,7 +128,12 @@ export type FeatureImplementation<
128
128
  F extends FeatureDef = EmptyFeatureDef
129
129
  > = {
130
130
  key?: string;
131
- dependingFeatures?: string[];
131
+ deps?: string[];
132
+ overwrites?: string[];
133
+
134
+ stateHandlerNames?: Partial<
135
+ Record<keyof MergedFeatures<F>["state"], keyof MergedFeatures<F>["config"]>
136
+ >;
132
137
 
133
138
  getInitialState?: (
134
139
  initialState: Partial<MergedFeatures<F>["state"]>,
@@ -174,9 +179,5 @@ export type FeatureImplementation<
174
179
  tree: MergedFeatures<F>["treeInstance"]
175
180
  ) => void;
176
181
 
177
- setState?: (instance: MergedFeatures<F>["treeInstance"]) => void;
178
- onConfigChange?: (instance: MergedFeatures<F>["treeInstance"]) => void;
179
- onStateOrConfigChange?: (instance: MergedFeatures<F>["treeInstance"]) => void;
180
-
181
182
  hotkeys?: HotkeysConfig<T, D>;
182
183
  };
@@ -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
- };