@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 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
- retrieveChildrenIds: (itemId: string) => string[];
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
- updateCachedData: (data: T) => void;
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
- setChecked: () => void;
457
- setUnchecked: () => void;
458
- toggleCheckedState: () => void;
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<any>;
508
- tree: TreeInstance<any>;
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<any>[Key]>;
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
- retrieveChildrenIds: (itemId: string) => string[];
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
- updateCachedData: (data: T) => void;
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
- setChecked: () => void;
457
- setUnchecked: () => void;
458
- toggleCheckedState: () => void;
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<any>;
508
- tree: TreeInstance<any>;
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<any>[Key]>;
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 }) => item.getItemMeta().level === -1 || tree.getConfig().isItemFolder(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
- state[stateName] = typeof updater === "function" ? updater(state[stateName]) : updater;
547
- const externalStateSetter = config[stateHandlerNames[stateName]];
548
- externalStateSetter == null ? void 0 : externalStateSetter(state[stateName]);
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
- rebuildItemMeta();
554
- (_a2 = config.setState) == null ? void 0 : _a2.call(config, state);
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: () => itemInstances,
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, _c;
831
- const hasAsyncLoader = (_a = defaultConfig.features) == null ? void 0 : _a.some(
832
- (f) => f.key === "async-data-loader"
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
- const { propagateCheckedState, canCheckFolders } = tree.getConfig();
893
- if (item.isFolder() && propagateCheckedState) {
894
- tree.applySubStateUpdate("checkedItems", (items) => [
895
- ...items,
896
- ...getAllLoadedDescendants(tree, itemId, canCheckFolders)
897
- ]);
898
- } else if (!item.isFolder() || canCheckFolders) {
899
- tree.applySubStateUpdate("checkedItems", (items) => [...items, itemId]);
900
- }
901
- },
902
- setUnchecked: ({ item, tree, itemId }) => {
903
- const { propagateCheckedState, canCheckFolders } = tree.getConfig();
904
- if (item.isFolder() && propagateCheckedState) {
905
- const descendants = getAllLoadedDescendants(
906
- tree,
907
- itemId,
908
- canCheckFolders
909
- );
910
- tree.applySubStateUpdate(
911
- "checkedItems",
912
- (items) => items.filter((id) => !descendants.includes(id) && id !== itemId)
913
- );
914
- } else {
915
- tree.applySubStateUpdate(
916
- "checkedItems",
917
- (items) => items.filter((id) => id !== itemId)
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
- tree.applySubStateUpdate("loadingItemData", (loadingItemData) => [
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.applySubStateUpdate(
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())