@headless-tree/core 0.0.0-20250322153940 → 0.0.0-20250330164609
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 +2 -1
- package/lib/cjs/features/drag-and-drop/feature.js +11 -11
- package/lib/cjs/features/drag-and-drop/types.d.ts +11 -11
- package/lib/cjs/features/drag-and-drop/types.js +7 -7
- package/lib/cjs/features/drag-and-drop/utils.d.ts +18 -3
- package/lib/cjs/features/drag-and-drop/utils.js +42 -30
- package/lib/cjs/features/hotkeys-core/feature.js +1 -0
- package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +2 -0
- package/lib/cjs/features/keyboard-drag-and-drop/feature.js +207 -0
- package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +27 -0
- package/lib/cjs/features/keyboard-drag-and-drop/types.js +11 -0
- package/lib/cjs/index.d.ts +2 -0
- package/lib/cjs/index.js +2 -0
- package/lib/cjs/mddocs-entry.d.ts +10 -0
- package/lib/cjs/test-utils/test-tree-expect.d.ts +5 -3
- package/lib/cjs/test-utils/test-tree-expect.js +3 -0
- package/lib/cjs/types/core.d.ts +2 -1
- package/lib/cjs/utilities/create-on-drop-handler.d.ts +2 -2
- package/lib/cjs/utilities/insert-items-at-target.d.ts +2 -2
- package/lib/esm/features/drag-and-drop/feature.js +12 -12
- package/lib/esm/features/drag-and-drop/types.d.ts +11 -11
- package/lib/esm/features/drag-and-drop/types.js +6 -6
- package/lib/esm/features/drag-and-drop/utils.d.ts +18 -3
- package/lib/esm/features/drag-and-drop/utils.js +37 -28
- package/lib/esm/features/hotkeys-core/feature.js +1 -0
- package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +2 -0
- package/lib/esm/features/keyboard-drag-and-drop/feature.js +204 -0
- package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +27 -0
- package/lib/esm/features/keyboard-drag-and-drop/types.js +8 -0
- package/lib/esm/index.d.ts +2 -0
- package/lib/esm/index.js +2 -0
- package/lib/esm/mddocs-entry.d.ts +10 -0
- package/lib/esm/test-utils/test-tree-expect.d.ts +5 -3
- package/lib/esm/test-utils/test-tree-expect.js +3 -0
- package/lib/esm/types/core.d.ts +2 -1
- package/lib/esm/utilities/create-on-drop-handler.d.ts +2 -2
- package/lib/esm/utilities/insert-items-at-target.d.ts +2 -2
- package/package.json +1 -1
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +6 -6
- package/src/features/drag-and-drop/feature.ts +12 -12
- package/src/features/drag-and-drop/types.ts +11 -11
- package/src/features/drag-and-drop/utils.ts +64 -39
- package/src/features/hotkeys-core/feature.ts +1 -0
- package/src/features/keyboard-drag-and-drop/feature.ts +255 -0
- package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +401 -0
- package/src/features/keyboard-drag-and-drop/types.ts +30 -0
- package/src/index.ts +2 -0
- package/src/mddocs-entry.ts +16 -0
- package/src/test-utils/test-tree-expect.ts +7 -2
- package/src/types/core.ts +2 -0
- package/src/utilities/create-on-drop-handler.ts +2 -2
- package/src/utilities/insert-items-at-target.ts +2 -2
package/lib/esm/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./types/core";
|
|
|
2
2
|
export * from "./core/create-tree";
|
|
3
3
|
export * from "./features/tree/types";
|
|
4
4
|
export * from "./features/drag-and-drop/types";
|
|
5
|
+
export * from "./features/keyboard-drag-and-drop/types";
|
|
5
6
|
export * from "./features/selection/types";
|
|
6
7
|
export * from "./features/async-data-loader/types";
|
|
7
8
|
export * from "./features/sync-data-loader/types";
|
|
@@ -15,6 +16,7 @@ export * from "./features/hotkeys-core/feature";
|
|
|
15
16
|
export * from "./features/async-data-loader/feature";
|
|
16
17
|
export * from "./features/sync-data-loader/feature";
|
|
17
18
|
export * from "./features/drag-and-drop/feature";
|
|
19
|
+
export * from "./features/keyboard-drag-and-drop/feature";
|
|
18
20
|
export * from "./features/search/feature";
|
|
19
21
|
export * from "./features/renaming/feature";
|
|
20
22
|
export * from "./features/expand-all/feature";
|
|
@@ -9,6 +9,7 @@ import { SelectionFeatureDef } from "./features/selection/types";
|
|
|
9
9
|
import { SyncDataLoaderFeatureDef } from "./features/sync-data-loader/types";
|
|
10
10
|
import { TreeFeatureDef } from "./features/tree/types";
|
|
11
11
|
import { PropMemoizationFeatureDef } from "./features/prop-memoization/types";
|
|
12
|
+
import { KeyboardDragAndDropFeatureDef } from "./features/keyboard-drag-and-drop/types";
|
|
12
13
|
export * from ".";
|
|
13
14
|
/** @interface */
|
|
14
15
|
export type AsyncDataLoaderFeatureConfig<T> = AsyncDataLoaderFeatureDef<T>["config"];
|
|
@@ -29,6 +30,15 @@ export type DragAndDropFeatureTreeInstance<T> = DragAndDropFeatureDef<T>["treeIn
|
|
|
29
30
|
export type DragAndDropFeatureItemInstance<T> = DragAndDropFeatureDef<T>["itemInstance"];
|
|
30
31
|
export type DragAndDropFeatureHotkeys<T> = DragAndDropFeatureDef<T>["hotkeys"];
|
|
31
32
|
/** @interface */
|
|
33
|
+
export type KeyboardDragAndDropFeatureConfig<T> = KeyboardDragAndDropFeatureDef<T>["config"];
|
|
34
|
+
/** @interface */
|
|
35
|
+
export type KeyboardDragAndDropFeatureState<T> = KeyboardDragAndDropFeatureDef<T>["state"];
|
|
36
|
+
/** @interface */
|
|
37
|
+
export type KeyboardDragAndDropFeatureTreeInstance<T> = KeyboardDragAndDropFeatureDef<T>["treeInstance"];
|
|
38
|
+
/** @interface */
|
|
39
|
+
export type KeyboardDragAndDropFeatureItemInstance<T> = KeyboardDragAndDropFeatureDef<T>["itemInstance"];
|
|
40
|
+
export type KeyboardDragAndDropFeatureHotkeys<T> = KeyboardDragAndDropFeatureDef<T>["hotkeys"];
|
|
41
|
+
/** @interface */
|
|
32
42
|
export type ExpandAllFeatureConfig = ExpandAllFeatureDef["config"];
|
|
33
43
|
/** @interface */
|
|
34
44
|
export type ExpandAllFeatureState = ExpandAllFeatureDef["state"];
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { DragEvent } from "react";
|
|
2
2
|
import { TestTree } from "./test-tree";
|
|
3
|
-
import {
|
|
3
|
+
import { DragTarget } from "../features/drag-and-drop/types";
|
|
4
|
+
import { TreeState } from "../types/core";
|
|
4
5
|
export declare class TestTreeExpect<T> {
|
|
5
6
|
private tree;
|
|
6
|
-
protected itemInstance(itemId: string): import("
|
|
7
|
+
protected itemInstance(itemId: string): import("../types/core").ItemInstance<T>;
|
|
7
8
|
protected itemProps(itemId: string): Record<string, any>;
|
|
8
9
|
constructor(tree: TestTree<T>);
|
|
9
10
|
foldersExpanded(...itemIds: string[]): void;
|
|
10
11
|
foldersCollapsed(...itemIds: string[]): void;
|
|
11
12
|
hasChildren(itemId: string, children: string[]): void;
|
|
12
|
-
|
|
13
|
+
substate<K extends keyof TreeState<T>>(key: K, value: TreeState<T>[K]): void;
|
|
14
|
+
dropped(draggedItems: string[], target: DragTarget<any>): void;
|
|
13
15
|
dragOverNotAllowed(itemId: string, event?: DragEvent): DragEvent<Element>;
|
|
14
16
|
defaultDragLineProps(indent?: number): void;
|
|
15
17
|
}
|
|
@@ -26,6 +26,9 @@ export class TestTreeExpect {
|
|
|
26
26
|
const itemChildren = item.getChildren().map((child) => child.getId());
|
|
27
27
|
expect(itemChildren).toEqual(children);
|
|
28
28
|
}
|
|
29
|
+
substate(key, value) {
|
|
30
|
+
expect(this.tree.instance.getState()[key]).toEqual(value);
|
|
31
|
+
}
|
|
29
32
|
dropped(draggedItems, target) {
|
|
30
33
|
expect(this.tree.instance.getConfig().onDrop).toBeCalledWith(draggedItems.map((id) => this.tree.item(id)), target);
|
|
31
34
|
}
|
package/lib/esm/types/core.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { SearchFeatureDef } from "../features/search/types";
|
|
|
9
9
|
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
|
+
import { KeyboardDragAndDropFeatureDef } from "../features/keyboard-drag-and-drop/types";
|
|
12
13
|
export type Updater<T> = T | ((old: T) => T);
|
|
13
14
|
export type SetStateFn<T> = (updaterOrValue: Updater<T>) => void;
|
|
14
15
|
export type FeatureDef = {
|
|
@@ -33,7 +34,7 @@ type MergedFeatures<F extends FeatureDef> = {
|
|
|
33
34
|
itemInstance: UnionToIntersection<F["itemInstance"]>;
|
|
34
35
|
hotkeys: F["hotkeys"];
|
|
35
36
|
};
|
|
36
|
-
export type RegisteredFeatures<T> = MainFeatureDef<T> | TreeFeatureDef<T> | SelectionFeatureDef<T> | DragAndDropFeatureDef<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;
|
|
37
38
|
type TreeStateType<T> = MergedFeatures<RegisteredFeatures<T>>["state"];
|
|
38
39
|
export interface TreeState<T> extends TreeStateType<T> {
|
|
39
40
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ItemInstance } from "../types/core";
|
|
2
|
-
import {
|
|
3
|
-
export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target:
|
|
2
|
+
import { DragTarget } from "../features/drag-and-drop/types";
|
|
3
|
+
export declare const createOnDropHandler: <T>(onChangeChildren: (item: ItemInstance<T>, newChildren: string[]) => void) => (items: ItemInstance<T>[], target: DragTarget<T>) => Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ItemInstance } from "../types/core";
|
|
2
|
-
import {
|
|
3
|
-
export declare const insertItemsAtTarget: <T>(itemIds: string[], target:
|
|
2
|
+
import { DragTarget } from "../features/drag-and-drop/types";
|
|
3
|
+
export declare const insertItemsAtTarget: <T>(itemIds: string[], target: DragTarget<T>, onChangeChildren: (item: ItemInstance<T>, newChildrenIds: string[]) => Promise<void> | void) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -648,20 +648,20 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
648
648
|
});
|
|
649
649
|
|
|
650
650
|
describe("item instance methods", () => {
|
|
651
|
-
it("returns
|
|
651
|
+
it("returns isDragTarget() correct for folders", () => {
|
|
652
652
|
tree.do.startDrag("x111");
|
|
653
653
|
tree.do.dragOver("x21");
|
|
654
|
-
expect(tree.instance.getItemInstance("x21").
|
|
655
|
-
expect(tree.instance.getItemInstance("x211").
|
|
654
|
+
expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
|
|
655
|
+
expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
|
|
656
656
|
false,
|
|
657
657
|
);
|
|
658
658
|
});
|
|
659
659
|
|
|
660
|
-
it("returns
|
|
660
|
+
it("returns isDragTarget() correct for items", () => {
|
|
661
661
|
tree.do.startDrag("x111");
|
|
662
662
|
tree.do.dragOver("x211");
|
|
663
|
-
expect(tree.instance.getItemInstance("x21").
|
|
664
|
-
expect(tree.instance.getItemInstance("x211").
|
|
663
|
+
expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
|
|
664
|
+
expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
|
|
665
665
|
false,
|
|
666
666
|
);
|
|
667
667
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FeatureImplementation } from "../../types/core";
|
|
2
2
|
import { DndDataRef, DragLineData } from "./types";
|
|
3
|
-
import { canDrop, getDragCode,
|
|
3
|
+
import { canDrop, getDragCode, getDragTarget } from "./utils";
|
|
4
4
|
import { makeStateUpdater } from "../../utils";
|
|
5
5
|
|
|
6
6
|
export const dragAndDropFeature: FeatureImplementation = {
|
|
@@ -20,12 +20,12 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
20
20
|
},
|
|
21
21
|
|
|
22
22
|
treeInstance: {
|
|
23
|
-
|
|
23
|
+
getDragTarget: ({ tree }) => {
|
|
24
24
|
return tree.getState().dnd?.dragTarget ?? null;
|
|
25
25
|
},
|
|
26
26
|
|
|
27
27
|
getDragLineData: ({ tree }): DragLineData | null => {
|
|
28
|
-
const target = tree.
|
|
28
|
+
const target = tree.getDragTarget();
|
|
29
29
|
const indent = (target?.item.getItemMeta().level ?? 0) + 1;
|
|
30
30
|
|
|
31
31
|
const treeBb = tree.getElement()?.getBoundingClientRect();
|
|
@@ -44,7 +44,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
44
44
|
if (bb) {
|
|
45
45
|
return {
|
|
46
46
|
indent,
|
|
47
|
-
top: bb.bottom - treeBb.
|
|
47
|
+
top: bb.bottom - treeBb.top,
|
|
48
48
|
left: bb.left + leftOffset - treeBb.left,
|
|
49
49
|
width: bb.width - leftOffset,
|
|
50
50
|
};
|
|
@@ -131,7 +131,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
131
131
|
}
|
|
132
132
|
dataRef.current.lastDragCode = nextDragCode;
|
|
133
133
|
|
|
134
|
-
const target =
|
|
134
|
+
const target = getDragTarget(e, item, tree);
|
|
135
135
|
|
|
136
136
|
if (
|
|
137
137
|
!tree.getState().dnd?.draggedItems &&
|
|
@@ -181,7 +181,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
181
181
|
|
|
182
182
|
onDrop: async (e: DragEvent) => {
|
|
183
183
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
184
|
-
const target =
|
|
184
|
+
const target = getDragTarget(e, item, tree);
|
|
185
185
|
|
|
186
186
|
if (!canDrop(e.dataTransfer, target, tree)) {
|
|
187
187
|
return;
|
|
@@ -202,13 +202,13 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
202
202
|
},
|
|
203
203
|
}),
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
const target = tree.
|
|
205
|
+
isDragTarget: ({ tree, item }) => {
|
|
206
|
+
const target = tree.getDragTarget();
|
|
207
207
|
return target ? target.item.getId() === item.getId() : false;
|
|
208
208
|
},
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
const target = tree.
|
|
210
|
+
isDragTargetAbove: ({ tree, item }) => {
|
|
211
|
+
const target = tree.getDragTarget();
|
|
212
212
|
|
|
213
213
|
if (
|
|
214
214
|
!target ||
|
|
@@ -219,8 +219,8 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
219
219
|
return target.childIndex === item.getItemMeta().posInSet;
|
|
220
220
|
},
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
const target = tree.
|
|
222
|
+
isDragTargetBelow: ({ tree, item }) => {
|
|
223
|
+
const target = tree.getDragTarget();
|
|
224
224
|
|
|
225
225
|
if (
|
|
226
226
|
!target ||
|
|
@@ -8,7 +8,7 @@ export interface DndDataRef {
|
|
|
8
8
|
export interface DndState<T> {
|
|
9
9
|
draggedItems?: ItemInstance<T>[];
|
|
10
10
|
draggingOverItem?: ItemInstance<T>;
|
|
11
|
-
dragTarget?:
|
|
11
|
+
dragTarget?: DragTarget<T>;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export interface DragLineData {
|
|
@@ -18,7 +18,7 @@ export interface DragLineData {
|
|
|
18
18
|
width: number;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export type
|
|
21
|
+
export type DragTarget<T> =
|
|
22
22
|
| {
|
|
23
23
|
item: ItemInstance<T>;
|
|
24
24
|
childIndex: number;
|
|
@@ -30,7 +30,7 @@ export type DropTarget<T> =
|
|
|
30
30
|
item: ItemInstance<T>;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export enum
|
|
33
|
+
export enum DragTargetPosition {
|
|
34
34
|
Top = "top",
|
|
35
35
|
Bottom = "bottom",
|
|
36
36
|
Item = "item",
|
|
@@ -50,7 +50,7 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
50
50
|
canReorder?: boolean;
|
|
51
51
|
|
|
52
52
|
canDrag?: (items: ItemInstance<T>[]) => boolean;
|
|
53
|
-
canDrop?: (items: ItemInstance<T>[], target:
|
|
53
|
+
canDrop?: (items: ItemInstance<T>[], target: DragTarget<T>) => boolean;
|
|
54
54
|
|
|
55
55
|
indent?: number;
|
|
56
56
|
|
|
@@ -60,20 +60,20 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
60
60
|
};
|
|
61
61
|
canDropForeignDragObject?: (
|
|
62
62
|
dataTransfer: DataTransfer,
|
|
63
|
-
target:
|
|
63
|
+
target: DragTarget<T>,
|
|
64
64
|
) => boolean;
|
|
65
65
|
onDrop?: (
|
|
66
66
|
items: ItemInstance<T>[],
|
|
67
|
-
target:
|
|
67
|
+
target: DragTarget<T>,
|
|
68
68
|
) => void | Promise<void>;
|
|
69
69
|
onDropForeignDragObject?: (
|
|
70
70
|
dataTransfer: DataTransfer,
|
|
71
|
-
target:
|
|
71
|
+
target: DragTarget<T>,
|
|
72
72
|
) => void | Promise<void>;
|
|
73
73
|
onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
|
|
74
74
|
};
|
|
75
75
|
treeInstance: {
|
|
76
|
-
|
|
76
|
+
getDragTarget: () => DragTarget<T> | null;
|
|
77
77
|
getDragLineData: () => DragLineData | null;
|
|
78
78
|
|
|
79
79
|
getDragLineStyle: (
|
|
@@ -82,9 +82,9 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
82
82
|
) => Record<string, any>;
|
|
83
83
|
};
|
|
84
84
|
itemInstance: {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
isDragTarget: () => boolean;
|
|
86
|
+
isDragTargetAbove: () => boolean;
|
|
87
|
+
isDragTargetBelow: () => boolean;
|
|
88
88
|
isDraggingOver: () => boolean;
|
|
89
89
|
};
|
|
90
90
|
hotkeys: never;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ItemInstance, TreeInstance } from "../../types/core";
|
|
2
|
-
import {
|
|
2
|
+
import { DragTarget } from "./types";
|
|
3
3
|
|
|
4
|
-
enum ItemDropCategory {
|
|
4
|
+
export enum ItemDropCategory {
|
|
5
5
|
Item,
|
|
6
6
|
ExpandedFolder,
|
|
7
7
|
LastInGroup,
|
|
@@ -28,7 +28,7 @@ type TargetPlacement =
|
|
|
28
28
|
|
|
29
29
|
export const canDrop = (
|
|
30
30
|
dataTransfer: DataTransfer | null,
|
|
31
|
-
target:
|
|
31
|
+
target: DragTarget<any>,
|
|
32
32
|
tree: TreeInstance<any>,
|
|
33
33
|
) => {
|
|
34
34
|
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
@@ -52,7 +52,8 @@ export const canDrop = (
|
|
|
52
52
|
if (
|
|
53
53
|
!draggedItems &&
|
|
54
54
|
dataTransfer &&
|
|
55
|
-
|
|
55
|
+
config.canDropForeignDragObject &&
|
|
56
|
+
!config.canDropForeignDragObject(dataTransfer, target)
|
|
56
57
|
) {
|
|
57
58
|
return false;
|
|
58
59
|
}
|
|
@@ -60,7 +61,7 @@ export const canDrop = (
|
|
|
60
61
|
return true;
|
|
61
62
|
};
|
|
62
63
|
|
|
63
|
-
const getItemDropCategory = (item: ItemInstance<any>) => {
|
|
64
|
+
export const getItemDropCategory = (item: ItemInstance<any>) => {
|
|
64
65
|
if (item.isExpanded()) {
|
|
65
66
|
return ItemDropCategory.ExpandedFolder;
|
|
66
67
|
}
|
|
@@ -73,6 +74,24 @@ const getItemDropCategory = (item: ItemInstance<any>) => {
|
|
|
73
74
|
return ItemDropCategory.Item;
|
|
74
75
|
};
|
|
75
76
|
|
|
77
|
+
export const getInsertionIndex = <T>(
|
|
78
|
+
children: ItemInstance<T>[],
|
|
79
|
+
childIndex: number,
|
|
80
|
+
draggedItems: ItemInstance<T>[] | undefined,
|
|
81
|
+
) => {
|
|
82
|
+
const numberOfDragItemsBeforeTarget =
|
|
83
|
+
children
|
|
84
|
+
.slice(0, childIndex)
|
|
85
|
+
.reduce(
|
|
86
|
+
(counter, child) =>
|
|
87
|
+
child && draggedItems?.some((i) => i.getId() === child.getId())
|
|
88
|
+
? ++counter
|
|
89
|
+
: counter,
|
|
90
|
+
0,
|
|
91
|
+
) ?? 0;
|
|
92
|
+
return childIndex - numberOfDragItemsBeforeTarget;
|
|
93
|
+
};
|
|
94
|
+
|
|
76
95
|
const getTargetPlacement = (
|
|
77
96
|
e: any,
|
|
78
97
|
item: ItemInstance<any>,
|
|
@@ -153,17 +172,43 @@ const getNthParent = (
|
|
|
153
172
|
return getNthParent(item.getParent()!, n);
|
|
154
173
|
};
|
|
155
174
|
|
|
156
|
-
|
|
175
|
+
/** @param item refers to the bottom-most item of the container, at which bottom is being reparented on (e.g. root-1-2-6) */
|
|
176
|
+
export const getReparentTarget = <T>(
|
|
177
|
+
item: ItemInstance<T>,
|
|
178
|
+
reparentLevel: number,
|
|
179
|
+
draggedItems: ItemInstance<T>[] | undefined,
|
|
180
|
+
) => {
|
|
181
|
+
const itemMeta = item.getItemMeta();
|
|
182
|
+
const reparentedTarget = getNthParent(item, reparentLevel - 1);
|
|
183
|
+
const targetItemAbove = getNthParent(item, reparentLevel); // .getItemBelow()!;
|
|
184
|
+
const targetIndex = targetItemAbove.getIndexInParent() + 1;
|
|
185
|
+
|
|
186
|
+
// TODO possibly count items dragged out above the new target
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
item: reparentedTarget,
|
|
190
|
+
childIndex: targetIndex,
|
|
191
|
+
insertionIndex: getInsertionIndex(
|
|
192
|
+
reparentedTarget.getChildren(),
|
|
193
|
+
targetIndex,
|
|
194
|
+
draggedItems,
|
|
195
|
+
),
|
|
196
|
+
dragLineIndex: itemMeta.index + 1,
|
|
197
|
+
dragLineLevel: reparentLevel,
|
|
198
|
+
};
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const getDragTarget = (
|
|
157
202
|
e: any,
|
|
158
203
|
item: ItemInstance<any>,
|
|
159
204
|
tree: TreeInstance<any>,
|
|
160
205
|
canReorder = tree.getConfig().canReorder,
|
|
161
|
-
):
|
|
162
|
-
const draggedItems = tree.getState().dnd?.draggedItems
|
|
206
|
+
): DragTarget<any> => {
|
|
207
|
+
const draggedItems = tree.getState().dnd?.draggedItems;
|
|
163
208
|
const itemMeta = item.getItemMeta();
|
|
164
209
|
const parent = item.getParent();
|
|
165
|
-
const itemTarget:
|
|
166
|
-
const parentTarget:
|
|
210
|
+
const itemTarget: DragTarget<any> = { item };
|
|
211
|
+
const parentTarget: DragTarget<any> | null = parent ? { item: parent } : null;
|
|
167
212
|
const canBecomeSibling =
|
|
168
213
|
parentTarget && canDrop(e.dataTransfer, parentTarget, tree);
|
|
169
214
|
|
|
@@ -180,8 +225,8 @@ export const getDropTarget = (
|
|
|
180
225
|
}
|
|
181
226
|
|
|
182
227
|
if (!canReorder && parent && !canBecomeSibling) {
|
|
183
|
-
// TODO! this breaks in story DND/Can Drop. Maybe move this logic into a composable
|
|
184
|
-
return
|
|
228
|
+
// TODO! this breaks in story DND/Can Drop. Maybe move this logic into a composable DragTargetStrategy[] ?
|
|
229
|
+
return getDragTarget(e, parent, tree, false);
|
|
185
230
|
}
|
|
186
231
|
|
|
187
232
|
if (!parent) {
|
|
@@ -194,47 +239,27 @@ export const getDropTarget = (
|
|
|
194
239
|
}
|
|
195
240
|
|
|
196
241
|
if (!canBecomeSibling) {
|
|
197
|
-
return
|
|
242
|
+
return getDragTarget(e, parent, tree, false);
|
|
198
243
|
}
|
|
199
244
|
|
|
200
245
|
if (placement.type === PlacementType.Reparent) {
|
|
201
|
-
|
|
202
|
-
const targetItemAbove = getNthParent(item, placement.reparentLevel); // .getItemBelow()!;
|
|
203
|
-
const targetIndex = targetItemAbove.getIndexInParent() + 1;
|
|
204
|
-
|
|
205
|
-
// TODO possibly count items dragged out above the new target
|
|
206
|
-
|
|
207
|
-
return {
|
|
208
|
-
item: reparentedTarget,
|
|
209
|
-
childIndex: targetIndex,
|
|
210
|
-
insertionIndex: targetIndex,
|
|
211
|
-
dragLineIndex: itemMeta.index + 1,
|
|
212
|
-
dragLineLevel: placement.reparentLevel,
|
|
213
|
-
};
|
|
246
|
+
return getReparentTarget(item, placement.reparentLevel, draggedItems);
|
|
214
247
|
}
|
|
215
248
|
|
|
216
249
|
const maybeAddOneForBelow =
|
|
217
250
|
placement.type === PlacementType.ReorderAbove ? 0 : 1;
|
|
218
251
|
const childIndex = item.getIndexInParent() + maybeAddOneForBelow;
|
|
219
252
|
|
|
220
|
-
const numberOfDragItemsBeforeTarget =
|
|
221
|
-
parent
|
|
222
|
-
.getChildren()
|
|
223
|
-
.slice(0, childIndex)
|
|
224
|
-
.reduce(
|
|
225
|
-
(counter, child) =>
|
|
226
|
-
child && draggedItems?.some((i) => i.getId() === child.getId())
|
|
227
|
-
? ++counter
|
|
228
|
-
: counter,
|
|
229
|
-
0,
|
|
230
|
-
) ?? 0;
|
|
231
|
-
|
|
232
253
|
return {
|
|
233
254
|
item: parent,
|
|
234
255
|
dragLineIndex: itemMeta.index + maybeAddOneForBelow,
|
|
235
256
|
dragLineLevel: itemMeta.level,
|
|
236
257
|
childIndex,
|
|
237
258
|
// TODO performance could be improved by computing this only when dragcode changed
|
|
238
|
-
insertionIndex:
|
|
259
|
+
insertionIndex: getInsertionIndex(
|
|
260
|
+
parent.getChildren(),
|
|
261
|
+
childIndex,
|
|
262
|
+
draggedItems,
|
|
263
|
+
),
|
|
239
264
|
};
|
|
240
265
|
};
|
|
@@ -48,6 +48,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
|
|
|
48
48
|
data.current.pressedKeys ??= new Set();
|
|
49
49
|
const newMatch = !data.current.pressedKeys.has(e.key);
|
|
50
50
|
data.current.pressedKeys.add(e.key);
|
|
51
|
+
console.log("HOTKEYS", data.current.pressedKeys);
|
|
51
52
|
|
|
52
53
|
const hotkeyName = findHotkeyMatch(
|
|
53
54
|
data.current.pressedKeys,
|