@headless-tree/core 0.0.0-20250511185653 → 0.0.0-20250511194715

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 (49) hide show
  1. package/CHANGELOG.md +2 -1
  2. package/lib/cjs/core/create-tree.js +0 -9
  3. package/lib/cjs/features/async-data-loader/feature.js +20 -41
  4. package/lib/cjs/features/async-data-loader/types.d.ts +4 -4
  5. package/lib/cjs/features/expand-all/feature.js +2 -2
  6. package/lib/cjs/features/hotkeys-core/feature.js +27 -13
  7. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +1 -1
  8. package/lib/cjs/features/main/types.d.ts +0 -2
  9. package/lib/cjs/features/selection/feature.js +1 -1
  10. package/lib/cjs/features/sync-data-loader/feature.js +2 -0
  11. package/lib/cjs/index.d.ts +0 -2
  12. package/lib/cjs/index.js +0 -2
  13. package/lib/cjs/types/core.d.ts +1 -2
  14. package/lib/esm/core/create-tree.js +0 -9
  15. package/lib/esm/features/async-data-loader/feature.js +20 -41
  16. package/lib/esm/features/async-data-loader/types.d.ts +4 -4
  17. package/lib/esm/features/expand-all/feature.js +2 -2
  18. package/lib/esm/features/hotkeys-core/feature.js +27 -13
  19. package/lib/esm/features/keyboard-drag-and-drop/feature.js +1 -1
  20. package/lib/esm/features/main/types.d.ts +0 -2
  21. package/lib/esm/features/selection/feature.js +1 -1
  22. package/lib/esm/features/sync-data-loader/feature.js +2 -0
  23. package/lib/esm/index.d.ts +0 -2
  24. package/lib/esm/index.js +0 -2
  25. package/lib/esm/types/core.d.ts +1 -2
  26. package/package.json +1 -1
  27. package/src/core/create-tree.ts +0 -13
  28. package/src/features/async-data-loader/feature.ts +24 -35
  29. package/src/features/async-data-loader/types.ts +4 -4
  30. package/src/features/expand-all/feature.ts +2 -2
  31. package/src/features/hotkeys-core/feature.ts +33 -15
  32. package/src/features/keyboard-drag-and-drop/feature.ts +1 -1
  33. package/src/features/main/types.ts +0 -2
  34. package/src/features/selection/feature.ts +1 -1
  35. package/src/features/sync-data-loader/feature.ts +3 -0
  36. package/src/features/tree/types.ts +1 -1
  37. package/src/index.ts +0 -2
  38. package/src/types/core.ts +0 -2
  39. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  40. package/lib/cjs/features/checkboxes/feature.js +0 -94
  41. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  42. package/lib/cjs/features/checkboxes/types.js +0 -9
  43. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  44. package/lib/esm/features/checkboxes/feature.js +0 -91
  45. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  46. package/lib/esm/features/checkboxes/types.js +0 -6
  47. package/src/features/checkboxes/checkboxes.spec.ts +0 -134
  48. package/src/features/checkboxes/feature.ts +0 -119
  49. package/src/features/checkboxes/types.ts +0 -28
@@ -119,7 +119,7 @@ export const selectionFeature = {
119
119
  },
120
120
  },
121
121
  selectAll: {
122
- hotkey: "Control+a",
122
+ hotkey: "Control+KeyA",
123
123
  preventDefault: true,
124
124
  handler: (e, tree) => {
125
125
  tree.setSelectedItems(tree.getItems().map((item) => item.getId()));
@@ -37,6 +37,8 @@ export const syncDataLoaderFeature = {
37
37
  }
38
38
  return unpromise(dataLoader.getChildrenWithData(itemId)).map((c) => c.data);
39
39
  },
40
+ loadItemData: ({ tree }, itemId) => tree.retrieveItemData(itemId),
41
+ loadChildrenIds: ({ tree }, itemId) => tree.retrieveChildrenIds(itemId),
40
42
  },
41
43
  itemInstance: {
42
44
  isLoading: () => false,
@@ -5,7 +5,6 @@ export { MainFeatureDef, InstanceBuilder } from "./features/main/types";
5
5
  export * from "./features/drag-and-drop/types";
6
6
  export * from "./features/keyboard-drag-and-drop/types";
7
7
  export * from "./features/selection/types";
8
- export * from "./features/checkboxes/types";
9
8
  export * from "./features/async-data-loader/types";
10
9
  export * from "./features/sync-data-loader/types";
11
10
  export * from "./features/hotkeys-core/types";
@@ -14,7 +13,6 @@ export * from "./features/renaming/types";
14
13
  export * from "./features/expand-all/types";
15
14
  export * from "./features/prop-memoization/types";
16
15
  export * from "./features/selection/feature";
17
- export * from "./features/checkboxes/feature";
18
16
  export * from "./features/hotkeys-core/feature";
19
17
  export * from "./features/async-data-loader/feature";
20
18
  export * from "./features/sync-data-loader/feature";
package/lib/esm/index.js CHANGED
@@ -4,7 +4,6 @@ export * from "./features/tree/types";
4
4
  export * from "./features/drag-and-drop/types";
5
5
  export * from "./features/keyboard-drag-and-drop/types";
6
6
  export * from "./features/selection/types";
7
- export * from "./features/checkboxes/types";
8
7
  export * from "./features/async-data-loader/types";
9
8
  export * from "./features/sync-data-loader/types";
10
9
  export * from "./features/hotkeys-core/types";
@@ -13,7 +12,6 @@ export * from "./features/renaming/types";
13
12
  export * from "./features/expand-all/types";
14
13
  export * from "./features/prop-memoization/types";
15
14
  export * from "./features/selection/feature";
16
- export * from "./features/checkboxes/feature";
17
15
  export * from "./features/hotkeys-core/feature";
18
16
  export * from "./features/async-data-loader/feature";
19
17
  export * from "./features/sync-data-loader/feature";
@@ -10,7 +10,6 @@ import { RenamingFeatureDef } from "../features/renaming/types";
10
10
  import { ExpandAllFeatureDef } from "../features/expand-all/types";
11
11
  import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
12
12
  import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
13
- import { CheckboxesFeatureDef } from "../features/checkboxes/types";
14
13
  export type Updater<T> = T | ((old: T) => T);
15
14
  export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
16
15
  export type FeatureDef = {
@@ -35,7 +34,7 @@ type MergedFeatures<F extends FeatureDef> = {
35
34
  itemInstance: UnionToIntersection<F["itemInstance"]>;
36
35
  hotkeys: F["hotkeys"];
37
36
  };
38
- export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | CheckboxesFeatureDef<T> | DragAndDropFeatureDef<T> | KeyboardDragAndDropFeatureDef<T> | HotkeysCoreFeatureDef<T> | SyncDataLoaderFeatureDef<T> | AsyncDataLoaderFeatureDef<T> | SearchFeatureDef<T> | RenamingFeatureDef<T> | ExpandAllFeatureDef | PropMemoizationFeatureDef;
37
+ export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | DragAndDropFeatureDef<T> | KeyboardDragAndDropFeatureDef<T> | HotkeysCoreFeatureDef<T> | SyncDataLoaderFeatureDef<T> | AsyncDataLoaderFeatureDef<T> | SearchFeatureDef<T> | RenamingFeatureDef<T> | ExpandAllFeatureDef | PropMemoizationFeatureDef;
39
38
  type TreeStateType<T> = MergedFeatures<RegisteredFeatures<T>>["state"];
40
39
  export interface TreeState<T> extends TreeStateType<T> {
41
40
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@headless-tree/core",
3
- "version": "0.0.0-20250511185653",
3
+ "version": "0.0.0-20250511194715",
4
4
  "type": "module",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/esm/index.js",
@@ -151,19 +151,6 @@ export const createTree = <T>(
151
151
  ] as Function;
152
152
  externalStateSetter?.(state[stateName]);
153
153
  },
154
- buildItemInstance: ({}, itemId) => {
155
- const [instance, finalizeInstance] = buildInstance(
156
- features,
157
- "itemInstance",
158
- (instance) => ({
159
- item: instance,
160
- tree: treeInstance,
161
- itemId,
162
- }),
163
- );
164
- finalizeInstance();
165
- return instance;
166
- },
167
154
  // TODO rebuildSubTree: (itemId: string) => void;
168
155
  rebuildTree: () => {
169
156
  rebuildItemMeta();
@@ -20,23 +20,21 @@ const loadItemData = async <T>(tree: TreeInstance<T>, itemId: string) => {
20
20
  loadingItemData.filter((id) => id !== itemId),
21
21
  );
22
22
 
23
- dataRef.current.awaitingItemDataLoading?.[itemId].forEach((cb) => cb());
24
- delete dataRef.current.awaitingItemDataLoading?.[itemId];
23
+ return item;
25
24
  };
26
25
 
27
26
  const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
28
27
  const config = tree.getConfig();
29
28
  const dataRef = getDataRef(tree);
29
+ let childrenIds: string[];
30
30
 
31
31
  if ("getChildrenWithData" in config.dataLoader) {
32
32
  const children = await config.dataLoader.getChildrenWithData(itemId);
33
- const childrenIds = children.map((c) => c.id);
33
+ childrenIds = children.map((c) => c.id);
34
34
  dataRef.current.childrenIds[itemId] = childrenIds;
35
35
  children.forEach(({ id, data }) => {
36
36
  dataRef.current.itemData[id] = data;
37
37
  config.onLoadedItem?.(id, data);
38
- dataRef.current.awaitingItemDataLoading?.[id].forEach((cb) => cb());
39
- delete dataRef.current.awaitingItemDataLoading?.[id];
40
38
  });
41
39
 
42
40
  config.onLoadedChildren?.(itemId, childrenIds);
@@ -45,7 +43,7 @@ const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
45
43
  loadingItemData.filter((id) => !childrenIds.includes(id)),
46
44
  );
47
45
  } else {
48
- const childrenIds = await config.dataLoader.getChildren(itemId);
46
+ childrenIds = await config.dataLoader.getChildren(itemId);
49
47
  dataRef.current.childrenIds[itemId] = childrenIds;
50
48
  config.onLoadedChildren?.(itemId, childrenIds);
51
49
  tree.rebuildTree();
@@ -55,8 +53,7 @@ const loadChildrenIds = async <T>(tree: TreeInstance<T>, itemId: string) => {
55
53
  loadingItemChildrens.filter((id) => id !== itemId),
56
54
  );
57
55
 
58
- dataRef.current.awaitingItemChildrensLoading?.[itemId]?.forEach((cb) => cb());
59
- delete dataRef.current.awaitingItemChildrensLoading?.[itemId];
56
+ return childrenIds;
60
57
  };
61
58
 
62
59
  export const asyncDataLoaderFeature: FeatureImplementation = {
@@ -80,33 +77,25 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
80
77
  },
81
78
 
82
79
  treeInstance: {
83
- waitForItemDataLoaded: async ({ tree }, itemId) => {
84
- tree.retrieveItemData(itemId);
85
- if (!tree.getState().loadingItemData.includes(itemId)) {
86
- return;
87
- }
88
- await new Promise<void>((resolve) => {
89
- const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
90
- dataRef.current.awaitingItemDataLoading ??= {};
91
- dataRef.current.awaitingItemDataLoading[itemId] ??= [];
92
- dataRef.current.awaitingItemDataLoading[itemId].push(resolve);
93
- });
94
- },
80
+ waitForItemDataLoaded: ({ tree }, itemId) => tree.loadItemData(itemId),
95
81
 
96
- waitForItemChildrenLoaded: async ({ tree }, itemId) => {
97
- tree.retrieveChildrenIds(itemId);
98
- if (!tree.getState().loadingItemChildrens.includes(itemId)) {
99
- return;
100
- }
101
- await new Promise<void>((resolve) => {
102
- const dataRef = tree.getDataRef<AsyncDataLoaderDataRef>();
103
- dataRef.current.awaitingItemChildrensLoading ??= {};
104
- dataRef.current.awaitingItemChildrensLoading[itemId] ??= [];
105
- dataRef.current.awaitingItemChildrensLoading[itemId].push(resolve);
106
- });
82
+ waitForItemChildrenLoaded: ({ tree }, itemId) =>
83
+ tree.loadChildrenIds(itemId),
84
+
85
+ loadItemData: async ({ tree }, itemId) => {
86
+ return (
87
+ getDataRef(tree).current.itemData[itemId] ??
88
+ (await loadItemData(tree, itemId))
89
+ );
90
+ },
91
+ loadChildrenIds: async ({ tree }, itemId) => {
92
+ return (
93
+ getDataRef(tree).current.childrenIds[itemId] ??
94
+ (await loadChildrenIds(tree, itemId))
95
+ );
107
96
  },
108
97
 
109
- retrieveItemData: ({ tree }, itemId, skipFetch = false) => {
98
+ retrieveItemData: ({ tree }, itemId) => {
110
99
  const config = tree.getConfig();
111
100
  const dataRef = getDataRef(tree);
112
101
 
@@ -114,7 +103,7 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
114
103
  return dataRef.current.itemData[itemId];
115
104
  }
116
105
 
117
- if (!tree.getState().loadingItemData.includes(itemId) && !skipFetch) {
106
+ if (!tree.getState().loadingItemData.includes(itemId)) {
118
107
  tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
119
108
  ...loadingItemData,
120
109
  itemId,
@@ -126,13 +115,13 @@ export const asyncDataLoaderFeature: FeatureImplementation = {
126
115
  return config.createLoadingItemData?.() ?? null;
127
116
  },
128
117
 
129
- retrieveChildrenIds: ({ tree }, itemId, skipFetch = false) => {
118
+ retrieveChildrenIds: ({ tree }, itemId) => {
130
119
  const dataRef = getDataRef(tree);
131
120
  if (dataRef.current.childrenIds[itemId]) {
132
121
  return dataRef.current.childrenIds[itemId];
133
122
  }
134
123
 
135
- if (tree.getState().loadingItemChildrens.includes(itemId) || skipFetch) {
124
+ if (tree.getState().loadingItemChildrens.includes(itemId)) {
136
125
  return [];
137
126
  }
138
127
 
@@ -1,13 +1,9 @@
1
1
  import { SetStateFn } from "../../types/core";
2
2
  import { SyncDataLoaderFeatureDef } from "../sync-data-loader/types";
3
3
 
4
- type AwaitingLoaderCallbacks = Record<string, (() => void)[]>;
5
-
6
4
  export interface AsyncDataLoaderDataRef<T = any> {
7
5
  itemData: Record<string, T>;
8
6
  childrenIds: Record<string, string[]>;
9
- awaitingItemDataLoading: AwaitingLoaderCallbacks;
10
- awaitingItemChildrensLoading: AwaitingLoaderCallbacks;
11
7
  }
12
8
 
13
9
  /**
@@ -32,8 +28,12 @@ export type AsyncDataLoaderFeatureDef<T> = {
32
28
  onLoadedChildren?: (itemId: string, childrenIds: string[]) => void;
33
29
  };
34
30
  treeInstance: SyncDataLoaderFeatureDef<T>["treeInstance"] & {
31
+ /** @deprecated use loadItemData instead */
35
32
  waitForItemDataLoaded: (itemId: string) => Promise<void>;
33
+ /** @deprecated use loadChildrenIds instead */
36
34
  waitForItemChildrenLoaded: (itemId: string) => Promise<void>;
35
+ loadItemData: (itemId: string) => Promise<T>;
36
+ loadChildrenIds: (itemId: string) => Promise<string[]>;
37
37
  };
38
38
  itemInstance: SyncDataLoaderFeatureDef<T>["itemInstance"] & {
39
39
  /** Invalidate fetched data for item, and triggers a refetch and subsequent rerender if the item is visible
@@ -50,7 +50,7 @@ export const expandAllFeature: FeatureImplementation = {
50
50
  handler: async (_, tree) => {
51
51
  const cancelToken = { current: false };
52
52
  const cancelHandler = (e: KeyboardEvent) => {
53
- if (e.key === "Escape") {
53
+ if (e.code === "Escape") {
54
54
  cancelToken.current = true;
55
55
  }
56
56
  };
@@ -63,7 +63,7 @@ export const expandAllFeature: FeatureImplementation = {
63
63
  },
64
64
 
65
65
  collapseSelected: {
66
- hotkey: "Control+Shift+-",
66
+ hotkey: "Control+Shift+Minus",
67
67
  handler: (_, tree) => {
68
68
  tree.getSelectedItems().forEach((item) => item.collapseAll());
69
69
  },
@@ -6,10 +6,13 @@ import {
6
6
  import { HotkeyConfig, HotkeysCoreDataRef } from "./types";
7
7
 
8
8
  const specialKeys: Record<string, RegExp> = {
9
- Letter: /^[a-z]$/,
10
- LetterOrNumber: /^[a-z0-9]$/,
11
- Plus: /^\+$/,
12
- Space: /^ $/,
9
+ // TODO:breaking deprecate auto-lowercase
10
+ letter: /^Key[A-Z]$/,
11
+ letterornumber: /^(Key[A-Z]|Digit[0-9])$/,
12
+ plus: /^(NumpadAdd|Plus)$/,
13
+ minus: /^(NumpadSubtract|Minus)$/,
14
+ control: /^(ControlLeft|ControlRight)$/,
15
+ shift: /^(ShiftLeft|ShiftRight)$/,
13
16
  };
14
17
 
15
18
  const testHotkeyMatch = (
@@ -17,12 +20,28 @@ const testHotkeyMatch = (
17
20
  tree: TreeInstance<any>,
18
21
  hotkey: HotkeyConfig<any>,
19
22
  ) => {
20
- const supposedKeys = hotkey.hotkey.toLowerCase().split("+");
21
- const doKeysMatch = supposedKeys.every((key) =>
22
- key in specialKeys
23
- ? [...pressedKeys].some((pressedKey) => specialKeys[key].test(pressedKey))
24
- : pressedKeys.has(key),
25
- );
23
+ const supposedKeys = hotkey.hotkey.toLowerCase().split("+"); // TODO:breaking deprecate auto-lowercase
24
+ const doKeysMatch = supposedKeys.every((key) => {
25
+ if (key in specialKeys) {
26
+ return [...pressedKeys].some((pressedKey) =>
27
+ specialKeys[key].test(pressedKey),
28
+ );
29
+ }
30
+
31
+ const pressedKeysLowerCase = [...pressedKeys] // TODO:breaking deprecate auto-lowercase
32
+ .map((k) => k.toLowerCase());
33
+
34
+ if (pressedKeysLowerCase.includes(key.toLowerCase())) {
35
+ return true;
36
+ }
37
+
38
+ if (pressedKeysLowerCase.includes(`key${key.toLowerCase()}`)) {
39
+ // TODO:breaking deprecate e.key character matching
40
+ return true;
41
+ }
42
+
43
+ return false;
44
+ });
26
45
  const isEnabled = !hotkey.isEnabled || hotkey.isEnabled(tree);
27
46
  const equalCounts = pressedKeys.size === supposedKeys.length;
28
47
  return doKeysMatch && isEnabled && equalCounts;
@@ -50,10 +69,9 @@ export const hotkeysCoreFeature: FeatureImplementation = {
50
69
  return;
51
70
  }
52
71
 
53
- const key = e.key.toLowerCase();
54
72
  data.current.pressedKeys ??= new Set();
55
- const newMatch = !data.current.pressedKeys.has(key);
56
- data.current.pressedKeys.add(key);
73
+ const newMatch = !data.current.pressedKeys.has(e.code);
74
+ data.current.pressedKeys.add(e.code);
57
75
 
58
76
  const hotkeyName = findHotkeyMatch(
59
77
  data.current.pressedKeys,
@@ -65,7 +83,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
65
83
  if (e.target instanceof HTMLInputElement) {
66
84
  // JS respects composite keydowns while input elements are focused, and
67
85
  // doesnt send the associated keyup events with the same key name
68
- data.current.pressedKeys.delete(key);
86
+ data.current.pressedKeys.delete(e.code);
69
87
  }
70
88
 
71
89
  if (!hotkeyName) return;
@@ -90,7 +108,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
90
108
 
91
109
  const keyup = (e: KeyboardEvent) => {
92
110
  data.current.pressedKeys ??= new Set();
93
- data.current.pressedKeys.delete(e.key.toLowerCase());
111
+ data.current.pressedKeys.delete(e.code);
94
112
  };
95
113
 
96
114
  const reset = () => {
@@ -187,7 +187,7 @@ export const keyboardDragAndDropFeature: FeatureImplementation = {
187
187
 
188
188
  hotkeys: {
189
189
  startDrag: {
190
- hotkey: "Control+Shift+D",
190
+ hotkey: "Control+Shift+KeyD",
191
191
  preventDefault: true,
192
192
  isEnabled: (tree) => !tree.getState().dnd,
193
193
  handler: (_, tree) => {
@@ -36,8 +36,6 @@ export type MainFeatureDef<T = any> = {
36
36
  stateName: K,
37
37
  updater: Updater<TreeState<T>[K]>,
38
38
  ) => void;
39
- /** @internal */
40
- buildItemInstance: (itemId: string) => ItemInstance<T>;
41
39
  setState: SetStateFn<TreeState<T>>;
42
40
  getState: () => TreeState<T>;
43
41
  setConfig: SetStateFn<TreeConfig<T>>;
@@ -144,7 +144,7 @@ export const selectionFeature: FeatureImplementation = {
144
144
  },
145
145
  },
146
146
  selectAll: {
147
- hotkey: "Control+a",
147
+ hotkey: "Control+KeyA",
148
148
  preventDefault: true,
149
149
  handler: (e, tree) => {
150
150
  tree.setSelectedItems(tree.getItems().map((item) => item.getId()));
@@ -47,6 +47,9 @@ export const syncDataLoaderFeature: FeatureImplementation = {
47
47
  (c) => c.data,
48
48
  );
49
49
  },
50
+
51
+ loadItemData: ({ tree }, itemId) => tree.retrieveItemData(itemId),
52
+ loadChildrenIds: ({ tree }, itemId) => tree.retrieveChildrenIds(itemId),
50
53
  },
51
54
 
52
55
  itemInstance: {
@@ -20,7 +20,7 @@ export type TreeFeatureDef<T> = {
20
20
  focusedItem: string | null;
21
21
  };
22
22
  config: {
23
- isItemFolder: (item: ItemInstance<T>) => boolean; // TODO:breaking use item data as payload
23
+ isItemFolder: (item: ItemInstance<T>) => boolean;
24
24
  getItemName: (item: ItemInstance<T>) => string;
25
25
 
26
26
  onPrimaryAction?: (item: ItemInstance<T>) => void;
package/src/index.ts CHANGED
@@ -6,7 +6,6 @@ export { MainFeatureDef, InstanceBuilder } from "./features/main/types";
6
6
  export * from "./features/drag-and-drop/types";
7
7
  export * from "./features/keyboard-drag-and-drop/types";
8
8
  export * from "./features/selection/types";
9
- export * from "./features/checkboxes/types";
10
9
  export * from "./features/async-data-loader/types";
11
10
  export * from "./features/sync-data-loader/types";
12
11
  export * from "./features/hotkeys-core/types";
@@ -16,7 +15,6 @@ export * from "./features/expand-all/types";
16
15
  export * from "./features/prop-memoization/types";
17
16
 
18
17
  export * from "./features/selection/feature";
19
- export * from "./features/checkboxes/feature";
20
18
  export * from "./features/hotkeys-core/feature";
21
19
  export * from "./features/async-data-loader/feature";
22
20
  export * from "./features/sync-data-loader/feature";
package/src/types/core.ts CHANGED
@@ -13,7 +13,6 @@ import { RenamingFeatureDef } from "../features/renaming/types";
13
13
  import { ExpandAllFeatureDef } from "../features/expand-all/types";
14
14
  import { PropMemoizationFeatureDef } from "../features/prop-memoization/types";
15
15
  import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
16
- import { CheckboxesFeatureDef } from "../features/checkboxes/types";
17
16
 
18
17
  export type Updater<T> = T | ((old: T) => T);
19
18
  export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
@@ -54,7 +53,6 @@ export type RegisteredFeatures<T> =
54
53
  | MainFeatureDef<T>
55
54
  | TreeFeatureDef<T>
56
55
  | SelectionFeatureDef<T>
57
- | CheckboxesFeatureDef<T>
58
56
  | DragAndDropFeatureDef<T>
59
57
  | KeyboardDragAndDropFeatureDef<T>
60
58
  | HotkeysCoreFeatureDef<T>
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const checkboxesFeature: FeatureImplementation;
@@ -1,94 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkboxesFeature = void 0;
4
- const utils_1 = require("../../utils");
5
- const types_1 = require("./types");
6
- const errors_1 = require("../../utilities/errors");
7
- const getAllLoadedDescendants = (tree, itemId) => {
8
- if (!tree.getConfig().isItemFolder(tree.buildItemInstance(itemId))) {
9
- return [itemId];
10
- }
11
- return tree
12
- .retrieveChildrenIds(itemId)
13
- .map((child) => getAllLoadedDescendants(tree, child))
14
- .flat();
15
- };
16
- exports.checkboxesFeature = {
17
- key: "checkboxes",
18
- overwrites: ["selection"],
19
- getInitialState: (initialState) => (Object.assign({ checkedItems: [] }, initialState)),
20
- getDefaultConfig: (defaultConfig, tree) => {
21
- var _a;
22
- const hasAsyncLoader = (_a = defaultConfig.features) === null || _a === void 0 ? void 0 : _a.some((f) => f.key === "async-data-loader");
23
- if (hasAsyncLoader && !defaultConfig.canCheckFolders) {
24
- (0, errors_1.throwError)(`!canCheckFolders not supported with async trees`);
25
- }
26
- return Object.assign({ setCheckedItems: (0, utils_1.makeStateUpdater)("checkedItems", tree), canCheckFolders: hasAsyncLoader !== null && hasAsyncLoader !== void 0 ? hasAsyncLoader : false }, defaultConfig);
27
- },
28
- stateHandlerNames: {
29
- checkedItems: "setCheckedItems",
30
- },
31
- treeInstance: {
32
- setCheckedItems: ({ tree }, checkedItems) => {
33
- tree.applySubStateUpdate("checkedItems", checkedItems);
34
- },
35
- },
36
- itemInstance: {
37
- getCheckboxProps: ({ item }) => {
38
- const checkedState = item.getCheckedState();
39
- return {
40
- onChange: item.toggleCheckedState,
41
- checked: checkedState === types_1.CheckedState.Checked,
42
- ref: (r) => {
43
- if (r) {
44
- r.indeterminate = checkedState === types_1.CheckedState.Indeterminate;
45
- }
46
- },
47
- };
48
- },
49
- toggleCheckedState: ({ item }) => {
50
- if (item.getCheckedState() === types_1.CheckedState.Checked) {
51
- item.setUnchecked();
52
- }
53
- else {
54
- item.setChecked();
55
- }
56
- },
57
- getCheckedState: ({ item, tree, itemId }) => {
58
- const { checkedItems } = tree.getState();
59
- if (checkedItems.includes(itemId)) {
60
- return types_1.CheckedState.Checked;
61
- }
62
- if (item.isFolder() && !tree.getConfig().canCheckFolders) {
63
- const descendants = getAllLoadedDescendants(tree, itemId);
64
- if (descendants.every((d) => checkedItems.includes(d))) {
65
- return types_1.CheckedState.Checked;
66
- }
67
- if (descendants.some((d) => checkedItems.includes(d))) {
68
- return types_1.CheckedState.Indeterminate;
69
- }
70
- }
71
- return types_1.CheckedState.Unchecked;
72
- },
73
- setChecked: ({ item, tree, itemId }) => {
74
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
75
- tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
76
- }
77
- else {
78
- tree.applySubStateUpdate("checkedItems", (items) => [
79
- ...items,
80
- ...getAllLoadedDescendants(tree, itemId),
81
- ]);
82
- }
83
- },
84
- setUnchecked: ({ item, tree, itemId }) => {
85
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
86
- tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => id !== itemId));
87
- }
88
- else {
89
- const descendants = getAllLoadedDescendants(tree, itemId);
90
- tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => !descendants.includes(id)));
91
- }
92
- },
93
- },
94
- };
@@ -1,26 +0,0 @@
1
- import { SetStateFn } from "../../types/core";
2
- export declare enum CheckedState {
3
- Checked = "checked",
4
- Unchecked = "unchecked",
5
- Indeterminate = "indeterminate"
6
- }
7
- export type CheckboxesFeatureDef<T> = {
8
- state: {
9
- checkedItems: string[];
10
- };
11
- config: {
12
- setCheckedItems?: SetStateFn<string[]>;
13
- canCheckFolders?: boolean;
14
- };
15
- treeInstance: {
16
- setCheckedItems: (checkedItems: string[]) => void;
17
- };
18
- itemInstance: {
19
- setChecked: () => void;
20
- setUnchecked: () => void;
21
- toggleCheckedState: () => void;
22
- getCheckedState: () => CheckedState;
23
- getCheckboxProps: () => Record<string, any>;
24
- };
25
- hotkeys: never;
26
- };
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CheckedState = void 0;
4
- var CheckedState;
5
- (function (CheckedState) {
6
- CheckedState["Checked"] = "checked";
7
- CheckedState["Unchecked"] = "unchecked";
8
- CheckedState["Indeterminate"] = "indeterminate";
9
- })(CheckedState || (exports.CheckedState = CheckedState = {}));
@@ -1,2 +0,0 @@
1
- import { FeatureImplementation } from "../../types/core";
2
- export declare const checkboxesFeature: FeatureImplementation;