@headless-tree/core 1.4.0 → 1.5.1
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.
- package/CHANGELOG.md +27 -0
- package/dist/index.d.mts +34 -10
- package/dist/index.d.ts +34 -10
- package/dist/index.js +152 -73
- package/dist/index.mjs +152 -73
- package/package.json +19 -3
- package/readme.md +6 -6
- package/src/core/create-tree.ts +45 -9
- package/src/features/async-data-loader/async-data-loader.spec.ts +1 -0
- package/src/features/async-data-loader/feature.ts +16 -20
- package/src/features/async-data-loader/types.ts +2 -1
- package/src/features/checkboxes/checkboxes.spec.ts +111 -122
- package/src/features/checkboxes/feature.ts +89 -40
- package/src/features/checkboxes/types.ts +16 -3
- package/src/features/drag-and-drop/feature.ts +7 -0
- package/src/features/drag-and-drop/types.ts +6 -0
- package/src/features/hotkeys-core/feature.ts +2 -0
- package/src/features/main/types.ts +9 -0
- package/src/features/sync-data-loader/types.ts +7 -1
- package/src/features/tree/feature.ts +2 -2
- package/src/features/tree/tree.spec.ts +37 -4
- package/src/mddocs-entry.ts +13 -0
- package/src/test-utils/test-tree-do.ts +6 -0
- package/src/test-utils/test-tree.ts +17 -6
- package/src/types/core.ts +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @headless-tree/core
|
|
2
2
|
|
|
3
|
+
## 1.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 08f10f1: Fixed an issue where `isFolder` returns incorrect values for leafs if they are not visibly rendered (#166)
|
|
8
|
+
|
|
9
|
+
## 1.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- cbeaba6: all state updates (like setSelectedItems) will not propagate while the component is unmounted. This happened before for `tree.setState()` calls directly, but not individual state atoms like `setSelectedItems`. When calling `createTree()` directly (instead of `useTree()`), `tree.setMounted(true)` needs to be called once after mount. No changes are necessary when using the React-based `useTree()` integration. (#158)
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 72e714b: all NPM deployments will now publish with provenance
|
|
18
|
+
- 6693986: fixed an issue where async data loaders cause calling `item.getItemData()` outside of the component calling `useTree()` to cause a React warning log (#158)
|
|
19
|
+
- 7a7424f: fixed incorrect exports definition in package.json for require/cjs imports (#161)
|
|
20
|
+
- 215ab4b: add a new symbol that can be used in hotkey configurations "metaorcontrol" that will trigger if either any windows control key or mac meta key is pressed (#141)
|
|
21
|
+
- 51b0dea: Added `isUnorderedDragTarget` as alternative to `isDragTarget` for easier detection of drag type
|
|
22
|
+
- cf845d7: Added new state variable `loadingCheckPropagationItems` to indicate if, in async trees with checkboxes and state propagation enabled, data loading operations are currently loading due to a checkbox propagation taking place
|
|
23
|
+
- 597faad: Checkbox propagation is now supported for trees with async data loaders!
|
|
24
|
+
- b0ee382: triggering a data refetch will now always set the loadingItemData/loadingItemChildrens state variable to the associated items if they where not apart of the cache before
|
|
25
|
+
|
|
26
|
+
### Sponsorship appreciation
|
|
27
|
+
|
|
28
|
+
Thanks for [Docmost](https://docmost.com/), who have supported the development of Headless Tree with a sponsor contribution. Docmost is a wiki-software that can be self-hosted or used in cloud. Thank you!
|
|
29
|
+
|
|
3
30
|
## 1.4.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -75,7 +75,12 @@ type DragAndDropFeatureDef<T> = {
|
|
|
75
75
|
getDragLineStyle: (topOffset?: number, leftOffset?: number) => Record<string, any>;
|
|
76
76
|
};
|
|
77
77
|
itemInstance: {
|
|
78
|
+
/** Checks if the user is dragging in a way which makes this the new parent of the dragged items, either by dragging on top of
|
|
79
|
+
* this item, or by dragging inbetween children of this item. See @{isUnorderedDragTarget} if the latter is undesirable. */
|
|
78
80
|
isDragTarget: () => boolean;
|
|
81
|
+
/** As opposed to @{isDragTarget}, this will not be true if the target is inbetween children of this item. This returns only true
|
|
82
|
+
* if the user is dragging directly on top of this item. */
|
|
83
|
+
isUnorderedDragTarget: () => boolean;
|
|
79
84
|
isDragTargetAbove: () => boolean;
|
|
80
85
|
isDragTargetBelow: () => boolean;
|
|
81
86
|
isDraggingOver: () => boolean;
|
|
@@ -177,6 +182,10 @@ type MainFeatureDef<T = any> = {
|
|
|
177
182
|
};
|
|
178
183
|
getHotkeyPresets: () => HotkeysConfig<T>;
|
|
179
184
|
rebuildTree: () => void;
|
|
185
|
+
/** @deprecated Experimental feature, might get removed or changed in the future. */
|
|
186
|
+
scheduleRebuildTree: () => void;
|
|
187
|
+
/** @internal */
|
|
188
|
+
setMounted: (isMounted: boolean) => void;
|
|
180
189
|
};
|
|
181
190
|
itemInstance: {
|
|
182
191
|
registerElement: (element: HTMLElement | null) => void;
|
|
@@ -259,7 +268,12 @@ type SyncDataLoaderFeatureDef<T> = {
|
|
|
259
268
|
};
|
|
260
269
|
treeInstance: {
|
|
261
270
|
retrieveItemData: (itemId: string) => T;
|
|
262
|
-
|
|
271
|
+
/** Retrieve children Ids. If an async data loader is used, skipFetch is set to true, and children have not been retrieved
|
|
272
|
+
* yet for this item, this will initiate fetching the children, and return an empty array. Once the children have loaded,
|
|
273
|
+
* a rerender will be triggered.
|
|
274
|
+
* @param skipFetch - Defaults to false.
|
|
275
|
+
*/
|
|
276
|
+
retrieveChildrenIds: (itemId: string, skipFetch?: boolean) => string[];
|
|
263
277
|
};
|
|
264
278
|
itemInstance: {
|
|
265
279
|
isLoading: () => boolean;
|
|
@@ -307,7 +321,8 @@ type AsyncDataLoaderFeatureDef<T> = {
|
|
|
307
321
|
* @param optimistic If true, the item will not trigger a state update on `loadingItemChildrens`, and
|
|
308
322
|
* the tree will continue to display the old data until the new data has loaded. */
|
|
309
323
|
invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
|
|
310
|
-
|
|
324
|
+
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch. */
|
|
325
|
+
updateCachedData: (data: T | undefined) => void;
|
|
311
326
|
updateCachedChildrenIds: (childrenIds: string[]) => void;
|
|
312
327
|
isLoading: () => boolean;
|
|
313
328
|
};
|
|
@@ -443,9 +458,11 @@ declare enum CheckedState {
|
|
|
443
458
|
type CheckboxesFeatureDef<T> = {
|
|
444
459
|
state: {
|
|
445
460
|
checkedItems: string[];
|
|
461
|
+
loadingCheckPropagationItems: string[];
|
|
446
462
|
};
|
|
447
463
|
config: {
|
|
448
464
|
setCheckedItems?: SetStateFn<string[]>;
|
|
465
|
+
setLoadingCheckPropagationItems?: SetStateFn<string[]>;
|
|
449
466
|
canCheckFolders?: boolean;
|
|
450
467
|
propagateCheckedState?: boolean;
|
|
451
468
|
};
|
|
@@ -453,11 +470,18 @@ type CheckboxesFeatureDef<T> = {
|
|
|
453
470
|
setCheckedItems: (checkedItems: string[]) => void;
|
|
454
471
|
};
|
|
455
472
|
itemInstance: {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
473
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
474
|
+
* this will return immediately. */
|
|
475
|
+
setChecked: () => Promise<void>;
|
|
476
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
477
|
+
* this will return immediately. */
|
|
478
|
+
setUnchecked: () => Promise<void>;
|
|
479
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
480
|
+
* this will return immediately. */
|
|
481
|
+
toggleCheckedState: () => Promise<void>;
|
|
459
482
|
getCheckedState: () => CheckedState;
|
|
460
483
|
getCheckboxProps: () => Record<string, any>;
|
|
484
|
+
isLoadingCheckPropagation: () => boolean;
|
|
461
485
|
};
|
|
462
486
|
hotkeys: never;
|
|
463
487
|
};
|
|
@@ -503,11 +527,11 @@ type HotkeyName = MergedFeatures<RegisteredFeatures<any>>["hotkeys"];
|
|
|
503
527
|
type HotkeysConfig<T> = Record<HotkeyName, HotkeyConfig<T>>;
|
|
504
528
|
type CustomHotkeysConfig<T> = Partial<Record<HotkeyName | `custom${string}`, Partial<HotkeyConfig<T>>>>;
|
|
505
529
|
type MayReturnNull<T extends (...x: any[]) => any> = (...args: Parameters<T>) => ReturnType<T> | null;
|
|
506
|
-
type ItemInstanceOpts<Key extends keyof ItemInstance<any>> = {
|
|
507
|
-
item: ItemInstance<
|
|
508
|
-
tree: TreeInstance<
|
|
530
|
+
type ItemInstanceOpts<T, Key extends keyof ItemInstance<any>> = {
|
|
531
|
+
item: ItemInstance<T>;
|
|
532
|
+
tree: TreeInstance<T>;
|
|
509
533
|
itemId: string;
|
|
510
|
-
prev?: MayReturnNull<ItemInstance<
|
|
534
|
+
prev?: MayReturnNull<ItemInstance<T>[Key]>;
|
|
511
535
|
};
|
|
512
536
|
type TreeInstanceOpts<Key extends keyof TreeInstance<any>> = {
|
|
513
537
|
tree: TreeInstance<any>;
|
|
@@ -524,7 +548,7 @@ type FeatureImplementation<T = any> = {
|
|
|
524
548
|
[key in keyof TreeInstance<T>]?: (opts: TreeInstanceOpts<key>, ...args: Parameters<TreeInstance<T>[key]>) => void;
|
|
525
549
|
};
|
|
526
550
|
itemInstance?: {
|
|
527
|
-
[key in keyof ItemInstance<T>]?: (opts: ItemInstanceOpts<key>, ...args: Parameters<ItemInstance<T>[key]>) => void;
|
|
551
|
+
[key in keyof ItemInstance<T>]?: (opts: ItemInstanceOpts<T, key>, ...args: Parameters<ItemInstance<T>[key]>) => void;
|
|
528
552
|
};
|
|
529
553
|
onTreeMount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
|
|
530
554
|
onTreeUnmount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -75,7 +75,12 @@ type DragAndDropFeatureDef<T> = {
|
|
|
75
75
|
getDragLineStyle: (topOffset?: number, leftOffset?: number) => Record<string, any>;
|
|
76
76
|
};
|
|
77
77
|
itemInstance: {
|
|
78
|
+
/** Checks if the user is dragging in a way which makes this the new parent of the dragged items, either by dragging on top of
|
|
79
|
+
* this item, or by dragging inbetween children of this item. See @{isUnorderedDragTarget} if the latter is undesirable. */
|
|
78
80
|
isDragTarget: () => boolean;
|
|
81
|
+
/** As opposed to @{isDragTarget}, this will not be true if the target is inbetween children of this item. This returns only true
|
|
82
|
+
* if the user is dragging directly on top of this item. */
|
|
83
|
+
isUnorderedDragTarget: () => boolean;
|
|
79
84
|
isDragTargetAbove: () => boolean;
|
|
80
85
|
isDragTargetBelow: () => boolean;
|
|
81
86
|
isDraggingOver: () => boolean;
|
|
@@ -177,6 +182,10 @@ type MainFeatureDef<T = any> = {
|
|
|
177
182
|
};
|
|
178
183
|
getHotkeyPresets: () => HotkeysConfig<T>;
|
|
179
184
|
rebuildTree: () => void;
|
|
185
|
+
/** @deprecated Experimental feature, might get removed or changed in the future. */
|
|
186
|
+
scheduleRebuildTree: () => void;
|
|
187
|
+
/** @internal */
|
|
188
|
+
setMounted: (isMounted: boolean) => void;
|
|
180
189
|
};
|
|
181
190
|
itemInstance: {
|
|
182
191
|
registerElement: (element: HTMLElement | null) => void;
|
|
@@ -259,7 +268,12 @@ type SyncDataLoaderFeatureDef<T> = {
|
|
|
259
268
|
};
|
|
260
269
|
treeInstance: {
|
|
261
270
|
retrieveItemData: (itemId: string) => T;
|
|
262
|
-
|
|
271
|
+
/** Retrieve children Ids. If an async data loader is used, skipFetch is set to true, and children have not been retrieved
|
|
272
|
+
* yet for this item, this will initiate fetching the children, and return an empty array. Once the children have loaded,
|
|
273
|
+
* a rerender will be triggered.
|
|
274
|
+
* @param skipFetch - Defaults to false.
|
|
275
|
+
*/
|
|
276
|
+
retrieveChildrenIds: (itemId: string, skipFetch?: boolean) => string[];
|
|
263
277
|
};
|
|
264
278
|
itemInstance: {
|
|
265
279
|
isLoading: () => boolean;
|
|
@@ -307,7 +321,8 @@ type AsyncDataLoaderFeatureDef<T> = {
|
|
|
307
321
|
* @param optimistic If true, the item will not trigger a state update on `loadingItemChildrens`, and
|
|
308
322
|
* the tree will continue to display the old data until the new data has loaded. */
|
|
309
323
|
invalidateChildrenIds: (optimistic?: boolean) => Promise<void>;
|
|
310
|
-
|
|
324
|
+
/** Set to undefined to clear cache without triggering automatic refetch. Use @invalidateItemData to clear and triggering refetch. */
|
|
325
|
+
updateCachedData: (data: T | undefined) => void;
|
|
311
326
|
updateCachedChildrenIds: (childrenIds: string[]) => void;
|
|
312
327
|
isLoading: () => boolean;
|
|
313
328
|
};
|
|
@@ -443,9 +458,11 @@ declare enum CheckedState {
|
|
|
443
458
|
type CheckboxesFeatureDef<T> = {
|
|
444
459
|
state: {
|
|
445
460
|
checkedItems: string[];
|
|
461
|
+
loadingCheckPropagationItems: string[];
|
|
446
462
|
};
|
|
447
463
|
config: {
|
|
448
464
|
setCheckedItems?: SetStateFn<string[]>;
|
|
465
|
+
setLoadingCheckPropagationItems?: SetStateFn<string[]>;
|
|
449
466
|
canCheckFolders?: boolean;
|
|
450
467
|
propagateCheckedState?: boolean;
|
|
451
468
|
};
|
|
@@ -453,11 +470,18 @@ type CheckboxesFeatureDef<T> = {
|
|
|
453
470
|
setCheckedItems: (checkedItems: string[]) => void;
|
|
454
471
|
};
|
|
455
472
|
itemInstance: {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
473
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
474
|
+
* this will return immediately. */
|
|
475
|
+
setChecked: () => Promise<void>;
|
|
476
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
477
|
+
* this will return immediately. */
|
|
478
|
+
setUnchecked: () => Promise<void>;
|
|
479
|
+
/** Will recursively load descendants if propagateCheckedState=true and async data loader is used. If not,
|
|
480
|
+
* this will return immediately. */
|
|
481
|
+
toggleCheckedState: () => Promise<void>;
|
|
459
482
|
getCheckedState: () => CheckedState;
|
|
460
483
|
getCheckboxProps: () => Record<string, any>;
|
|
484
|
+
isLoadingCheckPropagation: () => boolean;
|
|
461
485
|
};
|
|
462
486
|
hotkeys: never;
|
|
463
487
|
};
|
|
@@ -503,11 +527,11 @@ type HotkeyName = MergedFeatures<RegisteredFeatures<any>>["hotkeys"];
|
|
|
503
527
|
type HotkeysConfig<T> = Record<HotkeyName, HotkeyConfig<T>>;
|
|
504
528
|
type CustomHotkeysConfig<T> = Partial<Record<HotkeyName | `custom${string}`, Partial<HotkeyConfig<T>>>>;
|
|
505
529
|
type MayReturnNull<T extends (...x: any[]) => any> = (...args: Parameters<T>) => ReturnType<T> | null;
|
|
506
|
-
type ItemInstanceOpts<Key extends keyof ItemInstance<any>> = {
|
|
507
|
-
item: ItemInstance<
|
|
508
|
-
tree: TreeInstance<
|
|
530
|
+
type ItemInstanceOpts<T, Key extends keyof ItemInstance<any>> = {
|
|
531
|
+
item: ItemInstance<T>;
|
|
532
|
+
tree: TreeInstance<T>;
|
|
509
533
|
itemId: string;
|
|
510
|
-
prev?: MayReturnNull<ItemInstance<
|
|
534
|
+
prev?: MayReturnNull<ItemInstance<T>[Key]>;
|
|
511
535
|
};
|
|
512
536
|
type TreeInstanceOpts<Key extends keyof TreeInstance<any>> = {
|
|
513
537
|
tree: TreeInstance<any>;
|
|
@@ -524,7 +548,7 @@ type FeatureImplementation<T = any> = {
|
|
|
524
548
|
[key in keyof TreeInstance<T>]?: (opts: TreeInstanceOpts<key>, ...args: Parameters<TreeInstance<T>[key]>) => void;
|
|
525
549
|
};
|
|
526
550
|
itemInstance?: {
|
|
527
|
-
[key in keyof ItemInstance<T>]?: (opts: ItemInstanceOpts<key>, ...args: Parameters<ItemInstance<T>[key]>) => void;
|
|
551
|
+
[key in keyof ItemInstance<T>]?: (opts: ItemInstanceOpts<T, key>, ...args: Parameters<ItemInstance<T>[key]>) => void;
|
|
528
552
|
};
|
|
529
553
|
onTreeMount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
|
|
530
554
|
onTreeUnmount?: (instance: TreeInstance<T>, treeElement: HTMLElement) => void;
|
package/dist/index.js
CHANGED
|
@@ -303,7 +303,7 @@ var treeFeature = {
|
|
|
303
303
|
);
|
|
304
304
|
},
|
|
305
305
|
isFocused: ({ tree, item, itemId }) => tree.getState().focusedItem === itemId || tree.getState().focusedItem === null && item.getItemMeta().index === 0,
|
|
306
|
-
isFolder: ({ tree, item }) =>
|
|
306
|
+
isFolder: ({ tree, item, itemId }) => itemId === tree.getConfig().rootItemId || tree.getConfig().isItemFolder(item),
|
|
307
307
|
getItemName: ({ tree, item }) => {
|
|
308
308
|
const config = tree.getConfig();
|
|
309
309
|
return config.getItemName(item);
|
|
@@ -485,6 +485,7 @@ var createTree = (initialConfig) => {
|
|
|
485
485
|
);
|
|
486
486
|
let treeElement;
|
|
487
487
|
const treeDataRef = { current: {} };
|
|
488
|
+
let rebuildScheduled = false;
|
|
488
489
|
const itemInstancesMap = {};
|
|
489
490
|
let itemInstances = [];
|
|
490
491
|
const itemElementsMap = {};
|
|
@@ -528,6 +529,7 @@ var createTree = (initialConfig) => {
|
|
|
528
529
|
itemInstances.push(itemInstancesMap[item.itemId]);
|
|
529
530
|
}
|
|
530
531
|
}
|
|
532
|
+
rebuildScheduled = false;
|
|
531
533
|
};
|
|
532
534
|
const eachFeature = (fn) => {
|
|
533
535
|
for (const feature of additionalFeatures) {
|
|
@@ -542,16 +544,48 @@ var createTree = (initialConfig) => {
|
|
|
542
544
|
var _a2;
|
|
543
545
|
(_a2 = config.setState) == null ? void 0 : _a2.call(config, state);
|
|
544
546
|
},
|
|
547
|
+
setMounted: ({}, isMounted) => {
|
|
548
|
+
var _a2;
|
|
549
|
+
const ref = treeDataRef.current;
|
|
550
|
+
ref.isMounted = isMounted;
|
|
551
|
+
if (isMounted) {
|
|
552
|
+
(_a2 = ref.waitingForMount) == null ? void 0 : _a2.forEach((cb) => cb());
|
|
553
|
+
ref.waitingForMount = [];
|
|
554
|
+
}
|
|
555
|
+
},
|
|
545
556
|
applySubStateUpdate: ({}, stateName, updater) => {
|
|
546
|
-
|
|
547
|
-
const
|
|
548
|
-
|
|
557
|
+
var _a2;
|
|
558
|
+
const apply = () => {
|
|
559
|
+
state[stateName] = typeof updater === "function" ? updater(state[stateName]) : updater;
|
|
560
|
+
const externalStateSetter = config[stateHandlerNames[stateName]];
|
|
561
|
+
externalStateSetter == null ? void 0 : externalStateSetter(state[stateName]);
|
|
562
|
+
};
|
|
563
|
+
const ref = treeDataRef.current;
|
|
564
|
+
if (ref.isMounted) {
|
|
565
|
+
apply();
|
|
566
|
+
} else {
|
|
567
|
+
(_a2 = ref.waitingForMount) != null ? _a2 : ref.waitingForMount = [];
|
|
568
|
+
ref.waitingForMount.push(apply);
|
|
569
|
+
}
|
|
549
570
|
},
|
|
550
571
|
// TODO rebuildSubTree: (itemId: string) => void;
|
|
551
572
|
rebuildTree: () => {
|
|
552
|
-
var _a2;
|
|
553
|
-
|
|
554
|
-
(
|
|
573
|
+
var _a2, _b2;
|
|
574
|
+
const ref = treeDataRef.current;
|
|
575
|
+
if (ref.isMounted) {
|
|
576
|
+
rebuildItemMeta();
|
|
577
|
+
(_a2 = config.setState) == null ? void 0 : _a2.call(config, state);
|
|
578
|
+
} else {
|
|
579
|
+
(_b2 = ref.waitingForMount) != null ? _b2 : ref.waitingForMount = [];
|
|
580
|
+
ref.waitingForMount.push(() => {
|
|
581
|
+
var _a3;
|
|
582
|
+
rebuildItemMeta();
|
|
583
|
+
(_a3 = config.setState) == null ? void 0 : _a3.call(config, state);
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
scheduleRebuildTree: () => {
|
|
588
|
+
rebuildScheduled = true;
|
|
555
589
|
},
|
|
556
590
|
getConfig: () => config,
|
|
557
591
|
setConfig: (_, updater) => {
|
|
@@ -584,7 +618,10 @@ var createTree = (initialConfig) => {
|
|
|
584
618
|
}
|
|
585
619
|
return existingInstance;
|
|
586
620
|
},
|
|
587
|
-
getItems: () =>
|
|
621
|
+
getItems: () => {
|
|
622
|
+
if (rebuildScheduled) rebuildItemMeta();
|
|
623
|
+
return itemInstances;
|
|
624
|
+
},
|
|
588
625
|
registerElement: ({}, element) => {
|
|
589
626
|
if (treeElement === element) {
|
|
590
627
|
return;
|
|
@@ -817,33 +854,60 @@ var getAllLoadedDescendants = (tree, itemId, includeFolders = false) => {
|
|
|
817
854
|
if (!tree.getConfig().isItemFolder(tree.getItemInstance(itemId))) {
|
|
818
855
|
return [itemId];
|
|
819
856
|
}
|
|
820
|
-
const descendants = tree.retrieveChildrenIds(itemId).map((child) => getAllLoadedDescendants(tree, child, includeFolders)).flat();
|
|
857
|
+
const descendants = tree.retrieveChildrenIds(itemId, true).map((child) => getAllLoadedDescendants(tree, child, includeFolders)).flat();
|
|
821
858
|
return includeFolders ? [itemId, ...descendants] : descendants;
|
|
822
859
|
};
|
|
860
|
+
var getAllDescendants = (tree, itemId, includeFolders = false) => __async(null, null, function* () {
|
|
861
|
+
yield tree.loadItemData(itemId);
|
|
862
|
+
if (!tree.getConfig().isItemFolder(tree.getItemInstance(itemId))) {
|
|
863
|
+
return [itemId];
|
|
864
|
+
}
|
|
865
|
+
const childrenIds = yield tree.loadChildrenIds(itemId);
|
|
866
|
+
const descendants = (yield Promise.all(
|
|
867
|
+
childrenIds.map(
|
|
868
|
+
(child) => getAllDescendants(tree, child, includeFolders)
|
|
869
|
+
)
|
|
870
|
+
)).flat();
|
|
871
|
+
return includeFolders ? [itemId, ...descendants] : descendants;
|
|
872
|
+
});
|
|
873
|
+
var withLoadingState = (tree, itemId, callback) => __async(null, null, function* () {
|
|
874
|
+
tree.applySubStateUpdate("loadingCheckPropagationItems", (items) => [
|
|
875
|
+
...items,
|
|
876
|
+
itemId
|
|
877
|
+
]);
|
|
878
|
+
try {
|
|
879
|
+
yield callback();
|
|
880
|
+
} finally {
|
|
881
|
+
tree.applySubStateUpdate(
|
|
882
|
+
"loadingCheckPropagationItems",
|
|
883
|
+
(items) => items.filter((id) => id !== itemId)
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
});
|
|
823
887
|
var checkboxesFeature = {
|
|
824
888
|
key: "checkboxes",
|
|
825
889
|
overwrites: ["selection"],
|
|
826
890
|
getInitialState: (initialState) => __spreadValues({
|
|
827
|
-
checkedItems: []
|
|
891
|
+
checkedItems: [],
|
|
892
|
+
loadingCheckPropagationItems: []
|
|
828
893
|
}, initialState),
|
|
829
894
|
getDefaultConfig: (defaultConfig, tree) => {
|
|
830
|
-
var _a, _b
|
|
831
|
-
const
|
|
832
|
-
|
|
833
|
-
);
|
|
834
|
-
if (hasAsyncLoader && defaultConfig.propagateCheckedState) {
|
|
835
|
-
throwError(`propagateCheckedState not supported with async trees`);
|
|
836
|
-
}
|
|
837
|
-
const propagateCheckedState = (_b = defaultConfig.propagateCheckedState) != null ? _b : !hasAsyncLoader;
|
|
838
|
-
const canCheckFolders = (_c = defaultConfig.canCheckFolders) != null ? _c : !propagateCheckedState;
|
|
895
|
+
var _a, _b;
|
|
896
|
+
const propagateCheckedState = (_a = defaultConfig.propagateCheckedState) != null ? _a : true;
|
|
897
|
+
const canCheckFolders = (_b = defaultConfig.canCheckFolders) != null ? _b : !propagateCheckedState;
|
|
839
898
|
return __spreadValues({
|
|
840
899
|
setCheckedItems: makeStateUpdater("checkedItems", tree),
|
|
900
|
+
setLoadingCheckPropagationItems: makeStateUpdater(
|
|
901
|
+
"loadingCheckPropagationItems",
|
|
902
|
+
tree
|
|
903
|
+
),
|
|
841
904
|
propagateCheckedState,
|
|
842
905
|
canCheckFolders
|
|
843
906
|
}, defaultConfig);
|
|
844
907
|
},
|
|
845
908
|
stateHandlerNames: {
|
|
846
|
-
checkedItems: "setCheckedItems"
|
|
909
|
+
checkedItems: "setCheckedItems",
|
|
910
|
+
loadingCheckPropagationItems: "setLoadingCheckPropagationItems"
|
|
847
911
|
},
|
|
848
912
|
treeInstance: {
|
|
849
913
|
setCheckedItems: ({ tree }, checkedItems) => {
|
|
@@ -863,13 +927,13 @@ var checkboxesFeature = {
|
|
|
863
927
|
}
|
|
864
928
|
};
|
|
865
929
|
},
|
|
866
|
-
toggleCheckedState: ({ item })
|
|
930
|
+
toggleCheckedState: (_0) => __async(null, [_0], function* ({ item }) {
|
|
867
931
|
if (item.getCheckedState() === "checked" /* Checked */) {
|
|
868
|
-
item.setUnchecked();
|
|
932
|
+
yield item.setUnchecked();
|
|
869
933
|
} else {
|
|
870
|
-
item.setChecked();
|
|
934
|
+
yield item.setChecked();
|
|
871
935
|
}
|
|
872
|
-
},
|
|
936
|
+
}),
|
|
873
937
|
getCheckedState: ({ item, tree }) => {
|
|
874
938
|
const { checkedItems } = tree.getState();
|
|
875
939
|
const { propagateCheckedState } = tree.getConfig();
|
|
@@ -879,6 +943,7 @@ var checkboxesFeature = {
|
|
|
879
943
|
}
|
|
880
944
|
if (item.isFolder() && propagateCheckedState) {
|
|
881
945
|
const descendants = getAllLoadedDescendants(tree, itemId);
|
|
946
|
+
if (descendants.length === 0) return "unchecked" /* Unchecked */;
|
|
882
947
|
if (descendants.every((d) => checkedItems.includes(d))) {
|
|
883
948
|
return "checked" /* Checked */;
|
|
884
949
|
}
|
|
@@ -888,36 +953,48 @@ var checkboxesFeature = {
|
|
|
888
953
|
}
|
|
889
954
|
return "unchecked" /* Unchecked */;
|
|
890
955
|
},
|
|
891
|
-
setChecked: ({ item, tree, itemId })
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
956
|
+
setChecked: (_0) => __async(null, [_0], function* ({ item, tree, itemId }) {
|
|
957
|
+
yield withLoadingState(tree, itemId, () => __async(null, null, function* () {
|
|
958
|
+
const { propagateCheckedState, canCheckFolders } = tree.getConfig();
|
|
959
|
+
if (item.isFolder() && propagateCheckedState) {
|
|
960
|
+
const descendants = yield getAllDescendants(
|
|
961
|
+
tree,
|
|
962
|
+
itemId,
|
|
963
|
+
canCheckFolders
|
|
964
|
+
);
|
|
965
|
+
tree.applySubStateUpdate("checkedItems", (items) => [
|
|
966
|
+
...items,
|
|
967
|
+
...descendants
|
|
968
|
+
]);
|
|
969
|
+
} else if (!item.isFolder() || canCheckFolders) {
|
|
970
|
+
tree.applySubStateUpdate("checkedItems", (items) => [
|
|
971
|
+
...items,
|
|
972
|
+
itemId
|
|
973
|
+
]);
|
|
974
|
+
}
|
|
975
|
+
}));
|
|
976
|
+
}),
|
|
977
|
+
setUnchecked: (_0) => __async(null, [_0], function* ({ item, tree, itemId }) {
|
|
978
|
+
yield withLoadingState(tree, itemId, () => __async(null, null, function* () {
|
|
979
|
+
const { propagateCheckedState, canCheckFolders } = tree.getConfig();
|
|
980
|
+
if (item.isFolder() && propagateCheckedState) {
|
|
981
|
+
const descendants = yield getAllDescendants(
|
|
982
|
+
tree,
|
|
983
|
+
itemId,
|
|
984
|
+
canCheckFolders
|
|
985
|
+
);
|
|
986
|
+
tree.applySubStateUpdate(
|
|
987
|
+
"checkedItems",
|
|
988
|
+
(items) => items.filter((id) => !descendants.includes(id) && id !== itemId)
|
|
989
|
+
);
|
|
990
|
+
} else {
|
|
991
|
+
tree.applySubStateUpdate(
|
|
992
|
+
"checkedItems",
|
|
993
|
+
(items) => items.filter((id) => id !== itemId)
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
}));
|
|
997
|
+
})
|
|
921
998
|
}
|
|
922
999
|
};
|
|
923
1000
|
|
|
@@ -929,7 +1006,9 @@ var specialKeys = {
|
|
|
929
1006
|
plus: /^(NumpadAdd|Plus)$/,
|
|
930
1007
|
minus: /^(NumpadSubtract|Minus)$/,
|
|
931
1008
|
control: /^(ControlLeft|ControlRight)$/,
|
|
932
|
-
shift: /^(ShiftLeft|ShiftRight)
|
|
1009
|
+
shift: /^(ShiftLeft|ShiftRight)$/,
|
|
1010
|
+
metaorcontrol: /^(MetaLeft|MetaRight|ControlLeft|ControlRight)$/,
|
|
1011
|
+
enter: /^(Enter|NumpadEnter)$/
|
|
933
1012
|
};
|
|
934
1013
|
var testHotkeyMatch = (pressedKeys, tree, hotkey) => {
|
|
935
1014
|
const supposedKeys = hotkey.hotkey.toLowerCase().split("+");
|
|
@@ -1034,6 +1113,12 @@ var loadItemData = (tree, itemId) => __async(null, null, function* () {
|
|
|
1034
1113
|
var _a;
|
|
1035
1114
|
const config = tree.getConfig();
|
|
1036
1115
|
const dataRef = getDataRef(tree);
|
|
1116
|
+
if (!dataRef.current.itemData[itemId]) {
|
|
1117
|
+
tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
|
|
1118
|
+
...loadingItemData,
|
|
1119
|
+
itemId
|
|
1120
|
+
]);
|
|
1121
|
+
}
|
|
1037
1122
|
const item = yield config.dataLoader.getItem(itemId);
|
|
1038
1123
|
dataRef.current.itemData[itemId] = item;
|
|
1039
1124
|
(_a = config.onLoadedItem) == null ? void 0 : _a.call(config, itemId, item);
|
|
@@ -1048,6 +1133,12 @@ var loadChildrenIds = (tree, itemId) => __async(null, null, function* () {
|
|
|
1048
1133
|
const config = tree.getConfig();
|
|
1049
1134
|
const dataRef = getDataRef(tree);
|
|
1050
1135
|
let childrenIds;
|
|
1136
|
+
if (!dataRef.current.childrenIds[itemId]) {
|
|
1137
|
+
tree.applySubStateUpdate("loadingItemChildrens", (loadingItemChildrens) => [
|
|
1138
|
+
...loadingItemChildrens,
|
|
1139
|
+
itemId
|
|
1140
|
+
]);
|
|
1141
|
+
}
|
|
1051
1142
|
if ("getChildrenWithData" in config.dataLoader) {
|
|
1052
1143
|
const children = yield config.dataLoader.getChildrenWithData(itemId);
|
|
1053
1144
|
childrenIds = children.map((c) => c.id);
|
|
@@ -1108,11 +1199,7 @@ var asyncDataLoaderFeature = {
|
|
|
1108
1199
|
return dataRef.current.itemData[itemId];
|
|
1109
1200
|
}
|
|
1110
1201
|
if (!tree.getState().loadingItemData.includes(itemId) && !skipFetch) {
|
|
1111
|
-
|
|
1112
|
-
...loadingItemData,
|
|
1113
|
-
itemId
|
|
1114
|
-
]);
|
|
1115
|
-
loadItemData(tree, itemId);
|
|
1202
|
+
setTimeout(() => loadItemData(tree, itemId));
|
|
1116
1203
|
}
|
|
1117
1204
|
return (_b = (_a = config.createLoadingItemData) == null ? void 0 : _a.call(config)) != null ? _b : null;
|
|
1118
1205
|
},
|
|
@@ -1124,11 +1211,7 @@ var asyncDataLoaderFeature = {
|
|
|
1124
1211
|
if (tree.getState().loadingItemChildrens.includes(itemId) || skipFetch) {
|
|
1125
1212
|
return [];
|
|
1126
1213
|
}
|
|
1127
|
-
tree
|
|
1128
|
-
"loadingItemChildrens",
|
|
1129
|
-
(loadingItemChildrens) => [...loadingItemChildrens, itemId]
|
|
1130
|
-
);
|
|
1131
|
-
loadChildrenIds(tree, itemId);
|
|
1214
|
+
setTimeout(() => loadChildrenIds(tree, itemId));
|
|
1132
1215
|
return [];
|
|
1133
1216
|
}
|
|
1134
1217
|
},
|
|
@@ -1138,10 +1221,6 @@ var asyncDataLoaderFeature = {
|
|
|
1138
1221
|
var _a;
|
|
1139
1222
|
if (!optimistic) {
|
|
1140
1223
|
(_a = getDataRef(tree).current.itemData) == null ? true : delete _a[itemId];
|
|
1141
|
-
tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
|
|
1142
|
-
...loadingItemData,
|
|
1143
|
-
itemId
|
|
1144
|
-
]);
|
|
1145
1224
|
}
|
|
1146
1225
|
yield loadItemData(tree, itemId);
|
|
1147
1226
|
}),
|
|
@@ -1149,10 +1228,6 @@ var asyncDataLoaderFeature = {
|
|
|
1149
1228
|
var _a;
|
|
1150
1229
|
if (!optimistic) {
|
|
1151
1230
|
(_a = getDataRef(tree).current.childrenIds) == null ? true : delete _a[itemId];
|
|
1152
|
-
tree.applySubStateUpdate(
|
|
1153
|
-
"loadingItemChildrens",
|
|
1154
|
-
(loadingItemChildrens) => [...loadingItemChildrens, itemId]
|
|
1155
|
-
);
|
|
1156
1231
|
}
|
|
1157
1232
|
yield loadChildrenIds(tree, itemId);
|
|
1158
1233
|
}),
|
|
@@ -1604,6 +1679,10 @@ var dragAndDropFeature = {
|
|
|
1604
1679
|
const target = tree.getDragTarget();
|
|
1605
1680
|
return target ? target.item.getId() === item.getId() : false;
|
|
1606
1681
|
},
|
|
1682
|
+
isUnorderedDragTarget: ({ tree, item }) => {
|
|
1683
|
+
const target = tree.getDragTarget();
|
|
1684
|
+
return target ? !isOrderedDragTarget(target) && target.item.getId() === item.getId() : false;
|
|
1685
|
+
},
|
|
1607
1686
|
isDragTargetAbove: ({ tree, item }) => {
|
|
1608
1687
|
const target = tree.getDragTarget();
|
|
1609
1688
|
if (!target || !isOrderedDragTarget(target) || target.item !== item.getParent())
|