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

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 (37) hide show
  1. package/CHANGELOG.md +1 -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/main/types.d.ts +0 -2
  6. package/lib/cjs/features/sync-data-loader/feature.js +2 -0
  7. package/lib/cjs/index.d.ts +0 -2
  8. package/lib/cjs/index.js +0 -2
  9. package/lib/cjs/types/core.d.ts +1 -2
  10. package/lib/esm/core/create-tree.js +0 -9
  11. package/lib/esm/features/async-data-loader/feature.js +20 -41
  12. package/lib/esm/features/async-data-loader/types.d.ts +4 -4
  13. package/lib/esm/features/main/types.d.ts +0 -2
  14. package/lib/esm/features/sync-data-loader/feature.js +2 -0
  15. package/lib/esm/index.d.ts +0 -2
  16. package/lib/esm/index.js +0 -2
  17. package/lib/esm/types/core.d.ts +1 -2
  18. package/package.json +1 -1
  19. package/src/core/create-tree.ts +0 -13
  20. package/src/features/async-data-loader/feature.ts +24 -35
  21. package/src/features/async-data-loader/types.ts +4 -4
  22. package/src/features/main/types.ts +0 -2
  23. package/src/features/sync-data-loader/feature.ts +3 -0
  24. package/src/features/tree/types.ts +1 -1
  25. package/src/index.ts +0 -2
  26. package/src/types/core.ts +0 -2
  27. package/lib/cjs/features/checkboxes/feature.d.ts +0 -2
  28. package/lib/cjs/features/checkboxes/feature.js +0 -94
  29. package/lib/cjs/features/checkboxes/types.d.ts +0 -26
  30. package/lib/cjs/features/checkboxes/types.js +0 -9
  31. package/lib/esm/features/checkboxes/feature.d.ts +0 -2
  32. package/lib/esm/features/checkboxes/feature.js +0 -91
  33. package/lib/esm/features/checkboxes/types.d.ts +0 -26
  34. package/lib/esm/features/checkboxes/types.js +0 -6
  35. package/src/features/checkboxes/checkboxes.spec.ts +0 -134
  36. package/src/features/checkboxes/feature.ts +0 -119
  37. package/src/features/checkboxes/types.ts +0 -28
@@ -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
@@ -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>>;
@@ -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;
@@ -1,91 +0,0 @@
1
- import { makeStateUpdater } from "../../utils";
2
- import { CheckedState } from "./types";
3
- import { throwError } from "../../utilities/errors";
4
- const getAllLoadedDescendants = (tree, itemId) => {
5
- if (!tree.getConfig().isItemFolder(tree.buildItemInstance(itemId))) {
6
- return [itemId];
7
- }
8
- return tree
9
- .retrieveChildrenIds(itemId)
10
- .map((child) => getAllLoadedDescendants(tree, child))
11
- .flat();
12
- };
13
- export const checkboxesFeature = {
14
- key: "checkboxes",
15
- overwrites: ["selection"],
16
- getInitialState: (initialState) => (Object.assign({ checkedItems: [] }, initialState)),
17
- getDefaultConfig: (defaultConfig, tree) => {
18
- var _a;
19
- const hasAsyncLoader = (_a = defaultConfig.features) === null || _a === void 0 ? void 0 : _a.some((f) => f.key === "async-data-loader");
20
- if (hasAsyncLoader && !defaultConfig.canCheckFolders) {
21
- throwError(`!canCheckFolders not supported with async trees`);
22
- }
23
- return Object.assign({ setCheckedItems: makeStateUpdater("checkedItems", tree), canCheckFolders: hasAsyncLoader !== null && hasAsyncLoader !== void 0 ? hasAsyncLoader : false }, defaultConfig);
24
- },
25
- stateHandlerNames: {
26
- checkedItems: "setCheckedItems",
27
- },
28
- treeInstance: {
29
- setCheckedItems: ({ tree }, checkedItems) => {
30
- tree.applySubStateUpdate("checkedItems", checkedItems);
31
- },
32
- },
33
- itemInstance: {
34
- getCheckboxProps: ({ item }) => {
35
- const checkedState = item.getCheckedState();
36
- return {
37
- onChange: item.toggleCheckedState,
38
- checked: checkedState === CheckedState.Checked,
39
- ref: (r) => {
40
- if (r) {
41
- r.indeterminate = checkedState === CheckedState.Indeterminate;
42
- }
43
- },
44
- };
45
- },
46
- toggleCheckedState: ({ item }) => {
47
- if (item.getCheckedState() === CheckedState.Checked) {
48
- item.setUnchecked();
49
- }
50
- else {
51
- item.setChecked();
52
- }
53
- },
54
- getCheckedState: ({ item, tree, itemId }) => {
55
- const { checkedItems } = tree.getState();
56
- if (checkedItems.includes(itemId)) {
57
- return CheckedState.Checked;
58
- }
59
- if (item.isFolder() && !tree.getConfig().canCheckFolders) {
60
- const descendants = getAllLoadedDescendants(tree, itemId);
61
- if (descendants.every((d) => checkedItems.includes(d))) {
62
- return CheckedState.Checked;
63
- }
64
- if (descendants.some((d) => checkedItems.includes(d))) {
65
- return CheckedState.Indeterminate;
66
- }
67
- }
68
- return CheckedState.Unchecked;
69
- },
70
- setChecked: ({ item, tree, itemId }) => {
71
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
72
- tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
73
- }
74
- else {
75
- tree.applySubStateUpdate("checkedItems", (items) => [
76
- ...items,
77
- ...getAllLoadedDescendants(tree, itemId),
78
- ]);
79
- }
80
- },
81
- setUnchecked: ({ item, tree, itemId }) => {
82
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
83
- tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => id !== itemId));
84
- }
85
- else {
86
- const descendants = getAllLoadedDescendants(tree, itemId);
87
- tree.applySubStateUpdate("checkedItems", (items) => items.filter((id) => !descendants.includes(id)));
88
- }
89
- },
90
- },
91
- };
@@ -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,6 +0,0 @@
1
- export var CheckedState;
2
- (function (CheckedState) {
3
- CheckedState["Checked"] = "checked";
4
- CheckedState["Unchecked"] = "unchecked";
5
- CheckedState["Indeterminate"] = "indeterminate";
6
- })(CheckedState || (CheckedState = {}));
@@ -1,134 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { TestTree } from "../../test-utils/test-tree";
3
- import { checkboxesFeature } from "./feature";
4
- import { CheckedState } from "./types";
5
-
6
- const factory = TestTree.default({})
7
- .withFeatures(checkboxesFeature)
8
- .suits.sync().tree;
9
-
10
- describe("core-feature/checkboxes", () => {
11
- it("should initialize with no checked items", async () => {
12
- const tree = await factory.createTestCaseTree();
13
- expect(tree.instance.getState().checkedItems).toEqual([]);
14
- });
15
-
16
- it("should check items", async () => {
17
- const tree = await factory.createTestCaseTree();
18
- tree.item("x111").setChecked();
19
- tree.item("x112").setChecked();
20
- expect(tree.instance.getState().checkedItems).toEqual(["x111", "x112"]);
21
- });
22
-
23
- it("should uncheck an item", async () => {
24
- const tree = await factory
25
- .with({ state: { checkedItems: ["x111"] } })
26
- .createTestCaseTree();
27
- tree.item("x111").setUnchecked();
28
- expect(tree.instance.getState().checkedItems).not.toContain("x111");
29
- });
30
-
31
- it("should toggle checked state", async () => {
32
- const tree = await factory.createTestCaseTree();
33
- const item = tree.item("x111");
34
-
35
- item.toggleCheckedState();
36
- expect(tree.instance.getState().checkedItems).toContain("x111");
37
-
38
- item.toggleCheckedState();
39
- expect(tree.instance.getState().checkedItems).not.toContain("x111");
40
- });
41
-
42
- describe("props", () => {
43
- it("should toggle checked state", async () => {
44
- const tree = await factory.createTestCaseTree();
45
- const item = tree.item("x111");
46
-
47
- item.getCheckboxProps().onChange();
48
- expect(tree.instance.getState().checkedItems).toContain("x111");
49
-
50
- item.getCheckboxProps().onChange();
51
- expect(tree.instance.getState().checkedItems).not.toContain("x111");
52
- });
53
-
54
- it("should return checked state in props", async () => {
55
- const tree = await factory.createTestCaseTree();
56
- tree.item("x111").setChecked();
57
- expect(tree.item("x111").getCheckboxProps().checked).toBe(true);
58
- expect(tree.item("x112").getCheckboxProps().checked).toBe(false);
59
- });
60
-
61
- it("should create indeterminate state", async () => {
62
- const tree = await factory.createTestCaseTree();
63
- tree.item("x111").setChecked();
64
- const refObject = { indeterminate: undefined };
65
- tree.item("x11").getCheckboxProps().ref(refObject);
66
- expect(refObject.indeterminate).toBe(true);
67
- });
68
-
69
- it("should not create indeterminate state", async () => {
70
- const tree = await factory.createTestCaseTree();
71
- const refObject = { indeterminate: undefined };
72
- tree.item("x11").getCheckboxProps().ref(refObject);
73
- expect(refObject.indeterminate).toBe(false);
74
- });
75
- });
76
-
77
- it("should handle folder checking when canCheckFolders is true", async () => {
78
- const tree = await factory
79
- .with({ canCheckFolders: true })
80
- .createTestCaseTree();
81
-
82
- tree.item("x11").setChecked();
83
- expect(tree.instance.getState().checkedItems).toContain("x11");
84
- });
85
-
86
- it("should handle folder checking when canCheckFolders is false", async () => {
87
- const tree = await factory.createTestCaseTree();
88
-
89
- tree.item("x11").setChecked();
90
- expect(tree.instance.getState().checkedItems).toEqual(
91
- expect.arrayContaining(["x111", "x112", "x113", "x114"]),
92
- );
93
- });
94
-
95
- it("should turn folder indeterminate", async () => {
96
- const tree = await factory.createTestCaseTree();
97
-
98
- tree.item("x111").setChecked();
99
- expect(tree.item("x11").getCheckedState()).toBe(CheckedState.Indeterminate);
100
- });
101
-
102
- it("should turn folder checked if all children are checked", async () => {
103
- const tree = await factory
104
- .with({
105
- isItemFolder: (item) => item.getItemData().length < 4,
106
- })
107
- .createTestCaseTree();
108
-
109
- tree.item("x11").setChecked();
110
- tree.item("x12").setChecked();
111
- tree.item("x13").setChecked();
112
- expect(tree.item("x1").getCheckedState()).toBe(CheckedState.Indeterminate);
113
- tree.do.selectItem("x14");
114
- tree.item("x141").setChecked();
115
- tree.item("x142").setChecked();
116
- tree.item("x143").setChecked();
117
- expect(tree.item("x1").getCheckedState()).toBe(CheckedState.Indeterminate);
118
- tree.item("x144").setChecked();
119
- expect(tree.item("x1").getCheckedState()).toBe(CheckedState.Checked);
120
- });
121
-
122
- it("should return correct checked state for items", async () => {
123
- const tree = await factory.createTestCaseTree();
124
- const item = tree.instance.getItemInstance("x111");
125
-
126
- expect(item.getCheckedState()).toBe(CheckedState.Unchecked);
127
-
128
- item.setChecked();
129
- expect(item.getCheckedState()).toBe(CheckedState.Checked);
130
-
131
- item.setUnchecked();
132
- expect(item.getCheckedState()).toBe(CheckedState.Unchecked);
133
- });
134
- });
@@ -1,119 +0,0 @@
1
- import { FeatureImplementation, TreeInstance } from "../../types/core";
2
- import { makeStateUpdater } from "../../utils";
3
- import { CheckedState } from "./types";
4
- import { throwError } from "../../utilities/errors";
5
-
6
- const getAllLoadedDescendants = <T>(
7
- tree: TreeInstance<T>,
8
- itemId: string,
9
- ): string[] => {
10
- if (!tree.getConfig().isItemFolder(tree.buildItemInstance(itemId))) {
11
- return [itemId];
12
- }
13
- return tree
14
- .retrieveChildrenIds(itemId)
15
- .map((child) => getAllLoadedDescendants(tree, child))
16
- .flat();
17
- };
18
-
19
- export const checkboxesFeature: FeatureImplementation = {
20
- key: "checkboxes",
21
-
22
- overwrites: ["selection"],
23
-
24
- getInitialState: (initialState) => ({
25
- checkedItems: [],
26
- ...initialState,
27
- }),
28
-
29
- getDefaultConfig: (defaultConfig, tree) => {
30
- const hasAsyncLoader = defaultConfig.features?.some(
31
- (f) => f.key === "async-data-loader",
32
- );
33
- if (hasAsyncLoader && !defaultConfig.canCheckFolders) {
34
- throwError(`!canCheckFolders not supported with async trees`);
35
- }
36
- return {
37
- setCheckedItems: makeStateUpdater("checkedItems", tree),
38
- canCheckFolders: hasAsyncLoader ?? false,
39
- ...defaultConfig,
40
- };
41
- },
42
-
43
- stateHandlerNames: {
44
- checkedItems: "setCheckedItems",
45
- },
46
-
47
- treeInstance: {
48
- setCheckedItems: ({ tree }, checkedItems) => {
49
- tree.applySubStateUpdate("checkedItems", checkedItems);
50
- },
51
- },
52
-
53
- itemInstance: {
54
- getCheckboxProps: ({ item }) => {
55
- const checkedState = item.getCheckedState();
56
- return {
57
- onChange: item.toggleCheckedState,
58
- checked: checkedState === CheckedState.Checked,
59
- ref: (r: any) => {
60
- if (r) {
61
- r.indeterminate = checkedState === CheckedState.Indeterminate;
62
- }
63
- },
64
- };
65
- },
66
-
67
- toggleCheckedState: ({ item }) => {
68
- if (item.getCheckedState() === CheckedState.Checked) {
69
- item.setUnchecked();
70
- } else {
71
- item.setChecked();
72
- }
73
- },
74
-
75
- getCheckedState: ({ item, tree, itemId }) => {
76
- const { checkedItems } = tree.getState();
77
-
78
- if (checkedItems.includes(itemId)) {
79
- return CheckedState.Checked;
80
- }
81
-
82
- if (item.isFolder() && !tree.getConfig().canCheckFolders) {
83
- const descendants = getAllLoadedDescendants(tree, itemId);
84
- if (descendants.every((d) => checkedItems.includes(d))) {
85
- return CheckedState.Checked;
86
- }
87
- if (descendants.some((d) => checkedItems.includes(d))) {
88
- return CheckedState.Indeterminate;
89
- }
90
- }
91
-
92
- return CheckedState.Unchecked;
93
- },
94
-
95
- setChecked: ({ item, tree, itemId }) => {
96
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
97
- tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
98
- } else {
99
- tree.applySubStateUpdate("checkedItems", (items) => [
100
- ...items,
101
- ...getAllLoadedDescendants(tree, itemId),
102
- ]);
103
- }
104
- },
105
-
106
- setUnchecked: ({ item, tree, itemId }) => {
107
- if (!item.isFolder() || tree.getConfig().canCheckFolders) {
108
- tree.applySubStateUpdate("checkedItems", (items) =>
109
- items.filter((id) => id !== itemId),
110
- );
111
- } else {
112
- const descendants = getAllLoadedDescendants(tree, itemId);
113
- tree.applySubStateUpdate("checkedItems", (items) =>
114
- items.filter((id) => !descendants.includes(id)),
115
- );
116
- }
117
- },
118
- },
119
- };
@@ -1,28 +0,0 @@
1
- import { SetStateFn } from "../../types/core";
2
-
3
- export enum CheckedState {
4
- Checked = "checked",
5
- Unchecked = "unchecked",
6
- Indeterminate = "indeterminate",
7
- }
8
-
9
- export type CheckboxesFeatureDef<T> = {
10
- state: {
11
- checkedItems: string[];
12
- };
13
- config: {
14
- setCheckedItems?: SetStateFn<string[]>;
15
- canCheckFolders?: boolean;
16
- };
17
- treeInstance: {
18
- setCheckedItems: (checkedItems: string[]) => void;
19
- };
20
- itemInstance: {
21
- setChecked: () => void;
22
- setUnchecked: () => void;
23
- toggleCheckedState: () => void;
24
- getCheckedState: () => CheckedState;
25
- getCheckboxProps: () => Record<string, any>;
26
- };
27
- hotkeys: never;
28
- };