@headless-tree/core 0.0.1

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 (87) hide show
  1. package/lib/core/create-tree.d.ts +2 -0
  2. package/lib/core/create-tree.js +116 -0
  3. package/lib/data-adapters/nested-data-adapter.d.ts +9 -0
  4. package/lib/data-adapters/nested-data-adapter.js +32 -0
  5. package/lib/data-adapters/types.d.ts +7 -0
  6. package/lib/data-adapters/types.js +2 -0
  7. package/lib/features/async-data-loader/feature.d.ts +5 -0
  8. package/lib/features/async-data-loader/feature.js +80 -0
  9. package/lib/features/async-data-loader/types.d.ts +41 -0
  10. package/lib/features/async-data-loader/types.js +2 -0
  11. package/lib/features/drag-and-drop/feature.d.ts +3 -0
  12. package/lib/features/drag-and-drop/feature.js +144 -0
  13. package/lib/features/drag-and-drop/types.d.ts +49 -0
  14. package/lib/features/drag-and-drop/types.js +9 -0
  15. package/lib/features/drag-and-drop/utils.d.ts +7 -0
  16. package/lib/features/drag-and-drop/utils.js +121 -0
  17. package/lib/features/expand-all/feature.d.ts +6 -0
  18. package/lib/features/expand-all/feature.js +39 -0
  19. package/lib/features/expand-all/types.d.ts +17 -0
  20. package/lib/features/expand-all/types.js +2 -0
  21. package/lib/features/hotkeys-core/feature.d.ts +4 -0
  22. package/lib/features/hotkeys-core/feature.js +73 -0
  23. package/lib/features/hotkeys-core/types.d.ts +25 -0
  24. package/lib/features/hotkeys-core/types.js +2 -0
  25. package/lib/features/main/types.d.ts +36 -0
  26. package/lib/features/main/types.js +2 -0
  27. package/lib/features/renaming/feature.d.ts +5 -0
  28. package/lib/features/renaming/feature.js +65 -0
  29. package/lib/features/renaming/types.d.ts +27 -0
  30. package/lib/features/renaming/types.js +2 -0
  31. package/lib/features/search/feature.d.ts +5 -0
  32. package/lib/features/search/feature.js +90 -0
  33. package/lib/features/search/types.d.ts +33 -0
  34. package/lib/features/search/types.js +2 -0
  35. package/lib/features/selection/feature.d.ts +5 -0
  36. package/lib/features/selection/feature.js +112 -0
  37. package/lib/features/selection/types.d.ts +21 -0
  38. package/lib/features/selection/types.js +2 -0
  39. package/lib/features/sync-data-loader/feature.d.ts +4 -0
  40. package/lib/features/sync-data-loader/feature.js +9 -0
  41. package/lib/features/sync-data-loader/types.d.ts +19 -0
  42. package/lib/features/sync-data-loader/types.js +2 -0
  43. package/lib/features/tree/feature.d.ts +6 -0
  44. package/lib/features/tree/feature.js +216 -0
  45. package/lib/features/tree/types.d.ts +57 -0
  46. package/lib/features/tree/types.js +2 -0
  47. package/lib/index.d.ts +21 -0
  48. package/lib/index.js +37 -0
  49. package/lib/mddocs-entry.d.ts +21 -0
  50. package/lib/mddocs-entry.js +17 -0
  51. package/lib/types/core.d.ts +68 -0
  52. package/lib/types/core.js +2 -0
  53. package/lib/types/deep-merge.d.ts +13 -0
  54. package/lib/types/deep-merge.js +2 -0
  55. package/lib/utils.d.ts +9 -0
  56. package/lib/utils.js +105 -0
  57. package/package.json +15 -0
  58. package/src/core/create-tree.ts +195 -0
  59. package/src/data-adapters/nested-data-adapter.ts +48 -0
  60. package/src/data-adapters/types.ts +9 -0
  61. package/src/features/async-data-loader/feature.ts +117 -0
  62. package/src/features/async-data-loader/types.ts +41 -0
  63. package/src/features/drag-and-drop/feature.ts +153 -0
  64. package/src/features/drag-and-drop/types.ts +64 -0
  65. package/src/features/drag-and-drop/utils.ts +88 -0
  66. package/src/features/expand-all/feature.ts +62 -0
  67. package/src/features/expand-all/types.ts +13 -0
  68. package/src/features/hotkeys-core/feature.ts +111 -0
  69. package/src/features/hotkeys-core/types.ts +36 -0
  70. package/src/features/main/types.ts +41 -0
  71. package/src/features/renaming/feature.ts +102 -0
  72. package/src/features/renaming/types.ts +28 -0
  73. package/src/features/search/feature.ts +142 -0
  74. package/src/features/search/types.ts +39 -0
  75. package/src/features/selection/feature.ts +153 -0
  76. package/src/features/selection/types.ts +28 -0
  77. package/src/features/sync-data-loader/feature.ts +27 -0
  78. package/src/features/sync-data-loader/types.ts +20 -0
  79. package/src/features/tree/feature.ts +307 -0
  80. package/src/features/tree/types.ts +70 -0
  81. package/src/index.ts +23 -0
  82. package/src/mddocs-entry.ts +26 -0
  83. package/src/types/core.ts +182 -0
  84. package/src/types/deep-merge.ts +31 -0
  85. package/src/utils.ts +136 -0
  86. package/tsconfig.json +7 -0
  87. package/typedoc.json +4 -0
@@ -0,0 +1,2 @@
1
+ import { TreeConfig, TreeInstance } from "../types/core";
2
+ export declare const createTree: <T>(initialConfig: TreeConfig<T>) => TreeInstance<T>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createTree = void 0;
4
+ const feature_1 = require("../features/tree/feature");
5
+ const buildItemInstance = (features, tree, itemId) => {
6
+ var _a, _b;
7
+ const itemInstance = {};
8
+ for (const feature of features) {
9
+ Object.assign(itemInstance, (_b = (_a = feature.createItemInstance) === null || _a === void 0 ? void 0 : _a.call(feature, Object.assign({}, itemInstance), itemInstance, tree, itemId)) !== null && _b !== void 0 ? _b : {});
10
+ }
11
+ return itemInstance;
12
+ };
13
+ const createTree = (initialConfig) => {
14
+ var _a, _b, _c, _d, _e;
15
+ const treeInstance = {};
16
+ const additionalFeatures = [feature_1.treeFeature, ...((_a = initialConfig.features) !== null && _a !== void 0 ? _a : [])];
17
+ let state = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getInitialState) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, (_b = initialConfig.state) !== null && _b !== void 0 ? _b : {});
18
+ let config = additionalFeatures.reduce((acc, feature) => { var _a, _b; return (_b = (_a = feature.getDefaultConfig) === null || _a === void 0 ? void 0 : _a.call(feature, acc, treeInstance)) !== null && _b !== void 0 ? _b : acc; }, initialConfig);
19
+ let treeElement;
20
+ const treeDataRef = { current: {} };
21
+ const itemInstancesMap = {};
22
+ let itemInstances = [];
23
+ const itemElementsMap = {};
24
+ const itemDataRefs = {};
25
+ let itemMetaMap = {};
26
+ const hotkeyPresets = {};
27
+ const rebuildItemMeta = (main) => {
28
+ // TODO can we find a way to only run this for the changed substructure?
29
+ itemInstances = [];
30
+ itemMetaMap = {};
31
+ const rootInstance = buildItemInstance([main, ...additionalFeatures], treeInstance, config.rootItemId);
32
+ itemInstancesMap[config.rootItemId] = rootInstance;
33
+ itemMetaMap[config.rootItemId] = {
34
+ itemId: config.rootItemId,
35
+ index: -1,
36
+ parentId: null,
37
+ level: -1,
38
+ posInSet: 0,
39
+ setSize: 1,
40
+ };
41
+ for (const item of treeInstance.getItemsMeta()) {
42
+ itemMetaMap[item.itemId] = item;
43
+ if (!itemInstancesMap[item.itemId]) {
44
+ const instance = buildItemInstance([main, ...additionalFeatures], treeInstance, item.itemId);
45
+ itemInstancesMap[item.itemId] = instance;
46
+ itemInstances.push(instance);
47
+ }
48
+ else {
49
+ itemInstances.push(itemInstancesMap[item.itemId]);
50
+ }
51
+ }
52
+ console.log("REBUILT");
53
+ };
54
+ const eachFeature = (fn) => {
55
+ for (const feature of additionalFeatures) {
56
+ fn(feature);
57
+ }
58
+ };
59
+ const mainFeature = {
60
+ key: "main",
61
+ createTreeInstance: (prev) => (Object.assign(Object.assign({}, prev), { getState: () => state, setState: (updater) => {
62
+ var _a;
63
+ state = typeof updater === "function" ? updater(state) : updater;
64
+ (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
65
+ eachFeature((feature) => { var _a; return (_a = feature.setState) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance); });
66
+ eachFeature((feature) => { var _a; return (_a = feature.onStateOrConfigChange) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance); });
67
+ }, rebuildTree: () => {
68
+ var _a;
69
+ rebuildItemMeta(mainFeature);
70
+ (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
71
+ }, getConfig: () => config, setConfig: (updater) => {
72
+ config = typeof updater === "function" ? updater(config) : updater;
73
+ if (config.state) {
74
+ state = Object.assign(Object.assign({}, state), config.state);
75
+ eachFeature((feature) => { var _a; return (_a = feature.setState) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance); });
76
+ }
77
+ eachFeature((feature) => { var _a; return (_a = feature.onConfigChange) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance); });
78
+ eachFeature((feature) => { var _a; return (_a = feature.onStateOrConfigChange) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance); });
79
+ }, getItemInstance: (itemId) => itemInstancesMap[itemId], getItems: () => itemInstances, registerElement: (element) => {
80
+ if (treeElement === element) {
81
+ return;
82
+ }
83
+ if (treeElement && !element) {
84
+ eachFeature((feature) => { var _a; return (_a = feature.onTreeUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, treeElement); });
85
+ }
86
+ else if (!treeElement && element) {
87
+ eachFeature((feature) => { var _a; return (_a = feature.onTreeMount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, element); });
88
+ }
89
+ treeElement = element;
90
+ }, getElement: () => treeElement, getDataRef: () => treeDataRef, getHotkeyPresets: () => hotkeyPresets })),
91
+ createItemInstance: (prev, instance, _, itemId) => (Object.assign(Object.assign({}, prev), { registerElement: (element) => {
92
+ if (itemElementsMap[itemId] === element) {
93
+ return;
94
+ }
95
+ const oldElement = itemElementsMap[itemId];
96
+ if (oldElement && !element) {
97
+ eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, instance, oldElement, treeInstance); });
98
+ }
99
+ else if (!oldElement && element) {
100
+ eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature, instance, element, treeInstance); });
101
+ }
102
+ itemElementsMap[itemId] = element;
103
+ }, getElement: () => itemElementsMap[itemId],
104
+ // eslint-disable-next-line no-return-assign
105
+ getDataRef: () => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); }, getItemMeta: () => itemMetaMap[itemId] })),
106
+ };
107
+ // todo sort features
108
+ const features = [mainFeature, ...additionalFeatures];
109
+ for (const feature of features) {
110
+ Object.assign(treeInstance, (_d = (_c = feature.createTreeInstance) === null || _c === void 0 ? void 0 : _c.call(feature, Object.assign({}, treeInstance), treeInstance)) !== null && _d !== void 0 ? _d : {});
111
+ Object.assign(hotkeyPresets, (_e = feature.hotkeys) !== null && _e !== void 0 ? _e : {});
112
+ }
113
+ rebuildItemMeta(mainFeature);
114
+ return treeInstance;
115
+ };
116
+ exports.createTree = createTree;
@@ -0,0 +1,9 @@
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 {};
@@ -0,0 +1,32 @@
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;
@@ -0,0 +1,7 @@
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
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import { FeatureImplementation } from "../../types/core";
2
+ import { AsyncDataLoaderFeatureDef } from "./types";
3
+ import { MainFeatureDef } from "../main/types";
4
+ import { TreeFeatureDef } from "../tree/types";
5
+ export declare const asyncDataLoaderFeature: FeatureImplementation<any, AsyncDataLoaderFeatureDef<any>, MainFeatureDef | TreeFeatureDef<any> | AsyncDataLoaderFeatureDef<any>>;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.asyncDataLoaderFeature = void 0;
4
+ const utils_1 = require("../../utils");
5
+ exports.asyncDataLoaderFeature = {
6
+ key: "async-data-loader",
7
+ dependingFeatures: ["main"],
8
+ getInitialState: (initialState) => (Object.assign({ loadingItems: [] }, initialState)),
9
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItems: (0, utils_1.makeStateUpdater)("loadingItems", tree) }, defaultConfig)),
10
+ createTreeInstance: (prev, instance) => (Object.assign(Object.assign({}, prev), { retrieveItemData: (itemId) => {
11
+ var _a, _b, _c, _d, _e, _f;
12
+ var _g, _h;
13
+ const config = instance.getConfig();
14
+ const dataRef = instance.getDataRef();
15
+ (_a = (_g = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_g.itemData = {});
16
+ (_b = (_h = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_h.childrenIds = {});
17
+ if (dataRef.current.itemData[itemId]) {
18
+ return dataRef.current.itemData[itemId];
19
+ }
20
+ if (!instance.getState().loadingItems.includes(itemId)) {
21
+ (_c = config.setLoadingItems) === null || _c === void 0 ? void 0 : _c.call(config, (loadingItems) => [...loadingItems, itemId]);
22
+ (_d = config.asyncDataLoader) === null || _d === void 0 ? void 0 : _d.getItem(itemId).then((item) => {
23
+ var _a, _b;
24
+ dataRef.current.itemData[itemId] = item;
25
+ (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, itemId, item);
26
+ (_b = config.setLoadingItems) === null || _b === void 0 ? void 0 : _b.call(config, (loadingItems) => loadingItems.filter((id) => id !== itemId));
27
+ });
28
+ }
29
+ return (_f = (_e = config.createLoadingItemData) === null || _e === void 0 ? void 0 : _e.call(config)) !== null && _f !== void 0 ? _f : null;
30
+ }, retrieveChildrenIds: (itemId) => {
31
+ var _a, _b, _c, _d, _e, _f;
32
+ var _g, _h;
33
+ const config = instance.getConfig();
34
+ const dataRef = instance.getDataRef();
35
+ (_a = (_g = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_g.itemData = {});
36
+ (_b = (_h = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_h.childrenIds = {});
37
+ if (dataRef.current.childrenIds[itemId]) {
38
+ return dataRef.current.childrenIds[itemId];
39
+ }
40
+ if (instance.getState().loadingItems.includes(itemId)) {
41
+ return [];
42
+ }
43
+ (_c = config.setLoadingItems) === null || _c === void 0 ? void 0 : _c.call(config, (loadingItems) => [...loadingItems, itemId]);
44
+ if ((_d = config.asyncDataLoader) === null || _d === void 0 ? void 0 : _d.getChildrenWithData) {
45
+ (_e = config.asyncDataLoader) === null || _e === void 0 ? void 0 : _e.getChildrenWithData(itemId).then((children) => {
46
+ var _a, _b, _c;
47
+ for (const { id, data } of children) {
48
+ dataRef.current.itemData[id] = data;
49
+ (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, id, data);
50
+ }
51
+ const childrenIds = children.map(({ id }) => id);
52
+ dataRef.current.childrenIds[itemId] = childrenIds;
53
+ (_b = config.onLoadedChildren) === null || _b === void 0 ? void 0 : _b.call(config, itemId, childrenIds);
54
+ (_c = config.setLoadingItems) === null || _c === void 0 ? void 0 : _c.call(config, (loadingItems) => loadingItems.filter((id) => id !== itemId));
55
+ instance.rebuildTree();
56
+ });
57
+ }
58
+ else {
59
+ (_f = config.asyncDataLoader) === null || _f === void 0 ? void 0 : _f.getChildren(itemId).then((childrenIds) => {
60
+ var _a, _b;
61
+ dataRef.current.childrenIds[itemId] = childrenIds;
62
+ (_a = config.onLoadedChildren) === null || _a === void 0 ? void 0 : _a.call(config, itemId, childrenIds);
63
+ (_b = config.setLoadingItems) === null || _b === void 0 ? void 0 : _b.call(config, (loadingItems) => loadingItems.filter((id) => id !== itemId));
64
+ instance.rebuildTree();
65
+ });
66
+ }
67
+ return [];
68
+ }, invalidateItemData: (itemId) => {
69
+ var _a;
70
+ const dataRef = instance.getDataRef();
71
+ (_a = dataRef.current.itemData) === null || _a === void 0 ? true : delete _a[itemId];
72
+ instance.retrieveItemData(itemId);
73
+ }, invalidateChildrenIds: (itemId) => {
74
+ var _a;
75
+ const dataRef = instance.getDataRef();
76
+ (_a = dataRef.current.childrenIds) === null || _a === void 0 ? true : delete _a[itemId];
77
+ instance.retrieveChildrenIds(itemId);
78
+ } })),
79
+ createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { isLoading: () => tree.getState().loadingItems.includes(item.getItemMeta().itemId), invalidateItemData: () => tree.invalidateItemData(item.getItemMeta().itemId), invalidateChildrenIds: () => tree.invalidateChildrenIds(item.getItemMeta().itemId) })),
80
+ };
@@ -0,0 +1,41 @@
1
+ import { SetStateFn } from "../../types/core";
2
+ import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
3
+ export type AsyncTreeDataLoader<T> = {
4
+ getItem: (itemId: string) => Promise<T>;
5
+ getChildren: (itemId: string) => Promise<string[]>;
6
+ getChildrenWithData?: (itemId: string) => Promise<{
7
+ id: string;
8
+ data: T;
9
+ }[]>;
10
+ };
11
+ export type AsyncDataLoaderRef<T = any> = {
12
+ itemData: Record<string, T>;
13
+ childrenIds: Record<string, string[]>;
14
+ };
15
+ /**
16
+ * @category Async Data Loader/General
17
+ * */
18
+ export type AsyncDataLoaderFeatureDef<T> = {
19
+ state: {
20
+ loadingItems: string[];
21
+ };
22
+ config: {
23
+ rootItemId: string;
24
+ createLoadingItemData?: () => T;
25
+ setLoadingItems?: SetStateFn<string[]>;
26
+ onLoadedItem?: (itemId: string, item: T) => void;
27
+ onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
28
+ asyncDataLoader?: AsyncTreeDataLoader<T>;
29
+ };
30
+ treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"] & {
31
+ /** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible */
32
+ invalidateItemData: (itemId: string) => void;
33
+ invalidateChildrenIds: (itemId: string) => void;
34
+ };
35
+ itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
36
+ invalidateItemData: () => void;
37
+ invalidateChildrenIds: () => void;
38
+ isLoading: () => void;
39
+ };
40
+ hotkeys: SyncDataLoaderFeatureDef<T>["hotkeys"];
41
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import { FeatureDefs, FeatureImplementation } from "../../types/core";
2
+ import { DragAndDropFeatureDef } from "./types";
3
+ export declare const dragAndDropFeature: FeatureImplementation<any, DragAndDropFeatureDef<any>, FeatureDefs<any>>;
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dragAndDropFeature = void 0;
4
+ const utils_1 = require("./utils");
5
+ const utils_2 = require("../../utils");
6
+ exports.dragAndDropFeature = {
7
+ key: "dragAndDrop",
8
+ dependingFeatures: ["main", "tree", "selection"],
9
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ canDrop: (_, target) => target.item.isFolder(), setDndState: (0, utils_2.makeStateUpdater)("dnd", tree) }, defaultConfig)),
10
+ createTreeInstance: (prev, tree) => (Object.assign(Object.assign({}, prev), { getDropTarget: () => {
11
+ var _a, _b;
12
+ return (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.dragTarget) !== null && _b !== void 0 ? _b : null;
13
+ } })),
14
+ createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { getProps: () => {
15
+ var _a, _b, _c;
16
+ return (Object.assign(Object.assign({}, prev.getProps()), { draggable: (_c = (_b = (_a = tree.getConfig()).isItemDraggable) === null || _b === void 0 ? void 0 : _b.call(_a, item)) !== null && _c !== void 0 ? _c : true, onDragStart: (e) => {
17
+ var _a, _b, _c, _d, _e;
18
+ const selectedItems = tree.getSelectedItems();
19
+ const items = selectedItems.includes(item) ? selectedItems : [item];
20
+ const config = tree.getConfig();
21
+ if (!selectedItems.includes(item)) {
22
+ tree.setSelectedItems([item.getItemMeta().itemId]);
23
+ }
24
+ if (!((_b = (_a = config.canDrag) === null || _a === void 0 ? void 0 : _a.call(config, items)) !== null && _b !== void 0 ? _b : true)) {
25
+ e.preventDefault();
26
+ return;
27
+ }
28
+ if (config.createForeignDragObject) {
29
+ const { format, data } = config.createForeignDragObject(items);
30
+ (_c = e.dataTransfer) === null || _c === void 0 ? void 0 : _c.setData(format, data);
31
+ }
32
+ (_e = (_d = tree.getConfig()).setDndState) === null || _e === void 0 ? void 0 : _e.call(_d, {
33
+ draggedItems: items,
34
+ draggingOverItem: tree.getFocusedItem(),
35
+ });
36
+ }, onDragOver: (e) => {
37
+ var _a, _b, _c, _d, _e;
38
+ const target = (0, utils_1.getDropTarget)(e, item, tree);
39
+ const dataRef = tree.getDataRef();
40
+ if (!((_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) &&
41
+ !((_c = (_b = tree.getConfig()).canDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(_b, e.dataTransfer, target))) {
42
+ return;
43
+ }
44
+ if (!(0, utils_1.canDrop)(e.dataTransfer, target, tree)) {
45
+ return;
46
+ }
47
+ e.preventDefault();
48
+ const nextDragCode = (0, utils_1.getDragCode)(target);
49
+ if (nextDragCode === dataRef.current.lastDragCode) {
50
+ return;
51
+ }
52
+ dataRef.current.lastDragCode = nextDragCode;
53
+ (_e = (_d = tree.getConfig()).setDndState) === null || _e === void 0 ? void 0 : _e.call(_d, (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
54
+ }, onDragLeave: () => {
55
+ var _a, _b;
56
+ const dataRef = tree.getDataRef();
57
+ dataRef.current.lastDragCode = "no-drag";
58
+ (_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
59
+ }, onDrop: (e) => {
60
+ var _a, _b, _c, _d, _e;
61
+ const dataRef = tree.getDataRef();
62
+ const target = (0, utils_1.getDropTarget)(e, item, tree);
63
+ if (!(0, utils_1.canDrop)(e.dataTransfer, target, tree)) {
64
+ return;
65
+ }
66
+ e.preventDefault();
67
+ const config = tree.getConfig();
68
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
69
+ dataRef.current.lastDragCode = undefined;
70
+ (_c = (_b = tree.getConfig()).setDndState) === null || _c === void 0 ? void 0 : _c.call(_b, null);
71
+ if (draggedItems) {
72
+ (_d = config.onDrop) === null || _d === void 0 ? void 0 : _d.call(config, draggedItems, target);
73
+ }
74
+ else {
75
+ (_e = config.onDropForeignDragObject) === null || _e === void 0 ? void 0 : _e.call(config, e.dataTransfer, target);
76
+ }
77
+ // TODO rebuild tree?
78
+ } }));
79
+ }, isDropTarget: () => {
80
+ const target = tree.getDropTarget();
81
+ return target ? target.item.getId() === item.getId() : false;
82
+ }, isDropTargetAbove: () => {
83
+ const target = tree.getDropTarget();
84
+ if (!target || target.childIndex === null)
85
+ return false;
86
+ const targetIndex = target.item.getItemMeta().index;
87
+ return targetIndex + target.childIndex + 1 === item.getItemMeta().index;
88
+ }, isDropTargetBelow: () => {
89
+ const target = tree.getDropTarget();
90
+ if (!target || target.childIndex === null)
91
+ return false;
92
+ const targetIndex = target.item.getItemMeta().index;
93
+ return targetIndex + target.childIndex === item.getItemMeta().index;
94
+ }, isDraggingOver: () => {
95
+ var _a, _b;
96
+ return ((_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggingOverItem) === null || _b === void 0 ? void 0 : _b.getId()) === item.getId();
97
+ } })),
98
+ hotkeys: {
99
+ startDnd: {
100
+ hotkey: "Control+Alt+d",
101
+ handler: (e, tree) => {
102
+ console.log("DRAG");
103
+ tree.getFocusedItem().getProps().onDragStart(e);
104
+ },
105
+ },
106
+ cancelDnd: {
107
+ hotkey: "Escape",
108
+ isEnabled: (tree) => !!tree.getState().dnd,
109
+ handler: (e, tree) => {
110
+ var _a, _b;
111
+ (_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, null);
112
+ },
113
+ },
114
+ completeDnd: {
115
+ hotkey: "Enter",
116
+ isEnabled: (tree) => !!tree.getState().dnd,
117
+ handler: (e, tree) => {
118
+ console.log("DROP");
119
+ },
120
+ },
121
+ dndDown: {
122
+ preventDefault: true,
123
+ hotkey: "ArrowDown",
124
+ isEnabled: (tree) => !!tree.getState().dnd,
125
+ handler: (e, tree) => {
126
+ var _a, _b;
127
+ const target = (0, utils_1.searchDropTarget)(tree, false);
128
+ console.log("Down", target);
129
+ (_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, (state) => (Object.assign(Object.assign({}, state), { dragTarget: target !== null && target !== void 0 ? target : undefined })));
130
+ },
131
+ },
132
+ dndUp: {
133
+ preventDefault: true,
134
+ hotkey: "ArrowUp",
135
+ isEnabled: (tree) => !!tree.getState().dnd,
136
+ handler: (e, tree) => {
137
+ var _a, _b;
138
+ const target = (0, utils_1.searchDropTarget)(tree, true);
139
+ console.log("Up", target);
140
+ (_b = (_a = tree.getConfig()).setDndState) === null || _b === void 0 ? void 0 : _b.call(_a, (state) => (Object.assign(Object.assign({}, state), { dragTarget: target !== null && target !== void 0 ? target : undefined })));
141
+ },
142
+ },
143
+ },
144
+ };
@@ -0,0 +1,49 @@
1
+ import { ItemInstance, SetStateFn } from "../../types/core";
2
+ export type DndDataRef = {
3
+ lastDragCode?: string;
4
+ };
5
+ export type DndState<T> = {
6
+ draggedItems?: ItemInstance<T>[];
7
+ draggingOverItem?: ItemInstance<T>;
8
+ dragTarget?: DropTarget<T>;
9
+ };
10
+ export type DropTarget<T> = {
11
+ item: ItemInstance<T>;
12
+ childIndex: number | null;
13
+ };
14
+ export declare enum DropTargetPosition {
15
+ Top = "top",
16
+ Bottom = "bottom",
17
+ Item = "item"
18
+ }
19
+ export type DragAndDropFeatureDef<T> = {
20
+ state: {
21
+ dnd?: DndState<T> | null;
22
+ };
23
+ config: {
24
+ setDndState?: SetStateFn<DndState<T> | null>;
25
+ topLinePercentage?: number;
26
+ bottomLinePercentage?: number;
27
+ canDropInbetween?: boolean;
28
+ isItemDraggable?: (item: ItemInstance<T>) => boolean;
29
+ canDrag?: (items: ItemInstance<T>[]) => boolean;
30
+ canDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => boolean;
31
+ createForeignDragObject?: (items: ItemInstance<T>[]) => {
32
+ format: string;
33
+ data: any;
34
+ };
35
+ canDropForeignDragObject?: (dataTransfer: DataTransfer, target: DropTarget<T>) => boolean;
36
+ onDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => void;
37
+ onDropForeignDragObject?: (dataTransfer: DataTransfer, target: DropTarget<T>) => void;
38
+ };
39
+ treeInstance: {
40
+ getDropTarget: () => DropTarget<T> | null;
41
+ };
42
+ itemInstance: {
43
+ isDropTarget: () => boolean;
44
+ isDropTargetAbove: () => boolean;
45
+ isDropTargetBelow: () => boolean;
46
+ isDraggingOver: () => boolean;
47
+ };
48
+ hotkeys: "startDnd" | "completeDnd" | "cancelDnd" | "dndUp" | "dndDown";
49
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DropTargetPosition = void 0;
4
+ var DropTargetPosition;
5
+ (function (DropTargetPosition) {
6
+ DropTargetPosition["Top"] = "top";
7
+ DropTargetPosition["Bottom"] = "bottom";
8
+ DropTargetPosition["Item"] = "item";
9
+ })(DropTargetPosition = exports.DropTargetPosition || (exports.DropTargetPosition = {}));
@@ -0,0 +1,7 @@
1
+ import { ItemInstance, TreeInstance } from "../../types/core";
2
+ import { DropTarget } from "./types";
3
+ export declare const getDragCode: ({ item, childIndex }: DropTarget<any>) => string;
4
+ export declare const getDropOffset: (e: any, item: ItemInstance<any>) => number;
5
+ export declare const canDrop: (dataTransfer: DataTransfer | null, target: DropTarget<any>, tree: TreeInstance<any>) => boolean;
6
+ export declare const getDropTarget: (e: any, item: ItemInstance<any>, tree: TreeInstance<any>) => DropTarget<any>;
7
+ export declare const searchDropTarget: (tree: TreeInstance<any>, upwards?: boolean) => DropTarget<any> | null | undefined;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.searchDropTarget = exports.getDropTarget = exports.canDrop = exports.getDropOffset = exports.getDragCode = void 0;
4
+ const types_1 = require("./types");
5
+ const getDragCode = ({ item, childIndex }) => `${item.getId()}__${childIndex !== null && childIndex !== void 0 ? childIndex : "none"}`;
6
+ exports.getDragCode = getDragCode;
7
+ const getDropOffset = (e, item) => {
8
+ var _a;
9
+ const bb = (_a = item.getElement()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
10
+ return bb ? (e.pageY - bb.top) / bb.height : 0.5;
11
+ };
12
+ exports.getDropOffset = getDropOffset;
13
+ const canDrop = (dataTransfer, target, tree) => {
14
+ var _a, _b, _c, _d;
15
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
16
+ const config = tree.getConfig();
17
+ if (draggedItems && !((_c = (_b = config.canDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target)) !== null && _c !== void 0 ? _c : true)) {
18
+ return false;
19
+ }
20
+ if (!draggedItems &&
21
+ dataTransfer &&
22
+ !((_d = config.canDropForeignDragObject) === null || _d === void 0 ? void 0 : _d.call(config, dataTransfer, target))) {
23
+ return false;
24
+ }
25
+ return true;
26
+ };
27
+ exports.canDrop = canDrop;
28
+ const getDropTargetPosition = (offset, topLinePercentage, bottomLinePercentage) => {
29
+ if (offset < topLinePercentage) {
30
+ return types_1.DropTargetPosition.Top;
31
+ }
32
+ if (offset > bottomLinePercentage) {
33
+ return types_1.DropTargetPosition.Bottom;
34
+ }
35
+ return types_1.DropTargetPosition.Item;
36
+ };
37
+ const getDropTarget = (e, item, tree) => {
38
+ var _a, _b;
39
+ const config = tree.getConfig();
40
+ const offset = (0, exports.getDropOffset)(e, item);
41
+ const dropOnItemTarget = { item, childIndex: null };
42
+ const pos = getDropTargetPosition(offset, (_a = config.topLinePercentage) !== null && _a !== void 0 ? _a : 0.3, (_b = config.bottomLinePercentage) !== null && _b !== void 0 ? _b : 0.7);
43
+ const inbetweenPos = getDropTargetPosition(offset, 0.5, 0.5);
44
+ if (!config.canDropInbetween) {
45
+ return dropOnItemTarget;
46
+ }
47
+ if (!(0, exports.canDrop)(e.dataTransfer, dropOnItemTarget, tree)) {
48
+ return {
49
+ item: item.getParent(),
50
+ childIndex: item.getIndexInParent() +
51
+ (inbetweenPos === types_1.DropTargetPosition.Top ? 0 : 1),
52
+ };
53
+ }
54
+ if (pos === types_1.DropTargetPosition.Item) {
55
+ return dropOnItemTarget;
56
+ }
57
+ return {
58
+ item: item.getParent(),
59
+ childIndex: item.getIndexInParent() + (pos === types_1.DropTargetPosition.Top ? 0 : 1),
60
+ };
61
+ };
62
+ exports.getDropTarget = getDropTarget;
63
+ const searchDropTarget = (tree, upwards = false) => {
64
+ const state = tree.getState().dnd;
65
+ console.log("!", state);
66
+ if (!state || !state.draggingOverItem)
67
+ return null;
68
+ let currentItem = state.draggingOverItem;
69
+ while (currentItem) {
70
+ // const targetAbove: DropTarget<any> = {
71
+ // item: currentItem.getParent(),
72
+ // childIndex: currentItem.getIndexInParent() + (upwards ? -1 : 1),
73
+ // };
74
+ // if (canDrop(null, targetAbove, tree)) {
75
+ // return targetAbove;
76
+ // }
77
+ const itemTarget = {
78
+ item: currentItem,
79
+ childIndex: null,
80
+ };
81
+ if ((0, exports.canDrop)(null, itemTarget, tree)) {
82
+ return itemTarget;
83
+ }
84
+ currentItem = upwards
85
+ ? currentItem.getItemAbove()
86
+ : currentItem.getItemBelow();
87
+ }
88
+ };
89
+ exports.searchDropTarget = searchDropTarget;
90
+ /*
91
+
92
+ export const searchDropTarget = (
93
+ tree: TreeInstance<any>,
94
+ backwards = false,
95
+ target = tree.getState().dnd?.dragTarget
96
+ ) => {
97
+ const state = tree.getState().dnd;
98
+ if (!state) return null;
99
+ if (target && canDrop(null, target, tree)) return target;
100
+
101
+ if (target?.childIndex && target?.childIndex > 0 && !backwards) {
102
+ return searchDropTarget(tree, backwards, {
103
+ ...target,
104
+ childIndex: target.childIndex - 1,
105
+ });
106
+ }
107
+
108
+ if (
109
+ target?.childIndex &&
110
+ target?.childIndex < target.item.getChildren().length - 1 &&
111
+ backwards
112
+ ) {
113
+ return searchDropTarget(tree, backwards, {
114
+ ...target,
115
+ childIndex: target.childIndex + 1,
116
+ });
117
+ }
118
+
119
+
120
+ };
121
+ */
@@ -0,0 +1,6 @@
1
+ import { FeatureImplementation } from "../../types/core";
2
+ import { ExpandAllFeatureDef } from "./types";
3
+ import { MainFeatureDef } from "../main/types";
4
+ import { TreeFeatureDef } from "../tree/types";
5
+ import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
6
+ export declare const expandAllFeature: FeatureImplementation<any, ExpandAllFeatureDef, MainFeatureDef | TreeFeatureDef<any> | SyncDataLoaderFeatureDef<any> | ExpandAllFeatureDef>;