@headless-tree/core 0.0.0-20230802230636

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 (149) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/lib/cjs/core/create-tree.d.ts +2 -0
  3. package/lib/cjs/core/create-tree.js +138 -0
  4. package/lib/cjs/features/async-data-loader/feature.d.ts +5 -0
  5. package/lib/cjs/features/async-data-loader/feature.js +88 -0
  6. package/lib/cjs/features/async-data-loader/types.d.ts +41 -0
  7. package/lib/cjs/features/async-data-loader/types.js +2 -0
  8. package/lib/cjs/features/drag-and-drop/feature.d.ts +3 -0
  9. package/lib/cjs/features/drag-and-drop/feature.js +138 -0
  10. package/lib/cjs/features/drag-and-drop/types.d.ts +69 -0
  11. package/lib/cjs/features/drag-and-drop/types.js +9 -0
  12. package/lib/cjs/features/drag-and-drop/utils.d.ts +6 -0
  13. package/lib/cjs/features/drag-and-drop/utils.js +79 -0
  14. package/lib/cjs/features/expand-all/feature.d.ts +6 -0
  15. package/lib/cjs/features/expand-all/feature.js +41 -0
  16. package/lib/cjs/features/expand-all/types.d.ts +17 -0
  17. package/lib/cjs/features/expand-all/types.js +2 -0
  18. package/lib/cjs/features/hotkeys-core/feature.d.ts +4 -0
  19. package/lib/cjs/features/hotkeys-core/feature.js +71 -0
  20. package/lib/cjs/features/hotkeys-core/types.d.ts +25 -0
  21. package/lib/cjs/features/hotkeys-core/types.js +2 -0
  22. package/lib/cjs/features/main/types.d.ts +39 -0
  23. package/lib/cjs/features/main/types.js +2 -0
  24. package/lib/cjs/features/renaming/feature.d.ts +5 -0
  25. package/lib/cjs/features/renaming/feature.js +64 -0
  26. package/lib/cjs/features/renaming/types.d.ts +27 -0
  27. package/lib/cjs/features/renaming/types.js +2 -0
  28. package/lib/cjs/features/search/feature.d.ts +5 -0
  29. package/lib/cjs/features/search/feature.js +103 -0
  30. package/lib/cjs/features/search/types.d.ts +33 -0
  31. package/lib/cjs/features/search/types.js +2 -0
  32. package/lib/cjs/features/selection/feature.d.ts +5 -0
  33. package/lib/cjs/features/selection/feature.js +113 -0
  34. package/lib/cjs/features/selection/types.d.ts +21 -0
  35. package/lib/cjs/features/selection/types.js +2 -0
  36. package/lib/cjs/features/sync-data-loader/feature.d.ts +4 -0
  37. package/lib/cjs/features/sync-data-loader/feature.js +14 -0
  38. package/lib/cjs/features/sync-data-loader/types.d.ts +19 -0
  39. package/lib/cjs/features/sync-data-loader/types.js +2 -0
  40. package/lib/cjs/features/tree/feature.d.ts +6 -0
  41. package/lib/cjs/features/tree/feature.js +230 -0
  42. package/lib/cjs/features/tree/types.d.ts +62 -0
  43. package/lib/cjs/features/tree/types.js +2 -0
  44. package/lib/cjs/index.d.ts +23 -0
  45. package/lib/cjs/index.js +39 -0
  46. package/lib/cjs/mddocs-entry.d.ts +21 -0
  47. package/lib/cjs/mddocs-entry.js +17 -0
  48. package/lib/cjs/types/core.d.ts +67 -0
  49. package/lib/cjs/types/core.js +2 -0
  50. package/lib/cjs/types/deep-merge.d.ts +13 -0
  51. package/lib/cjs/types/deep-merge.js +2 -0
  52. package/lib/cjs/utilities/create-on-drop-handler.d.ts +3 -0
  53. package/lib/cjs/utilities/create-on-drop-handler.js +11 -0
  54. package/lib/cjs/utilities/insert-items-at-target.d.ts +3 -0
  55. package/lib/cjs/utilities/insert-items-at-target.js +24 -0
  56. package/lib/cjs/utilities/remove-items-from-parents.d.ts +2 -0
  57. package/lib/cjs/utilities/remove-items-from-parents.js +17 -0
  58. package/lib/cjs/utils.d.ts +6 -0
  59. package/lib/cjs/utils.js +53 -0
  60. package/lib/esm/core/create-tree.d.ts +2 -0
  61. package/lib/esm/core/create-tree.js +134 -0
  62. package/lib/esm/features/async-data-loader/feature.d.ts +5 -0
  63. package/lib/esm/features/async-data-loader/feature.js +85 -0
  64. package/lib/esm/features/async-data-loader/types.d.ts +41 -0
  65. package/lib/esm/features/async-data-loader/types.js +1 -0
  66. package/lib/esm/features/drag-and-drop/feature.d.ts +3 -0
  67. package/lib/esm/features/drag-and-drop/feature.js +135 -0
  68. package/lib/esm/features/drag-and-drop/types.d.ts +69 -0
  69. package/lib/esm/features/drag-and-drop/types.js +6 -0
  70. package/lib/esm/features/drag-and-drop/utils.d.ts +6 -0
  71. package/lib/esm/features/drag-and-drop/utils.js +72 -0
  72. package/lib/esm/features/expand-all/feature.d.ts +6 -0
  73. package/lib/esm/features/expand-all/feature.js +38 -0
  74. package/lib/esm/features/expand-all/types.d.ts +17 -0
  75. package/lib/esm/features/expand-all/types.js +1 -0
  76. package/lib/esm/features/hotkeys-core/feature.d.ts +4 -0
  77. package/lib/esm/features/hotkeys-core/feature.js +68 -0
  78. package/lib/esm/features/hotkeys-core/types.d.ts +25 -0
  79. package/lib/esm/features/hotkeys-core/types.js +1 -0
  80. package/lib/esm/features/main/types.d.ts +39 -0
  81. package/lib/esm/features/main/types.js +1 -0
  82. package/lib/esm/features/renaming/feature.d.ts +5 -0
  83. package/lib/esm/features/renaming/feature.js +61 -0
  84. package/lib/esm/features/renaming/types.d.ts +27 -0
  85. package/lib/esm/features/renaming/types.js +1 -0
  86. package/lib/esm/features/search/feature.d.ts +5 -0
  87. package/lib/esm/features/search/feature.js +100 -0
  88. package/lib/esm/features/search/types.d.ts +33 -0
  89. package/lib/esm/features/search/types.js +1 -0
  90. package/lib/esm/features/selection/feature.d.ts +5 -0
  91. package/lib/esm/features/selection/feature.js +110 -0
  92. package/lib/esm/features/selection/types.d.ts +21 -0
  93. package/lib/esm/features/selection/types.js +1 -0
  94. package/lib/esm/features/sync-data-loader/feature.d.ts +4 -0
  95. package/lib/esm/features/sync-data-loader/feature.js +11 -0
  96. package/lib/esm/features/sync-data-loader/types.d.ts +19 -0
  97. package/lib/esm/features/sync-data-loader/types.js +1 -0
  98. package/lib/esm/features/tree/feature.d.ts +6 -0
  99. package/lib/esm/features/tree/feature.js +227 -0
  100. package/lib/esm/features/tree/types.d.ts +62 -0
  101. package/lib/esm/features/tree/types.js +1 -0
  102. package/lib/esm/index.d.ts +23 -0
  103. package/lib/esm/index.js +23 -0
  104. package/lib/esm/mddocs-entry.d.ts +21 -0
  105. package/lib/esm/mddocs-entry.js +1 -0
  106. package/lib/esm/types/core.d.ts +67 -0
  107. package/lib/esm/types/core.js +1 -0
  108. package/lib/esm/types/deep-merge.d.ts +13 -0
  109. package/lib/esm/types/deep-merge.js +1 -0
  110. package/lib/esm/utilities/create-on-drop-handler.d.ts +3 -0
  111. package/lib/esm/utilities/create-on-drop-handler.js +7 -0
  112. package/lib/esm/utilities/insert-items-at-target.d.ts +3 -0
  113. package/lib/esm/utilities/insert-items-at-target.js +20 -0
  114. package/lib/esm/utilities/remove-items-from-parents.d.ts +2 -0
  115. package/lib/esm/utilities/remove-items-from-parents.js +13 -0
  116. package/lib/esm/utils.d.ts +6 -0
  117. package/lib/esm/utils.js +46 -0
  118. package/package.json +23 -0
  119. package/src/core/create-tree.ts +228 -0
  120. package/src/features/async-data-loader/feature.ts +126 -0
  121. package/src/features/async-data-loader/types.ts +41 -0
  122. package/src/features/drag-and-drop/feature.ts +214 -0
  123. package/src/features/drag-and-drop/types.ts +89 -0
  124. package/src/features/drag-and-drop/utils.ts +117 -0
  125. package/src/features/expand-all/feature.ts +63 -0
  126. package/src/features/expand-all/types.ts +13 -0
  127. package/src/features/hotkeys-core/feature.ts +110 -0
  128. package/src/features/hotkeys-core/types.ts +36 -0
  129. package/src/features/main/types.ts +48 -0
  130. package/src/features/renaming/feature.ts +105 -0
  131. package/src/features/renaming/types.ts +28 -0
  132. package/src/features/search/feature.ts +158 -0
  133. package/src/features/search/types.ts +40 -0
  134. package/src/features/selection/feature.ts +157 -0
  135. package/src/features/selection/types.ts +28 -0
  136. package/src/features/sync-data-loader/feature.ts +41 -0
  137. package/src/features/sync-data-loader/types.ts +20 -0
  138. package/src/features/tree/feature.ts +326 -0
  139. package/src/features/tree/types.ts +78 -0
  140. package/src/index.ts +26 -0
  141. package/src/mddocs-entry.ts +26 -0
  142. package/src/types/core.ts +183 -0
  143. package/src/types/deep-merge.ts +31 -0
  144. package/src/utilities/create-on-drop-handler.ts +14 -0
  145. package/src/utilities/insert-items-at-target.ts +30 -0
  146. package/src/utilities/remove-items-from-parents.ts +21 -0
  147. package/src/utils.ts +68 -0
  148. package/tsconfig.json +7 -0
  149. package/typedoc.json +4 -0
@@ -0,0 +1,134 @@
1
+ import { treeFeature } from "../features/tree/feature";
2
+ const buildItemInstance = (features, tree, itemId) => {
3
+ var _a, _b;
4
+ const itemInstance = {};
5
+ for (const feature of features) {
6
+ 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 : {});
7
+ }
8
+ return itemInstance;
9
+ };
10
+ const verifyFeatures = (features) => {
11
+ var _a;
12
+ const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key);
13
+ for (const feature of features !== null && features !== void 0 ? features : []) {
14
+ const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep)));
15
+ if (missingDependency) {
16
+ throw new Error(`${feature.key} needs ${missingDependency}`);
17
+ }
18
+ }
19
+ };
20
+ const compareFeatures = (feature1, feature2) => {
21
+ var _a;
22
+ if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) {
23
+ return 1;
24
+ }
25
+ return -1;
26
+ };
27
+ const sortFeatures = (features = []) => features.sort(compareFeatures);
28
+ export const createTree = (initialConfig) => {
29
+ var _a, _b, _c, _d, _e;
30
+ const treeInstance = {};
31
+ const additionalFeatures = [
32
+ treeFeature,
33
+ ...sortFeatures(initialConfig.features),
34
+ ];
35
+ verifyFeatures(additionalFeatures);
36
+ 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 = (_a = initialConfig.initialState) !== null && _a !== void 0 ? _a : initialConfig.state) !== null && _b !== void 0 ? _b : {});
37
+ 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);
38
+ const stateHandlerNames = additionalFeatures.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature.stateHandlerNames)), {});
39
+ let treeElement;
40
+ const treeDataRef = { current: {} };
41
+ const itemInstancesMap = {};
42
+ let itemInstances = [];
43
+ const itemElementsMap = {};
44
+ const itemDataRefs = {};
45
+ let itemMetaMap = {};
46
+ const hotkeyPresets = {};
47
+ const rebuildItemMeta = (main) => {
48
+ // TODO can we find a way to only run this for the changed substructure?
49
+ itemInstances = [];
50
+ itemMetaMap = {};
51
+ const rootInstance = buildItemInstance([main, ...additionalFeatures], treeInstance, config.rootItemId);
52
+ itemInstancesMap[config.rootItemId] = rootInstance;
53
+ itemMetaMap[config.rootItemId] = {
54
+ itemId: config.rootItemId,
55
+ index: -1,
56
+ parentId: null,
57
+ level: -1,
58
+ posInSet: 0,
59
+ setSize: 1,
60
+ };
61
+ for (const item of treeInstance.getItemsMeta()) {
62
+ itemMetaMap[item.itemId] = item;
63
+ if (!itemInstancesMap[item.itemId]) {
64
+ const instance = buildItemInstance([main, ...additionalFeatures], treeInstance, item.itemId);
65
+ itemInstancesMap[item.itemId] = instance;
66
+ itemInstances.push(instance);
67
+ }
68
+ else {
69
+ itemInstances.push(itemInstancesMap[item.itemId]);
70
+ }
71
+ }
72
+ console.log("REBUILT");
73
+ };
74
+ const eachFeature = (fn) => {
75
+ for (const feature of additionalFeatures) {
76
+ fn(feature);
77
+ }
78
+ };
79
+ const mainFeature = {
80
+ key: "main",
81
+ createTreeInstance: (prev) => (Object.assign(Object.assign({}, prev), { getState: () => state, setState: (updater) => {
82
+ var _a;
83
+ // Not necessary, since I think the subupdate below keeps the state fresh anyways?
84
+ // state = typeof updater === "function" ? updater(state) : updater;
85
+ (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
86
+ }, applySubStateUpdate: (stateName, updater) => {
87
+ state[stateName] =
88
+ typeof updater === "function" ? updater(state[stateName]) : updater;
89
+ config[stateHandlerNames[stateName]](state[stateName]);
90
+ }, rebuildTree: () => {
91
+ var _a;
92
+ rebuildItemMeta(mainFeature);
93
+ (_a = config.setState) === null || _a === void 0 ? void 0 : _a.call(config, state);
94
+ }, getConfig: () => config, setConfig: (updater) => {
95
+ config = typeof updater === "function" ? updater(config) : updater;
96
+ if (config.state) {
97
+ state = Object.assign(Object.assign({}, state), config.state);
98
+ }
99
+ }, getItemInstance: (itemId) => itemInstancesMap[itemId], getItems: () => itemInstances, registerElement: (element) => {
100
+ if (treeElement === element) {
101
+ return;
102
+ }
103
+ if (treeElement && !element) {
104
+ eachFeature((feature) => { var _a; return (_a = feature.onTreeUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, treeElement); });
105
+ }
106
+ else if (!treeElement && element) {
107
+ eachFeature((feature) => { var _a; return (_a = feature.onTreeMount) === null || _a === void 0 ? void 0 : _a.call(feature, treeInstance, element); });
108
+ }
109
+ treeElement = element;
110
+ }, getElement: () => treeElement, getDataRef: () => treeDataRef, getHotkeyPresets: () => hotkeyPresets })),
111
+ createItemInstance: (prev, instance, _, itemId) => (Object.assign(Object.assign({}, prev), { registerElement: (element) => {
112
+ if (itemElementsMap[itemId] === element) {
113
+ return;
114
+ }
115
+ const oldElement = itemElementsMap[itemId];
116
+ if (oldElement && !element) {
117
+ eachFeature((feature) => { var _a; return (_a = feature.onItemUnmount) === null || _a === void 0 ? void 0 : _a.call(feature, instance, oldElement, treeInstance); });
118
+ }
119
+ else if (!oldElement && element) {
120
+ eachFeature((feature) => { var _a; return (_a = feature.onItemMount) === null || _a === void 0 ? void 0 : _a.call(feature, instance, element, treeInstance); });
121
+ }
122
+ itemElementsMap[itemId] = element;
123
+ }, getElement: () => itemElementsMap[itemId],
124
+ // eslint-disable-next-line no-return-assign
125
+ getDataRef: () => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); }, getItemMeta: () => itemMetaMap[itemId] })),
126
+ };
127
+ const features = [mainFeature, ...additionalFeatures];
128
+ for (const feature of features) {
129
+ 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 : {});
130
+ Object.assign(hotkeyPresets, (_e = feature.hotkeys) !== null && _e !== void 0 ? _e : {});
131
+ }
132
+ rebuildItemMeta(mainFeature);
133
+ return treeInstance;
134
+ };
@@ -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,85 @@
1
+ import { makeStateUpdater } from "../../utils";
2
+ export const asyncDataLoaderFeature = {
3
+ key: "async-data-loader",
4
+ getInitialState: (initialState) => (Object.assign({ loadingItems: [] }, initialState)),
5
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItems: makeStateUpdater("loadingItems", tree) }, defaultConfig)),
6
+ stateHandlerNames: {
7
+ loadingItems: "setLoadingItems",
8
+ },
9
+ createTreeInstance: (prev, instance) => (Object.assign(Object.assign({}, prev), { retrieveItemData: (itemId) => {
10
+ var _a, _b, _c, _d, _e;
11
+ var _f, _g;
12
+ const config = instance.getConfig();
13
+ const dataRef = instance.getDataRef();
14
+ (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
15
+ (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
16
+ if (dataRef.current.itemData[itemId]) {
17
+ return dataRef.current.itemData[itemId];
18
+ }
19
+ if (!instance.getState().loadingItems.includes(itemId)) {
20
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => [
21
+ ...loadingItems,
22
+ itemId,
23
+ ]);
24
+ (_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getItem(itemId).then((item) => {
25
+ var _a;
26
+ dataRef.current.itemData[itemId] = item;
27
+ (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, itemId, item);
28
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
29
+ });
30
+ }
31
+ return (_e = (_d = config.createLoadingItemData) === null || _d === void 0 ? void 0 : _d.call(config)) !== null && _e !== void 0 ? _e : null;
32
+ }, retrieveChildrenIds: (itemId) => {
33
+ var _a, _b, _c, _d, _e;
34
+ var _f, _g;
35
+ const config = instance.getConfig();
36
+ const dataRef = instance.getDataRef();
37
+ (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
38
+ (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
39
+ if (dataRef.current.childrenIds[itemId]) {
40
+ return dataRef.current.childrenIds[itemId];
41
+ }
42
+ if (instance.getState().loadingItems.includes(itemId)) {
43
+ return [];
44
+ }
45
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => [
46
+ ...loadingItems,
47
+ itemId,
48
+ ]);
49
+ if ((_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getChildrenWithData) {
50
+ (_d = config.asyncDataLoader) === null || _d === void 0 ? void 0 : _d.getChildrenWithData(itemId).then((children) => {
51
+ var _a, _b;
52
+ for (const { id, data } of children) {
53
+ dataRef.current.itemData[id] = data;
54
+ (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, id, data);
55
+ }
56
+ const childrenIds = children.map(({ id }) => id);
57
+ dataRef.current.childrenIds[itemId] = childrenIds;
58
+ (_b = config.onLoadedChildren) === null || _b === void 0 ? void 0 : _b.call(config, itemId, childrenIds);
59
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
60
+ instance.rebuildTree();
61
+ });
62
+ }
63
+ else {
64
+ (_e = config.asyncDataLoader) === null || _e === void 0 ? void 0 : _e.getChildren(itemId).then((childrenIds) => {
65
+ var _a;
66
+ dataRef.current.childrenIds[itemId] = childrenIds;
67
+ (_a = config.onLoadedChildren) === null || _a === void 0 ? void 0 : _a.call(config, itemId, childrenIds);
68
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
69
+ instance.rebuildTree();
70
+ });
71
+ }
72
+ return [];
73
+ }, invalidateItemData: (itemId) => {
74
+ var _a;
75
+ const dataRef = instance.getDataRef();
76
+ (_a = dataRef.current.itemData) === null || _a === void 0 ? true : delete _a[itemId];
77
+ instance.retrieveItemData(itemId);
78
+ }, invalidateChildrenIds: (itemId) => {
79
+ var _a;
80
+ const dataRef = instance.getDataRef();
81
+ (_a = dataRef.current.childrenIds) === null || _a === void 0 ? true : delete _a[itemId];
82
+ instance.retrieveChildrenIds(itemId);
83
+ } })),
84
+ 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) })),
85
+ };
@@ -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 @@
1
+ export {};
@@ -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,135 @@
1
+ import { canDrop, getDragCode, getDropTarget } from "./utils";
2
+ import { makeStateUpdater } from "../../utils";
3
+ export const dragAndDropFeature = {
4
+ key: "dragAndDrop",
5
+ deps: ["selection"],
6
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ canDrop: (_, target) => target.item.isFolder(), canDropForeignDragObject: () => false, setDndState: makeStateUpdater("dnd", tree) }, defaultConfig)),
7
+ stateHandlerNames: {
8
+ dnd: "setDndState",
9
+ },
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
+ }, getDragLineData: () => {
14
+ var _a, _b, _c, _d, _e;
15
+ const target = tree.getDropTarget();
16
+ const intend = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1;
17
+ if (!target || target.childIndex === null)
18
+ return null;
19
+ const children = target.item.getChildren();
20
+ if (target.childIndex === children.length) {
21
+ const bb = (_c = (_b = children[target.childIndex - 1]) === null || _b === void 0 ? void 0 : _b.getElement()) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
22
+ if (bb) {
23
+ return {
24
+ intend,
25
+ top: bb.bottom,
26
+ left: bb.left,
27
+ right: bb.right,
28
+ };
29
+ }
30
+ }
31
+ const bb = (_e = (_d = children[target.childIndex]) === null || _d === void 0 ? void 0 : _d.getElement()) === null || _e === void 0 ? void 0 : _e.getBoundingClientRect();
32
+ if (bb) {
33
+ return {
34
+ intend,
35
+ top: bb.top,
36
+ left: bb.left,
37
+ right: bb.right,
38
+ };
39
+ }
40
+ return null;
41
+ } })),
42
+ createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { getProps: () => {
43
+ var _a, _b, _c;
44
+ 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: item.getMemoizedProp("dnd/onDragStart", () => (e) => {
45
+ var _a, _b, _c;
46
+ const selectedItems = tree.getSelectedItems();
47
+ const items = selectedItems.includes(item) ? selectedItems : [item];
48
+ const config = tree.getConfig();
49
+ if (!selectedItems.includes(item)) {
50
+ tree.setSelectedItems([item.getItemMeta().itemId]);
51
+ }
52
+ if (!((_b = (_a = config.canDrag) === null || _a === void 0 ? void 0 : _a.call(config, items)) !== null && _b !== void 0 ? _b : true)) {
53
+ e.preventDefault();
54
+ return;
55
+ }
56
+ if (config.createForeignDragObject) {
57
+ const { format, data } = config.createForeignDragObject(items);
58
+ (_c = e.dataTransfer) === null || _c === void 0 ? void 0 : _c.setData(format, data);
59
+ }
60
+ tree.applySubStateUpdate("dnd", {
61
+ draggedItems: items,
62
+ draggingOverItem: tree.getFocusedItem(),
63
+ });
64
+ }), onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => {
65
+ var _a, _b, _c;
66
+ const target = getDropTarget(e, item, tree);
67
+ const dataRef = tree.getDataRef();
68
+ if (!((_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) &&
69
+ !((_c = (_b = tree.getConfig()).canDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(_b, e.dataTransfer, target))) {
70
+ return;
71
+ }
72
+ if (!canDrop(e.dataTransfer, target, tree)) {
73
+ return;
74
+ }
75
+ e.preventDefault();
76
+ const nextDragCode = getDragCode(target);
77
+ if (nextDragCode === dataRef.current.lastDragCode) {
78
+ return;
79
+ }
80
+ dataRef.current.lastDragCode = nextDragCode;
81
+ tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
82
+ }), onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => {
83
+ const dataRef = tree.getDataRef();
84
+ dataRef.current.lastDragCode = "no-drag";
85
+ tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
86
+ }), onDragEnd: item.getMemoizedProp("dnd/onDragEnd", () => (e) => {
87
+ var _a, _b, _c;
88
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
89
+ tree.applySubStateUpdate("dnd", null);
90
+ if (e.dataTransfer.dropEffect === "none" || !draggedItems) {
91
+ return;
92
+ }
93
+ (_c = (_b = tree.getConfig()).onCompleteForeignDrop) === null || _c === void 0 ? void 0 : _c.call(_b, draggedItems);
94
+ }), onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => {
95
+ var _a, _b, _c;
96
+ const dataRef = tree.getDataRef();
97
+ const target = getDropTarget(e, item, tree);
98
+ if (!canDrop(e.dataTransfer, target, tree)) {
99
+ return;
100
+ }
101
+ e.preventDefault();
102
+ const config = tree.getConfig();
103
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
104
+ dataRef.current.lastDragCode = undefined;
105
+ tree.applySubStateUpdate("dnd", null);
106
+ if (draggedItems) {
107
+ (_b = config.onDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target);
108
+ }
109
+ else {
110
+ (_c = config.onDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(config, e.dataTransfer, target);
111
+ }
112
+ // TODO rebuild tree?
113
+ }) }));
114
+ }, isDropTarget: () => {
115
+ const target = tree.getDropTarget();
116
+ return target ? target.item.getId() === item.getId() : false;
117
+ }, isDropTargetAbove: () => {
118
+ const target = tree.getDropTarget();
119
+ if (!target ||
120
+ target.childIndex === null ||
121
+ target.item !== item.getParent())
122
+ return false;
123
+ return target.childIndex === item.getItemMeta().posInSet;
124
+ }, isDropTargetBelow: () => {
125
+ const target = tree.getDropTarget();
126
+ if (!target ||
127
+ target.childIndex === null ||
128
+ target.item !== item.getParent())
129
+ return false;
130
+ return target.childIndex - 1 === item.getItemMeta().posInSet;
131
+ }, isDraggingOver: () => {
132
+ var _a, _b;
133
+ return ((_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggingOverItem) === null || _b === void 0 ? void 0 : _b.getId()) === item.getId();
134
+ } })),
135
+ };
@@ -0,0 +1,69 @@
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 DragLineData = {
11
+ intend: number;
12
+ top: number;
13
+ left: number;
14
+ right: number;
15
+ };
16
+ export type DropTarget<T> = {
17
+ item: ItemInstance<T>;
18
+ childIndex: number;
19
+ insertionIndex: number;
20
+ } | {
21
+ item: ItemInstance<T>;
22
+ childIndex: null;
23
+ insertionIndex: null;
24
+ };
25
+ export declare enum DropTargetPosition {
26
+ Top = "top",
27
+ Bottom = "bottom",
28
+ Item = "item"
29
+ }
30
+ export type DragAndDropFeatureDef<T> = {
31
+ state: {
32
+ dnd?: DndState<T> | null;
33
+ };
34
+ config: {
35
+ setDndState?: SetStateFn<DndState<T> | null>;
36
+ topLinePercentage?: number;
37
+ bottomLinePercentage?: number;
38
+ canDropInbetween?: boolean;
39
+ isItemDraggable?: (item: ItemInstance<T>) => boolean;
40
+ canDrag?: (items: ItemInstance<T>[]) => boolean;
41
+ canDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => boolean;
42
+ createForeignDragObject?: (items: ItemInstance<T>[]) => {
43
+ format: string;
44
+ data: any;
45
+ };
46
+ canDropForeignDragObject?: (dataTransfer: DataTransfer, target: DropTarget<T>) => boolean;
47
+ onDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => void;
48
+ onDropForeignDragObject?: (dataTransfer: DataTransfer, target: DropTarget<T>) => void;
49
+ /** Runs in the onDragEnd event, if `ev.dataTransfer.dropEffect` is not `none`, i.e. the drop
50
+ * was not aborted. No target is provided as parameter since the target may be a foreign drop target.
51
+ * This is useful to seperate out the logic to move dragged items out of their previous parents.
52
+ * Use `onDrop` to handle drop-related logic.
53
+ *
54
+ * This ignores the `canDrop` handler, since the drop target is unknown in this handler.
55
+ */
56
+ onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
57
+ };
58
+ treeInstance: {
59
+ getDropTarget: () => DropTarget<T> | null;
60
+ getDragLineData: () => DragLineData | null;
61
+ };
62
+ itemInstance: {
63
+ isDropTarget: () => boolean;
64
+ isDropTargetAbove: () => boolean;
65
+ isDropTargetBelow: () => boolean;
66
+ isDraggingOver: () => boolean;
67
+ };
68
+ hotkeys: never;
69
+ };
@@ -0,0 +1,6 @@
1
+ export var DropTargetPosition;
2
+ (function (DropTargetPosition) {
3
+ DropTargetPosition["Top"] = "top";
4
+ DropTargetPosition["Bottom"] = "bottom";
5
+ DropTargetPosition["Item"] = "item";
6
+ })(DropTargetPosition || (DropTargetPosition = {}));
@@ -0,0 +1,6 @@
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>, canDropInbetween?: boolean | undefined) => DropTarget<any>;
@@ -0,0 +1,72 @@
1
+ import { DropTargetPosition, } from "./types";
2
+ export const getDragCode = ({ item, childIndex }) => `${item.getId()}__${childIndex !== null && childIndex !== void 0 ? childIndex : "none"}`;
3
+ export const getDropOffset = (e, item) => {
4
+ var _a;
5
+ const bb = (_a = item.getElement()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
6
+ return bb ? (e.pageY - bb.top) / bb.height : 0.5;
7
+ };
8
+ export const canDrop = (dataTransfer, target, tree) => {
9
+ var _a, _b, _c, _d;
10
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
11
+ const config = tree.getConfig();
12
+ if (draggedItems && !((_c = (_b = config.canDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target)) !== null && _c !== void 0 ? _c : true)) {
13
+ return false;
14
+ }
15
+ if (!draggedItems &&
16
+ dataTransfer &&
17
+ !((_d = config.canDropForeignDragObject) === null || _d === void 0 ? void 0 : _d.call(config, dataTransfer, target))) {
18
+ return false;
19
+ }
20
+ return true;
21
+ };
22
+ const getDropTargetPosition = (offset, topLinePercentage, bottomLinePercentage) => {
23
+ if (offset < topLinePercentage) {
24
+ return DropTargetPosition.Top;
25
+ }
26
+ if (offset > bottomLinePercentage) {
27
+ return DropTargetPosition.Bottom;
28
+ }
29
+ return DropTargetPosition.Item;
30
+ };
31
+ export const getDropTarget = (e, item, tree, canDropInbetween = tree.getConfig().canDropInbetween) => {
32
+ var _a, _b, _c, _d;
33
+ const config = tree.getConfig();
34
+ const draggedItems = (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) !== null && _b !== void 0 ? _b : [];
35
+ const itemTarget = { item, childIndex: null, insertionIndex: null };
36
+ const parentTarget = {
37
+ item: item.getParent(),
38
+ childIndex: null,
39
+ insertionIndex: null,
40
+ };
41
+ if (!canDropInbetween) {
42
+ if (!canDrop(e.dataTransfer, parentTarget, tree)) {
43
+ return getDropTarget(e, item.getParent(), tree, false);
44
+ }
45
+ return itemTarget;
46
+ }
47
+ const canDropInside = canDrop(e.dataTransfer, itemTarget, tree);
48
+ const offset = getDropOffset(e, item);
49
+ const pos = canDropInside
50
+ ? getDropTargetPosition(offset, (_c = config.topLinePercentage) !== null && _c !== void 0 ? _c : 0.3, (_d = config.bottomLinePercentage) !== null && _d !== void 0 ? _d : 0.7)
51
+ : getDropTargetPosition(offset, 0.5, 0.5);
52
+ if (pos === DropTargetPosition.Item) {
53
+ return itemTarget;
54
+ }
55
+ if (!canDrop(e.dataTransfer, parentTarget, tree)) {
56
+ return getDropTarget(e, item.getParent(), tree, false);
57
+ }
58
+ const childIndex = item.getIndexInParent() + (pos === DropTargetPosition.Top ? 0 : 1);
59
+ const numberOfDragItemsBeforeTarget = item
60
+ .getParent()
61
+ .getChildren()
62
+ .slice(0, childIndex)
63
+ .reduce((counter, child) => child && (draggedItems === null || draggedItems === void 0 ? void 0 : draggedItems.some((i) => i.getId() === child.getId()))
64
+ ? ++counter
65
+ : counter, 0);
66
+ return {
67
+ item: item.getParent(),
68
+ childIndex,
69
+ // TODO performance could be improved by computing this only when dragcode changed
70
+ insertionIndex: childIndex - numberOfDragItemsBeforeTarget,
71
+ };
72
+ };
@@ -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>;
@@ -0,0 +1,38 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { poll } from "../../utils";
11
+ export const expandAllFeature = {
12
+ key: "expand-all",
13
+ createTreeInstance: (prev, tree) => (Object.assign(Object.assign({}, prev), { expandAll: (cancelToken) => __awaiter(void 0, void 0, void 0, function* () {
14
+ yield Promise.all(tree.getItems().map((item) => item.expandAll(cancelToken)));
15
+ }), collapseAll: () => {
16
+ tree.applySubStateUpdate("expandedItems", []);
17
+ tree.rebuildTree();
18
+ } })),
19
+ createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { expandAll: (cancelToken) => __awaiter(void 0, void 0, void 0, function* () {
20
+ if (cancelToken === null || cancelToken === void 0 ? void 0 : cancelToken.current) {
21
+ return;
22
+ }
23
+ if (!item.isFolder()) {
24
+ return;
25
+ }
26
+ item.expand();
27
+ yield poll(() => !tree.getState().loadingItems.includes(item.getId()));
28
+ yield Promise.all(item.getChildren().map((child) => __awaiter(void 0, void 0, void 0, function* () {
29
+ yield poll(() => !tree.getState().loadingItems.includes(child.getId()));
30
+ yield (child === null || child === void 0 ? void 0 : child.expandAll(cancelToken));
31
+ })));
32
+ }), collapseAll: () => {
33
+ for (const child of item.getChildren()) {
34
+ child === null || child === void 0 ? void 0 : child.collapseAll();
35
+ }
36
+ item.collapse();
37
+ } })),
38
+ };
@@ -0,0 +1,17 @@
1
+ export type ExpandAllFeatureDef = {
2
+ state: {};
3
+ config: {};
4
+ treeInstance: {
5
+ expandAll: (cancelToken?: {
6
+ current: boolean;
7
+ }) => Promise<void>;
8
+ collapseAll: () => void;
9
+ };
10
+ itemInstance: {
11
+ expandAll: (cancelToken?: {
12
+ current: boolean;
13
+ }) => Promise<void>;
14
+ collapseAll: () => void;
15
+ };
16
+ hotkeys: never;
17
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,4 @@
1
+ import { FeatureImplementation } from "../../types/core";
2
+ import { HotkeysCoreFeatureDef } from "./types";
3
+ import { MainFeatureDef } from "../main/types";
4
+ export declare const hotkeysCoreFeature: FeatureImplementation<any, HotkeysCoreFeatureDef<any>, MainFeatureDef | HotkeysCoreFeatureDef<any>>;