@headless-tree/core 1.2.1 → 1.4.0

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 (190) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/index.d.mts +580 -0
  3. package/dist/index.d.ts +580 -0
  4. package/dist/index.js +2347 -0
  5. package/dist/index.mjs +2302 -0
  6. package/package.json +18 -10
  7. package/src/core/create-tree.ts +26 -15
  8. package/src/features/async-data-loader/feature.ts +5 -0
  9. package/src/features/async-data-loader/types.ts +2 -0
  10. package/src/features/checkboxes/checkboxes.spec.ts +20 -5
  11. package/src/features/checkboxes/feature.ts +31 -16
  12. package/src/features/checkboxes/types.ts +1 -0
  13. package/src/features/drag-and-drop/drag-and-drop.spec.ts +11 -2
  14. package/src/features/drag-and-drop/feature.ts +107 -24
  15. package/src/features/drag-and-drop/types.ts +21 -0
  16. package/src/features/drag-and-drop/utils.ts +8 -6
  17. package/src/features/keyboard-drag-and-drop/feature.ts +10 -1
  18. package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +34 -3
  19. package/src/features/main/types.ts +0 -2
  20. package/src/features/sync-data-loader/feature.ts +5 -1
  21. package/src/features/tree/feature.ts +4 -3
  22. package/src/features/tree/tree.spec.ts +14 -4
  23. package/src/test-utils/test-tree-do.ts +2 -0
  24. package/src/test-utils/test-tree.ts +1 -0
  25. package/tsconfig.json +1 -4
  26. package/vitest.config.ts +3 -1
  27. package/lib/cjs/core/build-proxified-instance.d.ts +0 -2
  28. package/lib/cjs/core/build-proxified-instance.js +0 -58
  29. package/lib/cjs/core/build-static-instance.d.ts +0 -2
  30. package/lib/cjs/core/build-static-instance.js +0 -26
  31. package/lib/cjs/core/create-tree.d.ts +0 -2
  32. package/lib/cjs/core/create-tree.js +0 -191
  33. package/lib/cjs/features/async-data-loader/feature.d.ts +0 -2
  34. package/lib/cjs/features/async-data-loader/feature.js +0 -135
  35. package/lib/cjs/features/async-data-loader/types.d.ts +0 -47
  36. package/lib/cjs/features/async-data-loader/types.js +0 -2
  37. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  38. package/lib/cjs/features/checkboxes/feature.js +0 -94
  39. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  40. package/lib/cjs/features/checkboxes/types.js +0 -9
  41. package/lib/cjs/features/drag-and-drop/feature.d.ts +0 -2
  42. package/lib/cjs/features/drag-and-drop/feature.js +0 -205
  43. package/lib/cjs/features/drag-and-drop/types.d.ts +0 -71
  44. package/lib/cjs/features/drag-and-drop/types.js +0 -9
  45. package/lib/cjs/features/drag-and-drop/utils.d.ts +0 -27
  46. package/lib/cjs/features/drag-and-drop/utils.js +0 -182
  47. package/lib/cjs/features/expand-all/feature.d.ts +0 -2
  48. package/lib/cjs/features/expand-all/feature.js +0 -70
  49. package/lib/cjs/features/expand-all/types.d.ts +0 -19
  50. package/lib/cjs/features/expand-all/types.js +0 -2
  51. package/lib/cjs/features/hotkeys-core/feature.d.ts +0 -2
  52. package/lib/cjs/features/hotkeys-core/feature.js +0 -107
  53. package/lib/cjs/features/hotkeys-core/types.d.ts +0 -27
  54. package/lib/cjs/features/hotkeys-core/types.js +0 -2
  55. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  56. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +0 -206
  57. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +0 -27
  58. package/lib/cjs/features/keyboard-drag-and-drop/types.js +0 -11
  59. package/lib/cjs/features/main/types.d.ts +0 -47
  60. package/lib/cjs/features/main/types.js +0 -2
  61. package/lib/cjs/features/prop-memoization/feature.d.ts +0 -2
  62. package/lib/cjs/features/prop-memoization/feature.js +0 -70
  63. package/lib/cjs/features/prop-memoization/types.d.ts +0 -15
  64. package/lib/cjs/features/prop-memoization/types.js +0 -2
  65. package/lib/cjs/features/renaming/feature.d.ts +0 -2
  66. package/lib/cjs/features/renaming/feature.js +0 -86
  67. package/lib/cjs/features/renaming/types.d.ts +0 -27
  68. package/lib/cjs/features/renaming/types.js +0 -2
  69. package/lib/cjs/features/search/feature.d.ts +0 -2
  70. package/lib/cjs/features/search/feature.js +0 -119
  71. package/lib/cjs/features/search/types.d.ts +0 -32
  72. package/lib/cjs/features/search/types.js +0 -2
  73. package/lib/cjs/features/selection/feature.d.ts +0 -2
  74. package/lib/cjs/features/selection/feature.js +0 -132
  75. package/lib/cjs/features/selection/types.d.ts +0 -21
  76. package/lib/cjs/features/selection/types.js +0 -2
  77. package/lib/cjs/features/sync-data-loader/feature.d.ts +0 -2
  78. package/lib/cjs/features/sync-data-loader/feature.js +0 -49
  79. package/lib/cjs/features/sync-data-loader/types.d.ts +0 -28
  80. package/lib/cjs/features/sync-data-loader/types.js +0 -2
  81. package/lib/cjs/features/tree/feature.d.ts +0 -2
  82. package/lib/cjs/features/tree/feature.js +0 -244
  83. package/lib/cjs/features/tree/types.d.ts +0 -63
  84. package/lib/cjs/features/tree/types.js +0 -2
  85. package/lib/cjs/index.d.ts +0 -33
  86. package/lib/cjs/index.js +0 -51
  87. package/lib/cjs/mddocs-entry.d.ts +0 -121
  88. package/lib/cjs/mddocs-entry.js +0 -17
  89. package/lib/cjs/test-utils/test-tree-do.d.ts +0 -23
  90. package/lib/cjs/test-utils/test-tree-do.js +0 -112
  91. package/lib/cjs/test-utils/test-tree-expect.d.ts +0 -17
  92. package/lib/cjs/test-utils/test-tree-expect.js +0 -66
  93. package/lib/cjs/test-utils/test-tree.d.ts +0 -48
  94. package/lib/cjs/test-utils/test-tree.js +0 -207
  95. package/lib/cjs/types/core.d.ts +0 -84
  96. package/lib/cjs/types/core.js +0 -2
  97. package/lib/cjs/types/deep-merge.d.ts +0 -13
  98. package/lib/cjs/types/deep-merge.js +0 -2
  99. package/lib/cjs/utilities/create-on-drop-handler.d.ts +0 -3
  100. package/lib/cjs/utilities/create-on-drop-handler.js +0 -20
  101. package/lib/cjs/utilities/errors.d.ts +0 -2
  102. package/lib/cjs/utilities/errors.js +0 -9
  103. package/lib/cjs/utilities/insert-items-at-target.d.ts +0 -3
  104. package/lib/cjs/utilities/insert-items-at-target.js +0 -40
  105. package/lib/cjs/utilities/remove-items-from-parents.d.ts +0 -2
  106. package/lib/cjs/utilities/remove-items-from-parents.js +0 -32
  107. package/lib/cjs/utils.d.ts +0 -6
  108. package/lib/cjs/utils.js +0 -53
  109. package/lib/esm/core/build-proxified-instance.d.ts +0 -2
  110. package/lib/esm/core/build-proxified-instance.js +0 -54
  111. package/lib/esm/core/build-static-instance.d.ts +0 -2
  112. package/lib/esm/core/build-static-instance.js +0 -22
  113. package/lib/esm/core/create-tree.d.ts +0 -2
  114. package/lib/esm/core/create-tree.js +0 -187
  115. package/lib/esm/features/async-data-loader/feature.d.ts +0 -2
  116. package/lib/esm/features/async-data-loader/feature.js +0 -132
  117. package/lib/esm/features/async-data-loader/types.d.ts +0 -47
  118. package/lib/esm/features/async-data-loader/types.js +0 -1
  119. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  120. package/lib/esm/features/checkboxes/feature.js +0 -91
  121. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  122. package/lib/esm/features/checkboxes/types.js +0 -6
  123. package/lib/esm/features/drag-and-drop/feature.d.ts +0 -2
  124. package/lib/esm/features/drag-and-drop/feature.js +0 -202
  125. package/lib/esm/features/drag-and-drop/types.d.ts +0 -71
  126. package/lib/esm/features/drag-and-drop/types.js +0 -6
  127. package/lib/esm/features/drag-and-drop/utils.d.ts +0 -27
  128. package/lib/esm/features/drag-and-drop/utils.js +0 -172
  129. package/lib/esm/features/expand-all/feature.d.ts +0 -2
  130. package/lib/esm/features/expand-all/feature.js +0 -67
  131. package/lib/esm/features/expand-all/types.d.ts +0 -19
  132. package/lib/esm/features/expand-all/types.js +0 -1
  133. package/lib/esm/features/hotkeys-core/feature.d.ts +0 -2
  134. package/lib/esm/features/hotkeys-core/feature.js +0 -104
  135. package/lib/esm/features/hotkeys-core/types.d.ts +0 -27
  136. package/lib/esm/features/hotkeys-core/types.js +0 -1
  137. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +0 -2
  138. package/lib/esm/features/keyboard-drag-and-drop/feature.js +0 -203
  139. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +0 -27
  140. package/lib/esm/features/keyboard-drag-and-drop/types.js +0 -8
  141. package/lib/esm/features/main/types.d.ts +0 -47
  142. package/lib/esm/features/main/types.js +0 -1
  143. package/lib/esm/features/prop-memoization/feature.d.ts +0 -2
  144. package/lib/esm/features/prop-memoization/feature.js +0 -67
  145. package/lib/esm/features/prop-memoization/types.d.ts +0 -15
  146. package/lib/esm/features/prop-memoization/types.js +0 -1
  147. package/lib/esm/features/renaming/feature.d.ts +0 -2
  148. package/lib/esm/features/renaming/feature.js +0 -83
  149. package/lib/esm/features/renaming/types.d.ts +0 -27
  150. package/lib/esm/features/renaming/types.js +0 -1
  151. package/lib/esm/features/search/feature.d.ts +0 -2
  152. package/lib/esm/features/search/feature.js +0 -116
  153. package/lib/esm/features/search/types.d.ts +0 -32
  154. package/lib/esm/features/search/types.js +0 -1
  155. package/lib/esm/features/selection/feature.d.ts +0 -2
  156. package/lib/esm/features/selection/feature.js +0 -129
  157. package/lib/esm/features/selection/types.d.ts +0 -21
  158. package/lib/esm/features/selection/types.js +0 -1
  159. package/lib/esm/features/sync-data-loader/feature.d.ts +0 -2
  160. package/lib/esm/features/sync-data-loader/feature.js +0 -46
  161. package/lib/esm/features/sync-data-loader/types.d.ts +0 -28
  162. package/lib/esm/features/sync-data-loader/types.js +0 -1
  163. package/lib/esm/features/tree/feature.d.ts +0 -2
  164. package/lib/esm/features/tree/feature.js +0 -241
  165. package/lib/esm/features/tree/types.d.ts +0 -63
  166. package/lib/esm/features/tree/types.js +0 -1
  167. package/lib/esm/index.d.ts +0 -33
  168. package/lib/esm/index.js +0 -32
  169. package/lib/esm/mddocs-entry.d.ts +0 -121
  170. package/lib/esm/mddocs-entry.js +0 -1
  171. package/lib/esm/test-utils/test-tree-do.d.ts +0 -23
  172. package/lib/esm/test-utils/test-tree-do.js +0 -108
  173. package/lib/esm/test-utils/test-tree-expect.d.ts +0 -17
  174. package/lib/esm/test-utils/test-tree-expect.js +0 -62
  175. package/lib/esm/test-utils/test-tree.d.ts +0 -48
  176. package/lib/esm/test-utils/test-tree.js +0 -203
  177. package/lib/esm/types/core.d.ts +0 -84
  178. package/lib/esm/types/core.js +0 -1
  179. package/lib/esm/types/deep-merge.d.ts +0 -13
  180. package/lib/esm/types/deep-merge.js +0 -1
  181. package/lib/esm/utilities/create-on-drop-handler.d.ts +0 -3
  182. package/lib/esm/utilities/create-on-drop-handler.js +0 -16
  183. package/lib/esm/utilities/errors.d.ts +0 -2
  184. package/lib/esm/utilities/errors.js +0 -4
  185. package/lib/esm/utilities/insert-items-at-target.d.ts +0 -3
  186. package/lib/esm/utilities/insert-items-at-target.js +0 -36
  187. package/lib/esm/utilities/remove-items-from-parents.d.ts +0 -2
  188. package/lib/esm/utilities/remove-items-from-parents.js +0 -28
  189. package/lib/esm/utils.d.ts +0 -6
  190. package/lib/esm/utils.js +0 -46
@@ -1,116 +0,0 @@
1
- import { makeStateUpdater, memo } from "../../utils";
2
- export const searchFeature = {
3
- key: "search",
4
- getInitialState: (initialState) => (Object.assign({ search: null }, initialState)),
5
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setSearch: makeStateUpdater("search", tree), isSearchMatchingItem: (search, item) => search.length > 0 &&
6
- item.getItemName().toLowerCase().includes(search.toLowerCase()) }, defaultConfig)),
7
- stateHandlerNames: {
8
- search: "setSearch",
9
- },
10
- treeInstance: {
11
- setSearch: ({ tree }, search) => {
12
- var _a;
13
- tree.applySubStateUpdate("search", search);
14
- (_a = tree
15
- .getItems()
16
- .find((item) => { var _a, _b; return (_b = (_a = tree.getConfig()).isSearchMatchingItem) === null || _b === void 0 ? void 0 : _b.call(_a, tree.getSearchValue(), item); })) === null || _a === void 0 ? void 0 : _a.setFocused();
17
- },
18
- openSearch: ({ tree }, initialValue = "") => {
19
- var _a, _b;
20
- tree.setSearch(initialValue);
21
- (_b = (_a = tree.getConfig()).onOpenSearch) === null || _b === void 0 ? void 0 : _b.call(_a);
22
- setTimeout(() => {
23
- var _a;
24
- (_a = tree.getDataRef().current.searchInput) === null || _a === void 0 ? void 0 : _a.focus();
25
- });
26
- },
27
- closeSearch: ({ tree }) => {
28
- var _a, _b;
29
- tree.setSearch(null);
30
- (_b = (_a = tree.getConfig()).onCloseSearch) === null || _b === void 0 ? void 0 : _b.call(_a);
31
- tree.updateDomFocus();
32
- },
33
- isSearchOpen: ({ tree }) => tree.getState().search !== null,
34
- getSearchValue: ({ tree }) => tree.getState().search || "",
35
- registerSearchInputElement: ({ tree }, element) => {
36
- const dataRef = tree.getDataRef();
37
- dataRef.current.searchInput = element;
38
- if (element && dataRef.current.keydownHandler) {
39
- element.addEventListener("keydown", dataRef.current.keydownHandler);
40
- }
41
- },
42
- getSearchInputElement: ({ tree }) => { var _a; return (_a = tree.getDataRef().current.searchInput) !== null && _a !== void 0 ? _a : null; },
43
- // TODO memoize with propMemoizationFeature
44
- getSearchInputElementProps: ({ tree }) => ({
45
- value: tree.getSearchValue(),
46
- onChange: (e) => tree.setSearch(e.target.value),
47
- onBlur: () => tree.closeSearch(),
48
- ref: tree.registerSearchInputElement,
49
- }),
50
- getSearchMatchingItems: memo(({ tree }) => [
51
- tree.getSearchValue(),
52
- tree.getItems(),
53
- tree.getConfig().isSearchMatchingItem,
54
- ], (search, items, isSearchMatchingItem) => items.filter((item) => search && (isSearchMatchingItem === null || isSearchMatchingItem === void 0 ? void 0 : isSearchMatchingItem(search, item)))),
55
- },
56
- itemInstance: {
57
- isMatchingSearch: ({ tree, item }) => tree.getSearchMatchingItems().some((i) => i.getId() === item.getId()),
58
- },
59
- hotkeys: {
60
- openSearch: {
61
- hotkey: "LetterOrNumber",
62
- preventDefault: true, // TODO make true default
63
- isEnabled: (tree) => !tree.isSearchOpen(),
64
- handler: (e, tree) => {
65
- e.stopPropagation();
66
- tree.openSearch(e.key);
67
- },
68
- },
69
- closeSearch: {
70
- // TODO allow multiple, i.e. Enter
71
- hotkey: "Escape",
72
- allowWhenInputFocused: true,
73
- isEnabled: (tree) => tree.isSearchOpen(),
74
- handler: (e, tree) => {
75
- tree.closeSearch();
76
- },
77
- },
78
- submitSearch: {
79
- hotkey: "Enter",
80
- allowWhenInputFocused: true,
81
- isEnabled: (tree) => tree.isSearchOpen(),
82
- handler: (e, tree) => {
83
- tree.closeSearch();
84
- tree.setSelectedItems([tree.getFocusedItem().getId()]);
85
- },
86
- },
87
- nextSearchItem: {
88
- hotkey: "ArrowDown",
89
- allowWhenInputFocused: true,
90
- canRepeat: true,
91
- isEnabled: (tree) => tree.isSearchOpen(),
92
- handler: (e, tree) => {
93
- const focusItem = tree
94
- .getSearchMatchingItems()
95
- .find((item) => item.getItemMeta().index >
96
- tree.getFocusedItem().getItemMeta().index);
97
- focusItem === null || focusItem === void 0 ? void 0 : focusItem.setFocused();
98
- focusItem === null || focusItem === void 0 ? void 0 : focusItem.scrollTo({ block: "nearest", inline: "nearest" });
99
- },
100
- },
101
- previousSearchItem: {
102
- hotkey: "ArrowUp",
103
- allowWhenInputFocused: true,
104
- canRepeat: true,
105
- isEnabled: (tree) => tree.isSearchOpen(),
106
- handler: (e, tree) => {
107
- const focusItem = [...tree.getSearchMatchingItems()]
108
- .reverse()
109
- .find((item) => item.getItemMeta().index <
110
- tree.getFocusedItem().getItemMeta().index);
111
- focusItem === null || focusItem === void 0 ? void 0 : focusItem.setFocused();
112
- focusItem === null || focusItem === void 0 ? void 0 : focusItem.scrollTo({ block: "nearest", inline: "nearest" });
113
- },
114
- },
115
- },
116
- };
@@ -1,32 +0,0 @@
1
- import { ItemInstance, SetStateFn } from "../../types/core";
2
- import { HotkeysCoreDataRef } from "../hotkeys-core/types";
3
- export interface SearchFeatureDataRef<T = any> extends HotkeysCoreDataRef {
4
- matchingItems: ItemInstance<T>[];
5
- searchInput: HTMLInputElement | null;
6
- }
7
- export type SearchFeatureDef<T> = {
8
- state: {
9
- search: string | null;
10
- };
11
- config: {
12
- setSearch?: SetStateFn<string | null>;
13
- onOpenSearch?: () => void;
14
- onCloseSearch?: () => void;
15
- isSearchMatchingItem?: (search: string, item: ItemInstance<T>) => boolean;
16
- };
17
- treeInstance: {
18
- setSearch: (search: string | null) => void;
19
- openSearch: (initialValue?: string) => void;
20
- closeSearch: () => void;
21
- isSearchOpen: () => boolean;
22
- getSearchValue: () => string;
23
- registerSearchInputElement: (element: HTMLInputElement | null) => void;
24
- getSearchInputElement: () => HTMLInputElement | null;
25
- getSearchInputElementProps: () => any;
26
- getSearchMatchingItems: () => ItemInstance<T>[];
27
- };
28
- itemInstance: {
29
- isMatchingSearch: () => boolean;
30
- };
31
- hotkeys: "openSearch" | "closeSearch" | "submitSearch" | "nextSearchItem" | "previousSearchItem";
32
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const selectionFeature: FeatureImplementation;
@@ -1,129 +0,0 @@
1
- import { makeStateUpdater } from "../../utils";
2
- export const selectionFeature = {
3
- key: "selection",
4
- getInitialState: (initialState) => (Object.assign({ selectedItems: [] }, initialState)),
5
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setSelectedItems: makeStateUpdater("selectedItems", tree) }, defaultConfig)),
6
- stateHandlerNames: {
7
- selectedItems: "setSelectedItems",
8
- },
9
- treeInstance: {
10
- setSelectedItems: ({ tree }, selectedItems) => {
11
- tree.applySubStateUpdate("selectedItems", selectedItems);
12
- },
13
- getSelectedItems: ({ tree }) => {
14
- return tree.getState().selectedItems.map(tree.getItemInstance);
15
- },
16
- },
17
- itemInstance: {
18
- select: ({ tree, itemId }) => {
19
- const { selectedItems } = tree.getState();
20
- tree.setSelectedItems(selectedItems.includes(itemId)
21
- ? selectedItems
22
- : [...selectedItems, itemId]);
23
- },
24
- deselect: ({ tree, itemId }) => {
25
- const { selectedItems } = tree.getState();
26
- tree.setSelectedItems(selectedItems.filter((id) => id !== itemId));
27
- },
28
- isSelected: ({ tree, itemId }) => {
29
- const { selectedItems } = tree.getState();
30
- return selectedItems.includes(itemId);
31
- },
32
- selectUpTo: ({ tree, item }, ctrl) => {
33
- const indexA = item.getItemMeta().index;
34
- // TODO dont use focused item as anchor, but last primary-clicked item
35
- const indexB = tree.getFocusedItem().getItemMeta().index;
36
- const [a, b] = indexA < indexB ? [indexA, indexB] : [indexB, indexA];
37
- const newSelectedItems = tree
38
- .getItems()
39
- .slice(a, b + 1)
40
- .map((treeItem) => treeItem.getItemMeta().itemId);
41
- if (!ctrl) {
42
- tree.setSelectedItems(newSelectedItems);
43
- return;
44
- }
45
- const { selectedItems } = tree.getState();
46
- const uniqueSelectedItems = [
47
- ...new Set([...selectedItems, ...newSelectedItems]),
48
- ];
49
- tree.setSelectedItems(uniqueSelectedItems);
50
- },
51
- toggleSelect: ({ item }) => {
52
- if (item.isSelected()) {
53
- item.deselect();
54
- }
55
- else {
56
- item.select();
57
- }
58
- },
59
- getProps: ({ tree, item, prev }) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { "aria-selected": item.isSelected() ? "true" : "false", onClick: (e) => {
60
- var _a, _b;
61
- if (e.shiftKey) {
62
- item.selectUpTo(e.ctrlKey || e.metaKey);
63
- }
64
- else if (e.ctrlKey || e.metaKey) {
65
- item.toggleSelect();
66
- }
67
- else {
68
- tree.setSelectedItems([item.getItemMeta().itemId]);
69
- }
70
- (_b = (_a = prev === null || prev === void 0 ? void 0 : prev()) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
71
- } })),
72
- },
73
- hotkeys: {
74
- // setSelectedItem: {
75
- // hotkey: "space",
76
- // handler: (e, tree) => {
77
- // tree.setSelectedItems([tree.getFocusedItem().getId()]);
78
- // },
79
- // },
80
- toggleSelectedItem: {
81
- hotkey: "Control+Space",
82
- preventDefault: true,
83
- handler: (_, tree) => {
84
- tree.getFocusedItem().toggleSelect();
85
- },
86
- },
87
- selectUpwards: {
88
- hotkey: "Shift+ArrowUp",
89
- handler: (e, tree) => {
90
- const focused = tree.getFocusedItem();
91
- const above = focused.getItemAbove();
92
- if (!above)
93
- return;
94
- if (focused.isSelected() && above.isSelected()) {
95
- focused.deselect();
96
- }
97
- else {
98
- above.select();
99
- }
100
- above.setFocused();
101
- tree.updateDomFocus();
102
- },
103
- },
104
- selectDownwards: {
105
- hotkey: "Shift+ArrowDown",
106
- handler: (e, tree) => {
107
- const focused = tree.getFocusedItem();
108
- const below = focused.getItemBelow();
109
- if (!below)
110
- return;
111
- if (focused.isSelected() && below.isSelected()) {
112
- focused.deselect();
113
- }
114
- else {
115
- below.select();
116
- }
117
- below.setFocused();
118
- tree.updateDomFocus();
119
- },
120
- },
121
- selectAll: {
122
- hotkey: "Control+KeyA",
123
- preventDefault: true,
124
- handler: (e, tree) => {
125
- tree.setSelectedItems(tree.getItems().map((item) => item.getId()));
126
- },
127
- },
128
- },
129
- };
@@ -1,21 +0,0 @@
1
- import { ItemInstance, SetStateFn } from "../../types/core";
2
- export type SelectionFeatureDef<T> = {
3
- state: {
4
- selectedItems: string[];
5
- };
6
- config: {
7
- setSelectedItems?: SetStateFn<string[]>;
8
- };
9
- treeInstance: {
10
- setSelectedItems: (selectedItems: string[]) => void;
11
- getSelectedItems: () => ItemInstance<T>[];
12
- };
13
- itemInstance: {
14
- select: () => void;
15
- deselect: () => void;
16
- toggleSelect: () => void;
17
- isSelected: () => boolean;
18
- selectUpTo: (ctrl: boolean) => void;
19
- };
20
- hotkeys: "toggleSelectedItem" | "selectUpwards" | "selectDownwards" | "selectAll";
21
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const syncDataLoaderFeature: FeatureImplementation;
@@ -1,46 +0,0 @@
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 { makeStateUpdater } from "../../utils";
11
- import { throwError } from "../../utilities/errors";
12
- const promiseErrorMessage = "sync dataLoader returned promise";
13
- const unpromise = (data) => {
14
- if (!data || (typeof data === "object" && "then" in data)) {
15
- throw throwError(promiseErrorMessage);
16
- }
17
- return data;
18
- };
19
- export const syncDataLoaderFeature = {
20
- key: "sync-data-loader",
21
- getInitialState: (initialState) => (Object.assign({ loadingItemData: [], loadingItemChildrens: [] }, initialState)),
22
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setLoadingItemData: makeStateUpdater("loadingItemData", tree), setLoadingItemChildrens: makeStateUpdater("loadingItemChildrens", tree) }, defaultConfig)),
23
- stateHandlerNames: {
24
- loadingItemData: "setLoadingItemData",
25
- loadingItemChildrens: "setLoadingItemChildrens",
26
- },
27
- treeInstance: {
28
- waitForItemDataLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
29
- waitForItemChildrenLoaded: () => __awaiter(void 0, void 0, void 0, function* () { }),
30
- retrieveItemData: ({ tree }, itemId) => {
31
- return unpromise(tree.getConfig().dataLoader.getItem(itemId));
32
- },
33
- retrieveChildrenIds: ({ tree }, itemId) => {
34
- const { dataLoader } = tree.getConfig();
35
- if ("getChildren" in dataLoader) {
36
- return unpromise(dataLoader.getChildren(itemId));
37
- }
38
- return unpromise(dataLoader.getChildrenWithData(itemId)).map((c) => c.data);
39
- },
40
- loadItemData: ({ tree }, itemId) => tree.retrieveItemData(itemId),
41
- loadChildrenIds: ({ tree }, itemId) => tree.retrieveChildrenIds(itemId),
42
- },
43
- itemInstance: {
44
- isLoading: () => false,
45
- },
46
- };
@@ -1,28 +0,0 @@
1
- export type TreeDataLoader<T> = {
2
- getItem: (itemId: string) => T | Promise<T>;
3
- getChildren: (itemId: string) => string[] | Promise<string[]>;
4
- } | {
5
- getItem: (itemId: string) => T | Promise<T>;
6
- getChildrenWithData: (itemId: string) => {
7
- id: string;
8
- data: T;
9
- }[] | Promise<{
10
- id: string;
11
- data: T;
12
- }[]>;
13
- };
14
- export type SyncDataLoaderFeatureDef<T> = {
15
- state: {};
16
- config: {
17
- rootItemId: string;
18
- dataLoader: TreeDataLoader<T>;
19
- };
20
- treeInstance: {
21
- retrieveItemData: (itemId: string) => T;
22
- retrieveChildrenIds: (itemId: string) => string[];
23
- };
24
- itemInstance: {
25
- isLoading: () => boolean;
26
- };
27
- hotkeys: never;
28
- };
@@ -1 +0,0 @@
1
- export {};
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const treeFeature: FeatureImplementation<any>;
@@ -1,241 +0,0 @@
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 { makeStateUpdater, poll } from "../../utils";
11
- import { logWarning } from "../../utilities/errors";
12
- export const treeFeature = {
13
- key: "tree",
14
- getInitialState: (initialState) => (Object.assign({ expandedItems: [], focusedItem: null }, initialState)),
15
- getDefaultConfig: (defaultConfig, tree) => (Object.assign({ setExpandedItems: makeStateUpdater("expandedItems", tree), setFocusedItem: makeStateUpdater("focusedItem", tree) }, defaultConfig)),
16
- stateHandlerNames: {
17
- expandedItems: "setExpandedItems",
18
- focusedItem: "setFocusedItem",
19
- },
20
- treeInstance: {
21
- getItemsMeta: ({ tree }) => {
22
- const { rootItemId } = tree.getConfig();
23
- const { expandedItems } = tree.getState();
24
- const flatItems = [];
25
- const expandedItemsSet = new Set(expandedItems); // TODO support setting state expandedItems as set instead of array
26
- const recursiveAdd = (itemId, path, level, setSize, posInSet) => {
27
- var _a;
28
- if (path.includes(itemId)) {
29
- logWarning(`Circular reference for ${path.join(".")}`);
30
- return;
31
- }
32
- flatItems.push({
33
- itemId,
34
- level,
35
- index: flatItems.length,
36
- parentId: path.at(-1),
37
- setSize,
38
- posInSet,
39
- });
40
- if (expandedItemsSet.has(itemId)) {
41
- const children = (_a = tree.retrieveChildrenIds(itemId)) !== null && _a !== void 0 ? _a : [];
42
- let i = 0;
43
- for (const childId of children) {
44
- recursiveAdd(childId, path.concat(itemId), level + 1, children.length, i++);
45
- }
46
- }
47
- };
48
- const children = tree.retrieveChildrenIds(rootItemId);
49
- let i = 0;
50
- for (const itemId of children) {
51
- recursiveAdd(itemId, [rootItemId], 0, children.length, i++);
52
- }
53
- return flatItems;
54
- },
55
- getFocusedItem: ({ tree }) => {
56
- var _a, _b;
57
- return ((_b = tree.getItemInstance((_a = tree.getState().focusedItem) !== null && _a !== void 0 ? _a : "")) !== null && _b !== void 0 ? _b : tree.getItems()[0]);
58
- },
59
- getRootItem: ({ tree }) => {
60
- const { rootItemId } = tree.getConfig();
61
- return tree.getItemInstance(rootItemId);
62
- },
63
- focusNextItem: ({ tree }) => {
64
- var _a;
65
- const focused = tree.getFocusedItem().getItemMeta();
66
- if (!focused)
67
- return;
68
- const nextIndex = Math.min(focused.index + 1, tree.getItems().length - 1);
69
- (_a = tree.getItems()[nextIndex]) === null || _a === void 0 ? void 0 : _a.setFocused();
70
- },
71
- focusPreviousItem: ({ tree }) => {
72
- var _a;
73
- const focused = tree.getFocusedItem().getItemMeta();
74
- if (!focused)
75
- return;
76
- const nextIndex = Math.max(focused.index - 1, 0);
77
- (_a = tree.getItems()[nextIndex]) === null || _a === void 0 ? void 0 : _a.setFocused();
78
- },
79
- updateDomFocus: ({ tree }) => {
80
- // Required because if the state is managed outside in react, the state only updated during next render
81
- setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
82
- var _a, _b;
83
- const focusedItem = tree.getFocusedItem();
84
- (_b = (_a = tree.getConfig()).scrollToItem) === null || _b === void 0 ? void 0 : _b.call(_a, focusedItem);
85
- yield poll(() => focusedItem.getElement() !== null, 20);
86
- const focusedElement = focusedItem.getElement();
87
- if (!focusedElement)
88
- return;
89
- focusedElement.focus();
90
- }));
91
- },
92
- getContainerProps: ({ prev, tree }, treeLabel) => (Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { role: "tree", "aria-label": treeLabel !== null && treeLabel !== void 0 ? treeLabel : "", ref: tree.registerElement })),
93
- // relevant for hotkeys of this feature
94
- isSearchOpen: () => false,
95
- },
96
- itemInstance: {
97
- scrollTo: (_a, scrollIntoViewArg_1) => __awaiter(void 0, [_a, scrollIntoViewArg_1], void 0, function* ({ tree, item }, scrollIntoViewArg) {
98
- var _b, _c, _d;
99
- (_c = (_b = tree.getConfig()).scrollToItem) === null || _c === void 0 ? void 0 : _c.call(_b, item);
100
- yield poll(() => item.getElement() !== null, 20);
101
- (_d = item.getElement()) === null || _d === void 0 ? void 0 : _d.scrollIntoView(scrollIntoViewArg);
102
- }),
103
- getId: ({ itemId }) => itemId,
104
- getKey: ({ itemId }) => itemId, // TODO apply to all stories to use
105
- getProps: ({ item, prev }) => {
106
- const itemMeta = item.getItemMeta();
107
- return Object.assign(Object.assign({}, prev === null || prev === void 0 ? void 0 : prev()), { ref: item.registerElement, role: "treeitem", "aria-setsize": itemMeta.setSize, "aria-posinset": itemMeta.posInSet, "aria-selected": "false", "aria-label": item.getItemName(), "aria-level": itemMeta.level, tabIndex: item.isFocused() ? 0 : -1, onClick: (e) => {
108
- item.setFocused();
109
- item.primaryAction();
110
- if (e.ctrlKey || e.shiftKey || e.metaKey) {
111
- return;
112
- }
113
- if (!item.isFolder()) {
114
- return;
115
- }
116
- if (item.isExpanded()) {
117
- item.collapse();
118
- }
119
- else {
120
- item.expand();
121
- }
122
- } });
123
- },
124
- expand: ({ tree, item, itemId }) => {
125
- var _a;
126
- if (!item.isFolder()) {
127
- return;
128
- }
129
- if ((_a = tree.getState().loadingItemChildrens) === null || _a === void 0 ? void 0 : _a.includes(itemId)) {
130
- return;
131
- }
132
- tree.applySubStateUpdate("expandedItems", (expandedItems) => [
133
- ...expandedItems,
134
- itemId,
135
- ]);
136
- tree.rebuildTree();
137
- },
138
- collapse: ({ tree, item, itemId }) => {
139
- if (!item.isFolder()) {
140
- return;
141
- }
142
- tree.applySubStateUpdate("expandedItems", (expandedItems) => expandedItems.filter((id) => id !== itemId));
143
- tree.rebuildTree();
144
- },
145
- getItemData: ({ tree, itemId }) => tree.retrieveItemData(itemId),
146
- equals: ({ item }, other) => item.getId() === (other === null || other === void 0 ? void 0 : other.getId()),
147
- isExpanded: ({ tree, itemId }) => tree.getState().expandedItems.includes(itemId),
148
- isDescendentOf: ({ item }, parentId) => {
149
- const parent = item.getParent();
150
- return Boolean((parent === null || parent === void 0 ? void 0 : parent.getId()) === parentId || (parent === null || parent === void 0 ? void 0 : parent.isDescendentOf(parentId)));
151
- },
152
- isFocused: ({ tree, item, itemId }) => tree.getState().focusedItem === itemId ||
153
- (tree.getState().focusedItem === null && item.getItemMeta().index === 0),
154
- isFolder: ({ tree, item }) => item.getItemMeta().level === -1 ||
155
- tree.getConfig().isItemFolder(item),
156
- getItemName: ({ tree, item }) => {
157
- const config = tree.getConfig();
158
- return config.getItemName(item);
159
- },
160
- setFocused: ({ tree, itemId }) => {
161
- tree.applySubStateUpdate("focusedItem", itemId);
162
- },
163
- primaryAction: ({ tree, item }) => { var _a, _b; return (_b = (_a = tree.getConfig()).onPrimaryAction) === null || _b === void 0 ? void 0 : _b.call(_a, item); },
164
- getParent: ({ tree, item }) => item.getItemMeta().parentId
165
- ? tree.getItemInstance(item.getItemMeta().parentId)
166
- : undefined,
167
- getIndexInParent: ({ item }) => item.getItemMeta().posInSet,
168
- getChildren: ({ tree, itemId }) => tree.retrieveChildrenIds(itemId).map((id) => tree.getItemInstance(id)),
169
- getTree: ({ tree }) => tree,
170
- getItemAbove: ({ tree, item }) => tree.getItems()[item.getItemMeta().index - 1],
171
- getItemBelow: ({ tree, item }) => tree.getItems()[item.getItemMeta().index + 1],
172
- },
173
- hotkeys: {
174
- focusNextItem: {
175
- hotkey: "ArrowDown",
176
- canRepeat: true,
177
- preventDefault: true,
178
- isEnabled: (tree) => { var _a, _b; return !((_b = (_a = tree.isSearchOpen) === null || _a === void 0 ? void 0 : _a.call(tree)) !== null && _b !== void 0 ? _b : false) && !tree.getState().dnd; }, // TODO what happens when the feature doesnt exist? proxy method still claims to exist
179
- handler: (e, tree) => {
180
- tree.focusNextItem();
181
- tree.updateDomFocus();
182
- },
183
- },
184
- focusPreviousItem: {
185
- hotkey: "ArrowUp",
186
- canRepeat: true,
187
- preventDefault: true,
188
- isEnabled: (tree) => { var _a, _b; return !((_b = (_a = tree.isSearchOpen) === null || _a === void 0 ? void 0 : _a.call(tree)) !== null && _b !== void 0 ? _b : false) && !tree.getState().dnd; },
189
- handler: (e, tree) => {
190
- tree.focusPreviousItem();
191
- tree.updateDomFocus();
192
- },
193
- },
194
- expandOrDown: {
195
- hotkey: "ArrowRight",
196
- canRepeat: true,
197
- handler: (e, tree) => {
198
- const item = tree.getFocusedItem();
199
- if (item.isExpanded() || !item.isFolder()) {
200
- tree.focusNextItem();
201
- tree.updateDomFocus();
202
- }
203
- else {
204
- item.expand();
205
- }
206
- },
207
- },
208
- collapseOrUp: {
209
- hotkey: "ArrowLeft",
210
- canRepeat: true,
211
- handler: (e, tree) => {
212
- var _a;
213
- const item = tree.getFocusedItem();
214
- if ((!item.isExpanded() || !item.isFolder()) &&
215
- item.getItemMeta().level !== 0) {
216
- (_a = item.getParent()) === null || _a === void 0 ? void 0 : _a.setFocused();
217
- tree.updateDomFocus();
218
- }
219
- else {
220
- item.collapse();
221
- }
222
- },
223
- },
224
- focusFirstItem: {
225
- hotkey: "Home",
226
- handler: (e, tree) => {
227
- var _a;
228
- (_a = tree.getItems()[0]) === null || _a === void 0 ? void 0 : _a.setFocused();
229
- tree.updateDomFocus();
230
- },
231
- },
232
- focusLastItem: {
233
- hotkey: "End",
234
- handler: (e, tree) => {
235
- var _a;
236
- (_a = tree.getItems()[tree.getItems().length - 1]) === null || _a === void 0 ? void 0 : _a.setFocused();
237
- tree.updateDomFocus();
238
- },
239
- },
240
- },
241
- };