@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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @headless-tree/core
2
2
 
3
+ ## 0.0.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 6ec53b3: dev release
8
+
9
+ ## 0.0.6
10
+
11
+ ### Patch Changes
12
+
13
+ - bc9c446: dev release
14
+
3
15
  ## 0.0.5
4
16
 
5
17
  ### Patch Changes
@@ -10,12 +10,35 @@ const buildItemInstance = (features, tree, itemId) => {
10
10
  }
11
11
  return itemInstance;
12
12
  };
13
+ const verifyFeatures = (features) => {
14
+ var _a;
15
+ const loadedFeatures = features === null || features === void 0 ? void 0 : features.map((feature) => feature.key);
16
+ for (const feature of features !== null && features !== void 0 ? features : []) {
17
+ const missingDependency = (_a = feature.deps) === null || _a === void 0 ? void 0 : _a.find((dep) => !(loadedFeatures === null || loadedFeatures === void 0 ? void 0 : loadedFeatures.includes(dep)));
18
+ if (missingDependency) {
19
+ throw new Error(`${feature.key} needs ${missingDependency}`);
20
+ }
21
+ }
22
+ };
23
+ const compareFeatures = (feature1, feature2) => {
24
+ var _a;
25
+ if (feature2.key && ((_a = feature1.overwrites) === null || _a === void 0 ? void 0 : _a.includes(feature2.key))) {
26
+ return 1;
27
+ }
28
+ return -1;
29
+ };
30
+ const sortFeatures = (features = []) => features.sort(compareFeatures);
13
31
  const createTree = (initialConfig) => {
14
- var _a, _b, _c, _d, _e, _f;
32
+ var _a, _b, _c, _d, _e;
15
33
  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; }, (_c = (_b = initialConfig.initialState) !== null && _b !== void 0 ? _b : initialConfig.state) !== null && _c !== void 0 ? _c : {});
34
+ const additionalFeatures = [
35
+ feature_1.treeFeature,
36
+ ...sortFeatures(initialConfig.features),
37
+ ];
38
+ verifyFeatures(additionalFeatures);
39
+ 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 : {});
18
40
  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);
41
+ const stateHandlerNames = additionalFeatures.reduce((acc, feature) => (Object.assign(Object.assign({}, acc), feature.stateHandlerNames)), {});
19
42
  let treeElement;
20
43
  const treeDataRef = { current: {} };
21
44
  const itemInstancesMap = {};
@@ -60,10 +83,13 @@ const createTree = (initialConfig) => {
60
83
  key: "main",
61
84
  createTreeInstance: (prev) => (Object.assign(Object.assign({}, prev), { getState: () => state, setState: (updater) => {
62
85
  var _a;
63
- state = typeof updater === "function" ? updater(state) : updater;
86
+ // Not necessary, since I think the subupdate below keeps the state fresh anyways?
87
+ // state = typeof updater === "function" ? updater(state) : updater;
64
88
  (_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); });
89
+ }, applySubStateUpdate: (stateName, updater) => {
90
+ state[stateName] =
91
+ typeof updater === "function" ? updater(state[stateName]) : updater;
92
+ config[stateHandlerNames[stateName]](state[stateName]);
67
93
  }, rebuildTree: () => {
68
94
  var _a;
69
95
  rebuildItemMeta(mainFeature);
@@ -72,10 +98,7 @@ const createTree = (initialConfig) => {
72
98
  config = typeof updater === "function" ? updater(config) : updater;
73
99
  if (config.state) {
74
100
  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
101
  }
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
102
  }, getItemInstance: (itemId) => itemInstancesMap[itemId], getItems: () => itemInstances, registerElement: (element) => {
80
103
  if (treeElement === element) {
81
104
  return;
@@ -104,11 +127,10 @@ const createTree = (initialConfig) => {
104
127
  // eslint-disable-next-line no-return-assign
105
128
  getDataRef: () => { var _a; return ((_a = itemDataRefs[itemId]) !== null && _a !== void 0 ? _a : (itemDataRefs[itemId] = { current: {} })); }, getItemMeta: () => itemMetaMap[itemId] })),
106
129
  };
107
- // todo sort features
108
130
  const features = [mainFeature, ...additionalFeatures];
109
131
  for (const feature of features) {
110
- Object.assign(treeInstance, (_e = (_d = feature.createTreeInstance) === null || _d === void 0 ? void 0 : _d.call(feature, Object.assign({}, treeInstance), treeInstance)) !== null && _e !== void 0 ? _e : {});
111
- Object.assign(hotkeyPresets, (_f = feature.hotkeys) !== null && _f !== void 0 ? _f : {});
132
+ 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 : {});
133
+ Object.assign(hotkeyPresets, (_e = feature.hotkeys) !== null && _e !== void 0 ? _e : {});
112
134
  }
113
135
  rebuildItemMeta(mainFeature);
114
136
  return treeInstance;
@@ -4,46 +4,54 @@ exports.asyncDataLoaderFeature = void 0;
4
4
  const utils_1 = require("../../utils");
5
5
  exports.asyncDataLoaderFeature = {
6
6
  key: "async-data-loader",
7
- dependingFeatures: ["main"],
8
7
  getInitialState: (initialState) => (Object.assign({ loadingItems: [] }, initialState)),
9
8
  getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItems: (0, utils_1.makeStateUpdater)("loadingItems", tree) }, defaultConfig)),
9
+ stateHandlerNames: {
10
+ loadingItems: "setLoadingItems",
11
+ },
10
12
  createTreeInstance: (prev, instance) => (Object.assign(Object.assign({}, prev), { retrieveItemData: (itemId) => {
11
- var _a, _b, _c, _d, _e, _f;
12
- var _g, _h;
13
+ var _a, _b, _c, _d, _e;
14
+ var _f, _g;
13
15
  const config = instance.getConfig();
14
16
  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
+ (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
18
+ (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
17
19
  if (dataRef.current.itemData[itemId]) {
18
20
  return dataRef.current.itemData[itemId];
19
21
  }
20
22
  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;
23
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => [
24
+ ...loadingItems,
25
+ itemId,
26
+ ]);
27
+ (_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getItem(itemId).then((item) => {
28
+ var _a;
24
29
  dataRef.current.itemData[itemId] = item;
25
30
  (_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));
31
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
27
32
  });
28
33
  }
29
- return (_f = (_e = config.createLoadingItemData) === null || _e === void 0 ? void 0 : _e.call(config)) !== null && _f !== void 0 ? _f : null;
34
+ return (_e = (_d = config.createLoadingItemData) === null || _d === void 0 ? void 0 : _d.call(config)) !== null && _e !== void 0 ? _e : null;
30
35
  }, retrieveChildrenIds: (itemId) => {
31
- var _a, _b, _c, _d, _e, _f;
32
- var _g, _h;
36
+ var _a, _b, _c, _d, _e;
37
+ var _f, _g;
33
38
  const config = instance.getConfig();
34
39
  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 = {});
40
+ (_a = (_f = dataRef.current).itemData) !== null && _a !== void 0 ? _a : (_f.itemData = {});
41
+ (_b = (_g = dataRef.current).childrenIds) !== null && _b !== void 0 ? _b : (_g.childrenIds = {});
37
42
  if (dataRef.current.childrenIds[itemId]) {
38
43
  return dataRef.current.childrenIds[itemId];
39
44
  }
40
45
  if (instance.getState().loadingItems.includes(itemId)) {
41
46
  return [];
42
47
  }
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;
48
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => [
49
+ ...loadingItems,
50
+ itemId,
51
+ ]);
52
+ if ((_c = config.asyncDataLoader) === null || _c === void 0 ? void 0 : _c.getChildrenWithData) {
53
+ (_d = config.asyncDataLoader) === null || _d === void 0 ? void 0 : _d.getChildrenWithData(itemId).then((children) => {
54
+ var _a, _b;
47
55
  for (const { id, data } of children) {
48
56
  dataRef.current.itemData[id] = data;
49
57
  (_a = config.onLoadedItem) === null || _a === void 0 ? void 0 : _a.call(config, id, data);
@@ -51,16 +59,16 @@ exports.asyncDataLoaderFeature = {
51
59
  const childrenIds = children.map(({ id }) => id);
52
60
  dataRef.current.childrenIds[itemId] = childrenIds;
53
61
  (_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));
62
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
55
63
  instance.rebuildTree();
56
64
  });
57
65
  }
58
66
  else {
59
- (_f = config.asyncDataLoader) === null || _f === void 0 ? void 0 : _f.getChildren(itemId).then((childrenIds) => {
60
- var _a, _b;
67
+ (_e = config.asyncDataLoader) === null || _e === void 0 ? void 0 : _e.getChildren(itemId).then((childrenIds) => {
68
+ var _a;
61
69
  dataRef.current.childrenIds[itemId] = childrenIds;
62
70
  (_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));
71
+ instance.applySubStateUpdate("loadingItems", (loadingItems) => loadingItems.filter((id) => id !== itemId));
64
72
  instance.rebuildTree();
65
73
  });
66
74
  }
@@ -5,16 +5,47 @@ const utils_1 = require("./utils");
5
5
  const utils_2 = require("../../utils");
6
6
  exports.dragAndDropFeature = {
7
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)),
8
+ deps: ["selection"],
9
+ getDefaultConfig: (defaultConfig, tree) => (Object.assign({ canDrop: (_, target) => target.item.isFolder(), canDropForeignDragObject: () => false, setDndState: (0, utils_2.makeStateUpdater)("dnd", tree) }, defaultConfig)),
10
+ stateHandlerNames: {
11
+ dnd: "setDndState",
12
+ },
10
13
  createTreeInstance: (prev, tree) => (Object.assign(Object.assign({}, prev), { getDropTarget: () => {
11
14
  var _a, _b;
12
15
  return (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.dragTarget) !== null && _b !== void 0 ? _b : null;
16
+ }, getDragLineData: () => {
17
+ var _a, _b, _c, _d, _e;
18
+ const target = tree.getDropTarget();
19
+ const intend = ((_a = target === null || target === void 0 ? void 0 : target.item.getItemMeta().level) !== null && _a !== void 0 ? _a : 0) + 1;
20
+ if (!target || target.childIndex === null)
21
+ return null;
22
+ const children = target.item.getChildren();
23
+ if (target.childIndex === children.length) {
24
+ const bb = (_c = (_b = children[target.childIndex - 1]) === null || _b === void 0 ? void 0 : _b.getElement()) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect();
25
+ if (bb) {
26
+ return {
27
+ intend,
28
+ top: bb.bottom,
29
+ left: bb.left,
30
+ right: bb.right,
31
+ };
32
+ }
33
+ }
34
+ const bb = (_e = (_d = children[target.childIndex]) === null || _d === void 0 ? void 0 : _d.getElement()) === null || _e === void 0 ? void 0 : _e.getBoundingClientRect();
35
+ if (bb) {
36
+ return {
37
+ intend,
38
+ top: bb.top,
39
+ left: bb.left,
40
+ right: bb.right,
41
+ };
42
+ }
43
+ return null;
13
44
  } })),
14
45
  createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { getProps: () => {
15
46
  var _a, _b, _c;
16
47
  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) => {
17
- var _a, _b, _c, _d, _e;
48
+ var _a, _b, _c;
18
49
  const selectedItems = tree.getSelectedItems();
19
50
  const items = selectedItems.includes(item) ? selectedItems : [item];
20
51
  const config = tree.getConfig();
@@ -29,12 +60,12 @@ exports.dragAndDropFeature = {
29
60
  const { format, data } = config.createForeignDragObject(items);
30
61
  (_c = e.dataTransfer) === null || _c === void 0 ? void 0 : _c.setData(format, data);
31
62
  }
32
- (_e = (_d = tree.getConfig()).setDndState) === null || _e === void 0 ? void 0 : _e.call(_d, {
63
+ tree.applySubStateUpdate("dnd", {
33
64
  draggedItems: items,
34
65
  draggingOverItem: tree.getFocusedItem(),
35
66
  });
36
67
  }), onDragOver: item.getMemoizedProp("dnd/onDragOver", () => (e) => {
37
- var _a, _b, _c, _d, _e;
68
+ var _a, _b, _c;
38
69
  const target = (0, utils_1.getDropTarget)(e, item, tree);
39
70
  const dataRef = tree.getDataRef();
40
71
  if (!((_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) &&
@@ -50,14 +81,21 @@ exports.dragAndDropFeature = {
50
81
  return;
51
82
  }
52
83
  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 })));
84
+ tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { dragTarget: target, draggingOverItem: item })));
54
85
  }), onDragLeave: item.getMemoizedProp("dnd/onDragLeave", () => () => {
55
- var _a, _b;
56
86
  const dataRef = tree.getDataRef();
57
87
  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 })));
88
+ tree.applySubStateUpdate("dnd", (state) => (Object.assign(Object.assign({}, state), { draggingOverItem: undefined, dragTarget: undefined })));
89
+ }), onDragEnd: item.getMemoizedProp("dnd/onDragEnd", () => (e) => {
90
+ var _a, _b, _c;
91
+ const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
92
+ tree.applySubStateUpdate("dnd", null);
93
+ if (e.dataTransfer.dropEffect === "none" || !draggedItems) {
94
+ return;
95
+ }
96
+ (_c = (_b = tree.getConfig()).onCompleteForeignDrop) === null || _c === void 0 ? void 0 : _c.call(_b, draggedItems);
59
97
  }), onDrop: item.getMemoizedProp("dnd/onDrop", () => (e) => {
60
- var _a, _b, _c, _d, _e;
98
+ var _a, _b, _c;
61
99
  const dataRef = tree.getDataRef();
62
100
  const target = (0, utils_1.getDropTarget)(e, item, tree);
63
101
  if (!(0, utils_1.canDrop)(e.dataTransfer, target, tree)) {
@@ -67,12 +105,12 @@ exports.dragAndDropFeature = {
67
105
  const config = tree.getConfig();
68
106
  const draggedItems = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems;
69
107
  dataRef.current.lastDragCode = undefined;
70
- (_c = (_b = tree.getConfig()).setDndState) === null || _c === void 0 ? void 0 : _c.call(_b, null);
108
+ tree.applySubStateUpdate("dnd", null);
71
109
  if (draggedItems) {
72
- (_d = config.onDrop) === null || _d === void 0 ? void 0 : _d.call(config, draggedItems, target);
110
+ (_b = config.onDrop) === null || _b === void 0 ? void 0 : _b.call(config, draggedItems, target);
73
111
  }
74
112
  else {
75
- (_e = config.onDropForeignDragObject) === null || _e === void 0 ? void 0 : _e.call(config, e.dataTransfer, target);
113
+ (_c = config.onDropForeignDragObject) === null || _c === void 0 ? void 0 : _c.call(config, e.dataTransfer, target);
76
114
  }
77
115
  // TODO rebuild tree?
78
116
  }) }));
@@ -81,16 +119,18 @@ exports.dragAndDropFeature = {
81
119
  return target ? target.item.getId() === item.getId() : false;
82
120
  }, isDropTargetAbove: () => {
83
121
  const target = tree.getDropTarget();
84
- if (!target || target.childIndex === null)
122
+ if (!target ||
123
+ target.childIndex === null ||
124
+ target.item !== item.getParent())
85
125
  return false;
86
- const targetIndex = target.item.getItemMeta().index;
87
- return targetIndex + target.childIndex + 1 === item.getItemMeta().index;
126
+ return target.childIndex === item.getItemMeta().posInSet;
88
127
  }, isDropTargetBelow: () => {
89
128
  const target = tree.getDropTarget();
90
- if (!target || target.childIndex === null)
129
+ if (!target ||
130
+ target.childIndex === null ||
131
+ target.item !== item.getParent())
91
132
  return false;
92
- const targetIndex = target.item.getItemMeta().index;
93
- return targetIndex + target.childIndex === item.getItemMeta().index;
133
+ return target.childIndex - 1 === item.getItemMeta().posInSet;
94
134
  }, isDraggingOver: () => {
95
135
  var _a, _b;
96
136
  return ((_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggingOverItem) === null || _b === void 0 ? void 0 : _b.getId()) === item.getId();
@@ -7,9 +7,20 @@ export type DndState<T> = {
7
7
  draggingOverItem?: ItemInstance<T>;
8
8
  dragTarget?: DropTarget<T>;
9
9
  };
10
+ export type DragLineData = {
11
+ intend: number;
12
+ top: number;
13
+ left: number;
14
+ right: number;
15
+ };
10
16
  export type DropTarget<T> = {
11
17
  item: ItemInstance<T>;
12
- childIndex: number | null;
18
+ childIndex: number;
19
+ insertionIndex: number;
20
+ } | {
21
+ item: ItemInstance<T>;
22
+ childIndex: null;
23
+ insertionIndex: null;
13
24
  };
14
25
  export declare enum DropTargetPosition {
15
26
  Top = "top",
@@ -35,9 +46,18 @@ export type DragAndDropFeatureDef<T> = {
35
46
  canDropForeignDragObject?: (dataTransfer: DataTransfer, target: DropTarget<T>) => boolean;
36
47
  onDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => void;
37
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;
38
57
  };
39
58
  treeInstance: {
40
59
  getDropTarget: () => DropTarget<T> | null;
60
+ getDragLineData: () => DragLineData | null;
41
61
  };
42
62
  itemInstance: {
43
63
  isDropTarget: () => boolean;
@@ -3,4 +3,4 @@ import { DropTarget } from "./types";
3
3
  export declare const getDragCode: ({ item, childIndex }: DropTarget<any>) => string;
4
4
  export declare const getDropOffset: (e: any, item: ItemInstance<any>) => number;
5
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>;
6
+ export declare const getDropTarget: (e: any, item: ItemInstance<any>, tree: TreeInstance<any>, canDropInbetween?: boolean | undefined) => DropTarget<any>;
@@ -34,29 +34,46 @@ const getDropTargetPosition = (offset, topLinePercentage, bottomLinePercentage)
34
34
  }
35
35
  return types_1.DropTargetPosition.Item;
36
36
  };
37
- const getDropTarget = (e, item, tree) => {
38
- var _a, _b;
37
+ const getDropTarget = (e, item, tree, canDropInbetween = tree.getConfig().canDropInbetween) => {
38
+ var _a, _b, _c, _d;
39
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
- };
40
+ const draggedItems = (_b = (_a = tree.getState().dnd) === null || _a === void 0 ? void 0 : _a.draggedItems) !== null && _b !== void 0 ? _b : [];
41
+ const itemTarget = { item, childIndex: null, insertionIndex: null };
42
+ const parentTarget = {
43
+ item: item.getParent(),
44
+ childIndex: null,
45
+ insertionIndex: null,
46
+ };
47
+ if (!canDropInbetween) {
48
+ if (!(0, exports.canDrop)(e.dataTransfer, parentTarget, tree)) {
49
+ return (0, exports.getDropTarget)(e, item.getParent(), tree, false);
50
+ }
51
+ return itemTarget;
53
52
  }
53
+ const canDropInside = (0, exports.canDrop)(e.dataTransfer, itemTarget, tree);
54
+ const offset = (0, exports.getDropOffset)(e, item);
55
+ const pos = canDropInside
56
+ ? getDropTargetPosition(offset, (_c = config.topLinePercentage) !== null && _c !== void 0 ? _c : 0.3, (_d = config.bottomLinePercentage) !== null && _d !== void 0 ? _d : 0.7)
57
+ : getDropTargetPosition(offset, 0.5, 0.5);
54
58
  if (pos === types_1.DropTargetPosition.Item) {
55
- return dropOnItemTarget;
59
+ return itemTarget;
60
+ }
61
+ if (!(0, exports.canDrop)(e.dataTransfer, parentTarget, tree)) {
62
+ return (0, exports.getDropTarget)(e, item.getParent(), tree, false);
56
63
  }
64
+ const childIndex = item.getIndexInParent() + (pos === types_1.DropTargetPosition.Top ? 0 : 1);
65
+ const numberOfDragItemsBeforeTarget = item
66
+ .getParent()
67
+ .getChildren()
68
+ .slice(0, childIndex)
69
+ .reduce((counter, child) => child && (draggedItems === null || draggedItems === void 0 ? void 0 : draggedItems.some((i) => i.getId() === child.getId()))
70
+ ? ++counter
71
+ : counter, 0);
57
72
  return {
58
73
  item: item.getParent(),
59
- childIndex: item.getIndexInParent() + (pos === types_1.DropTargetPosition.Top ? 0 : 1),
74
+ childIndex,
75
+ // TODO performance could be improved by computing this only when dragcode changed
76
+ insertionIndex: childIndex - numberOfDragItemsBeforeTarget,
60
77
  };
61
78
  };
62
79
  exports.getDropTarget = getDropTarget;
@@ -13,27 +13,29 @@ exports.expandAllFeature = void 0;
13
13
  const utils_1 = require("../../utils");
14
14
  exports.expandAllFeature = {
15
15
  key: "expand-all",
16
- dependingFeatures: ["main", "tree"],
17
16
  createTreeInstance: (prev, tree) => (Object.assign(Object.assign({}, prev), { expandAll: (cancelToken) => __awaiter(void 0, void 0, void 0, function* () {
18
17
  yield Promise.all(tree.getItems().map((item) => item.expandAll(cancelToken)));
19
- }), collapseAll: () => __awaiter(void 0, void 0, void 0, function* () {
20
- var _a, _b;
21
- (_b = (_a = tree.getConfig()).setExpandedItems) === null || _b === void 0 ? void 0 : _b.call(_a, []);
22
- }) })),
18
+ }), collapseAll: () => {
19
+ tree.applySubStateUpdate("expandedItems", []);
20
+ tree.rebuildTree();
21
+ } })),
23
22
  createItemInstance: (prev, item, tree) => (Object.assign(Object.assign({}, prev), { expandAll: (cancelToken) => __awaiter(void 0, void 0, void 0, function* () {
24
23
  if (cancelToken === null || cancelToken === void 0 ? void 0 : cancelToken.current) {
25
24
  return;
26
25
  }
26
+ if (!item.isFolder()) {
27
+ return;
28
+ }
27
29
  item.expand();
28
30
  yield (0, utils_1.poll)(() => !tree.getState().loadingItems.includes(item.getId()));
29
31
  yield Promise.all(item.getChildren().map((child) => __awaiter(void 0, void 0, void 0, function* () {
30
32
  yield (0, utils_1.poll)(() => !tree.getState().loadingItems.includes(child.getId()));
31
33
  yield (child === null || child === void 0 ? void 0 : child.expandAll(cancelToken));
32
34
  })));
33
- }), collapseAll: () => __awaiter(void 0, void 0, void 0, function* () {
34
- yield Promise.all(item.getChildren().map((child) => __awaiter(void 0, void 0, void 0, function* () {
35
- yield (child === null || child === void 0 ? void 0 : child.collapseAll());
36
- })));
35
+ }), collapseAll: () => {
36
+ for (const child of item.getChildren()) {
37
+ child === null || child === void 0 ? void 0 : child.collapseAll();
38
+ }
37
39
  item.collapse();
38
- }) })),
40
+ } })),
39
41
  };
@@ -5,13 +5,13 @@ export type ExpandAllFeatureDef = {
5
5
  expandAll: (cancelToken?: {
6
6
  current: boolean;
7
7
  }) => Promise<void>;
8
- collapseAll: () => Promise<void>;
8
+ collapseAll: () => void;
9
9
  };
10
10
  itemInstance: {
11
11
  expandAll: (cancelToken?: {
12
12
  current: boolean;
13
13
  }) => Promise<void>;
14
- collapseAll: () => Promise<void>;
14
+ collapseAll: () => void;
15
15
  };
16
16
  hotkeys: never;
17
17
  };
@@ -20,7 +20,6 @@ const findHotkeyMatch = (pressedKeys, tree, config1, config2) => {
20
20
  };
21
21
  exports.hotkeysCoreFeature = {
22
22
  key: "hotkeys-core",
23
- dependingFeatures: ["main", "tree"],
24
23
  onTreeMount: (tree, element) => {
25
24
  const data = tree.getDataRef();
26
25
  const keydown = (e) => {
@@ -1,4 +1,4 @@
1
- import { FeatureImplementation, HotkeysConfig, ItemInstance, SetStateFn, TreeConfig, TreeState } from "../../types/core";
1
+ import { FeatureImplementation, HotkeysConfig, ItemInstance, SetStateFn, TreeConfig, TreeState, Updater } from "../../types/core";
2
2
  import { ItemMeta } from "../tree/types";
3
3
  export type MainFeatureDef<T = any> = {
4
4
  state: {};
@@ -9,6 +9,8 @@ export type MainFeatureDef<T = any> = {
9
9
  setState?: SetStateFn<TreeState<T>>;
10
10
  };
11
11
  treeInstance: {
12
+ /** @internal */
13
+ applySubStateUpdate: <K extends keyof TreeState<any>>(stateName: K, updater: Updater<TreeState<T>[K]>) => void;
12
14
  setState: SetStateFn<TreeState<T>>;
13
15
  getState: () => TreeState<T>;
14
16
  setConfig: SetStateFn<TreeConfig<T>>;
@@ -4,38 +4,37 @@ exports.renamingFeature = void 0;
4
4
  const utils_1 = require("../../utils");
5
5
  exports.renamingFeature = {
6
6
  key: "renaming",
7
- dependingFeatures: ["main", "tree"],
8
7
  getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setRenamingItem: (0, utils_1.makeStateUpdater)("renamingItem", tree), setRenamingValue: (0, utils_1.makeStateUpdater)("renamingValue", tree), canRename: () => true }, defaultConfig)),
8
+ stateHandlerNames: {
9
+ renamingItem: "setRenamingItem",
10
+ renamingValue: "setRenamingValue",
11
+ },
9
12
  createTreeInstance: (prev, instance) => (Object.assign(Object.assign({}, prev), { startRenamingItem: (itemId) => {
10
- var _a, _b;
11
- const config = instance.getConfig();
12
13
  const item = instance.getItemInstance(itemId);
13
14
  if (!item.canRename()) {
14
15
  return;
15
16
  }
16
- (_a = config.setRenamingItem) === null || _a === void 0 ? void 0 : _a.call(config, itemId);
17
- (_b = config.setRenamingValue) === null || _b === void 0 ? void 0 : _b.call(config, item.getItemName());
17
+ instance.applySubStateUpdate("renamingItem", itemId);
18
+ instance.applySubStateUpdate("renamingValue", item.getItemName());
18
19
  }, getRenamingItem: () => {
19
20
  const itemId = instance.getState().renamingItem;
20
21
  return itemId ? instance.getItemInstance(itemId) : null;
21
22
  }, getRenamingValue: () => instance.getState().renamingValue || "", abortRenaming: () => {
22
- var _a, _b;
23
- (_b = (_a = instance.getConfig()).setRenamingItem) === null || _b === void 0 ? void 0 : _b.call(_a, null);
23
+ instance.applySubStateUpdate("renamingItem", null);
24
24
  }, completeRenaming: () => {
25
- var _a, _b, _c;
25
+ var _a;
26
26
  const config = instance.getConfig();
27
27
  const item = instance.getRenamingItem();
28
28
  if (item) {
29
29
  (_a = config.onRename) === null || _a === void 0 ? void 0 : _a.call(config, item, instance.getState().renamingValue || "");
30
30
  }
31
- (_c = (_b = instance.getConfig()).setRenamingItem) === null || _c === void 0 ? void 0 : _c.call(_b, null);
31
+ instance.applySubStateUpdate("renamingItem", null);
32
32
  }, isRenamingItem: () => !!instance.getState().renamingItem })),
33
33
  createItemInstance: (prev, instance, tree) => (Object.assign(Object.assign({}, prev), { getRenameInputProps: () => ({
34
34
  onBlur: () => tree.abortRenaming(),
35
35
  value: tree.getRenamingValue(),
36
36
  onChange: (e) => {
37
- var _a, _b;
38
- (_b = (_a = tree.getConfig()).setRenamingValue) === null || _b === void 0 ? void 0 : _b.call(_a, e.target.value);
37
+ tree.applySubStateUpdate("renamingValue", e.target.value);
39
38
  },
40
39
  }), canRename: () => { var _a, _b, _c; return (_c = (_b = (_a = tree.getConfig()).canRename) === null || _b === void 0 ? void 0 : _b.call(_a, instance)) !== null && _c !== void 0 ? _c : true; }, isRenaming: () => instance.getId() === tree.getState().renamingItem })),
41
40
  hotkeys: {