@headless-tree/core 0.0.0-20250224211405 → 0.0.0-20250322153940
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 +7 -1
- package/lib/cjs/core/create-tree.js +13 -4
- package/lib/cjs/features/async-data-loader/feature.js +73 -48
- package/lib/cjs/features/async-data-loader/types.d.ts +17 -14
- package/lib/cjs/features/drag-and-drop/feature.js +89 -84
- package/lib/cjs/features/drag-and-drop/types.d.ts +8 -20
- package/lib/cjs/features/drag-and-drop/utils.js +8 -21
- package/lib/cjs/features/expand-all/feature.js +26 -3
- package/lib/cjs/features/expand-all/types.d.ts +3 -1
- package/lib/cjs/features/hotkeys-core/feature.js +6 -3
- package/lib/cjs/features/hotkeys-core/types.d.ts +4 -5
- package/lib/cjs/features/prop-memoization/feature.js +2 -2
- package/lib/cjs/features/prop-memoization/types.d.ts +2 -2
- package/lib/cjs/features/renaming/feature.js +1 -1
- package/lib/cjs/features/search/feature.js +2 -0
- package/lib/cjs/features/search/types.d.ts +2 -2
- package/lib/cjs/features/selection/feature.js +4 -4
- package/lib/cjs/features/selection/types.d.ts +1 -1
- package/lib/cjs/features/sync-data-loader/feature.js +31 -5
- package/lib/cjs/features/sync-data-loader/types.d.ts +5 -5
- package/lib/cjs/features/tree/feature.js +4 -7
- package/lib/cjs/features/tree/types.d.ts +7 -5
- package/lib/cjs/test-utils/test-tree-do.d.ts +2 -2
- package/lib/cjs/test-utils/test-tree-do.js +19 -6
- package/lib/cjs/test-utils/test-tree.d.ts +2 -1
- package/lib/cjs/test-utils/test-tree.js +24 -21
- package/lib/cjs/utilities/create-on-drop-handler.d.ts +1 -1
- package/lib/cjs/utilities/create-on-drop-handler.js +13 -4
- package/lib/cjs/utilities/insert-items-at-target.d.ts +1 -1
- package/lib/cjs/utilities/insert-items-at-target.js +21 -12
- package/lib/cjs/utilities/remove-items-from-parents.d.ts +1 -1
- package/lib/cjs/utilities/remove-items-from-parents.js +12 -3
- package/lib/esm/core/create-tree.js +13 -4
- package/lib/esm/features/async-data-loader/feature.js +73 -48
- package/lib/esm/features/async-data-loader/types.d.ts +17 -14
- package/lib/esm/features/drag-and-drop/feature.js +89 -84
- package/lib/esm/features/drag-and-drop/types.d.ts +8 -20
- package/lib/esm/features/drag-and-drop/utils.js +8 -21
- package/lib/esm/features/expand-all/feature.js +26 -3
- package/lib/esm/features/expand-all/types.d.ts +3 -1
- package/lib/esm/features/hotkeys-core/feature.js +6 -3
- package/lib/esm/features/hotkeys-core/types.d.ts +4 -5
- package/lib/esm/features/prop-memoization/feature.js +2 -2
- package/lib/esm/features/prop-memoization/types.d.ts +2 -2
- package/lib/esm/features/renaming/feature.js +1 -1
- package/lib/esm/features/search/feature.js +2 -0
- package/lib/esm/features/search/types.d.ts +2 -2
- package/lib/esm/features/selection/feature.js +4 -4
- package/lib/esm/features/selection/types.d.ts +1 -1
- package/lib/esm/features/sync-data-loader/feature.js +31 -5
- package/lib/esm/features/sync-data-loader/types.d.ts +5 -5
- package/lib/esm/features/tree/feature.js +4 -7
- package/lib/esm/features/tree/types.d.ts +7 -5
- package/lib/esm/test-utils/test-tree-do.d.ts +2 -2
- package/lib/esm/test-utils/test-tree-do.js +19 -6
- package/lib/esm/test-utils/test-tree.d.ts +2 -1
- package/lib/esm/test-utils/test-tree.js +24 -21
- package/lib/esm/utilities/create-on-drop-handler.d.ts +1 -1
- package/lib/esm/utilities/create-on-drop-handler.js +13 -4
- package/lib/esm/utilities/insert-items-at-target.d.ts +1 -1
- package/lib/esm/utilities/insert-items-at-target.js +21 -12
- package/lib/esm/utilities/remove-items-from-parents.d.ts +1 -1
- package/lib/esm/utilities/remove-items-from-parents.js +12 -3
- package/package.json +2 -2
- package/src/core/core.spec.ts +31 -0
- package/src/core/create-tree.ts +15 -5
- package/src/features/async-data-loader/async-data-loader.spec.ts +10 -6
- package/src/features/async-data-loader/feature.ts +76 -48
- package/src/features/async-data-loader/types.ts +18 -11
- package/src/features/drag-and-drop/drag-and-drop.spec.ts +69 -83
- package/src/features/drag-and-drop/feature.ts +9 -10
- package/src/features/drag-and-drop/types.ts +15 -27
- package/src/features/drag-and-drop/utils.ts +7 -20
- package/src/features/expand-all/feature.ts +29 -5
- package/src/features/expand-all/types.ts +3 -1
- package/src/features/hotkeys-core/feature.ts +3 -0
- package/src/features/hotkeys-core/types.ts +4 -13
- package/src/features/prop-memoization/feature.ts +2 -2
- package/src/features/prop-memoization/prop-memoization.spec.ts +2 -2
- package/src/features/prop-memoization/types.ts +2 -2
- package/src/features/renaming/feature.ts +8 -2
- package/src/features/search/feature.ts +2 -0
- package/src/features/search/types.ts +2 -2
- package/src/features/selection/feature.ts +4 -4
- package/src/features/selection/types.ts +1 -1
- package/src/features/sync-data-loader/feature.ts +26 -7
- package/src/features/sync-data-loader/types.ts +5 -5
- package/src/features/tree/feature.ts +8 -11
- package/src/features/tree/types.ts +7 -5
- package/src/test-utils/test-tree-do.ts +3 -3
- package/src/test-utils/test-tree.ts +26 -22
- package/src/utilities/create-on-drop-handler.ts +3 -3
- package/src/utilities/insert-items-at-target.ts +16 -12
- package/src/utilities/remove-items-from-parents.ts +6 -3
|
@@ -31,10 +31,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
31
31
|
tree.do.startDrag("x111");
|
|
32
32
|
tree.do.dragOverAndDrop("x21");
|
|
33
33
|
tree.expect.dropped(["x111"], {
|
|
34
|
-
dragLineIndex: null,
|
|
35
|
-
dragLineLevel: null,
|
|
36
|
-
childIndex: null,
|
|
37
|
-
insertionIndex: null,
|
|
38
34
|
item: tree.item("x21"),
|
|
39
35
|
});
|
|
40
36
|
});
|
|
@@ -44,10 +40,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
44
40
|
tree.do.startDrag("x111");
|
|
45
41
|
tree.do.dragOverAndDrop("x2");
|
|
46
42
|
tree.expect.dropped(["x111"], {
|
|
47
|
-
dragLineIndex: null,
|
|
48
|
-
dragLineLevel: null,
|
|
49
|
-
childIndex: null,
|
|
50
|
-
insertionIndex: null,
|
|
51
43
|
item: tree.item("x2"),
|
|
52
44
|
});
|
|
53
45
|
});
|
|
@@ -57,10 +49,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
57
49
|
tree.do.startDrag("x111");
|
|
58
50
|
tree.do.dragOverAndDrop("x12");
|
|
59
51
|
tree.expect.dropped(["x111"], {
|
|
60
|
-
dragLineIndex: null,
|
|
61
|
-
dragLineLevel: null,
|
|
62
|
-
childIndex: null,
|
|
63
|
-
insertionIndex: null,
|
|
64
52
|
item: tree.item("x12"),
|
|
65
53
|
});
|
|
66
54
|
});
|
|
@@ -109,33 +97,52 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
109
97
|
});
|
|
110
98
|
});
|
|
111
99
|
|
|
112
|
-
it("drop reparented one level", () => {
|
|
100
|
+
it("drop reparented one level", async () => {
|
|
101
|
+
tree.item("x14").expand();
|
|
102
|
+
await tree.resolveAsyncVisibleItems();
|
|
113
103
|
tree.do.ctrlSelectItem("x111");
|
|
114
104
|
tree.do.startDrag("x111");
|
|
115
|
-
tree.setElementBoundingBox("
|
|
105
|
+
tree.setElementBoundingBox("x144");
|
|
116
106
|
const event = tree.createBottomDragEvent(1);
|
|
117
|
-
tree.do.dragOverAndDrop("
|
|
107
|
+
tree.do.dragOverAndDrop("x144", event);
|
|
118
108
|
tree.expect.dropped(["x111"], {
|
|
119
|
-
dragLineIndex:
|
|
109
|
+
dragLineIndex: 13,
|
|
120
110
|
dragLineLevel: 1,
|
|
111
|
+
childIndex: 4,
|
|
112
|
+
insertionIndex: 4,
|
|
113
|
+
item: tree.item("x1"),
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("drop reparented two levels", async () => {
|
|
118
|
+
tree.item("x14").expand();
|
|
119
|
+
await tree.resolveAsyncVisibleItems();
|
|
120
|
+
tree.do.ctrlSelectItem("x111");
|
|
121
|
+
tree.do.startDrag("x111");
|
|
122
|
+
tree.setElementBoundingBox("x144");
|
|
123
|
+
const event = tree.createBottomDragEvent(0);
|
|
124
|
+
tree.do.dragOverAndDrop("x144", event);
|
|
125
|
+
tree.expect.dropped(["x111"], {
|
|
126
|
+
dragLineIndex: 13,
|
|
127
|
+
dragLineLevel: 0,
|
|
121
128
|
childIndex: 1,
|
|
122
129
|
insertionIndex: 1,
|
|
123
|
-
item: tree.item("
|
|
130
|
+
item: tree.item("x"),
|
|
124
131
|
});
|
|
125
132
|
});
|
|
126
133
|
|
|
127
|
-
it("drop reparented
|
|
128
|
-
// TODO reparenting two levels should work at x144, but not at x114
|
|
134
|
+
it("doesnt drop reparented higher than it can", () => {
|
|
129
135
|
tree.do.ctrlSelectItem("x111");
|
|
130
136
|
tree.do.startDrag("x111");
|
|
137
|
+
tree.setElementBoundingBox("x114");
|
|
131
138
|
const event = tree.createBottomDragEvent(0);
|
|
132
139
|
tree.do.dragOverAndDrop("x114", event);
|
|
133
140
|
tree.expect.dropped(["x111"], {
|
|
134
141
|
dragLineIndex: 6,
|
|
135
|
-
dragLineLevel:
|
|
142
|
+
dragLineLevel: 1,
|
|
136
143
|
childIndex: 1,
|
|
137
144
|
insertionIndex: 1,
|
|
138
|
-
item: tree.item("
|
|
145
|
+
item: tree.item("x1"),
|
|
139
146
|
});
|
|
140
147
|
});
|
|
141
148
|
|
|
@@ -147,10 +154,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
147
154
|
tree.do.startDrag("x111");
|
|
148
155
|
tree.do.dragOverAndDrop("x21");
|
|
149
156
|
tree.expect.dropped(["x111", "x112", "x113", "x114"], {
|
|
150
|
-
dragLineIndex: null,
|
|
151
|
-
dragLineLevel: null,
|
|
152
|
-
childIndex: null,
|
|
153
|
-
insertionIndex: null,
|
|
154
157
|
item: tree.item("x21"),
|
|
155
158
|
});
|
|
156
159
|
});
|
|
@@ -163,10 +166,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
163
166
|
tree.do.startDrag("x111");
|
|
164
167
|
tree.do.dragOverAndDrop("x21");
|
|
165
168
|
tree.expect.dropped(["x111", "x112", "x113", "x114"], {
|
|
166
|
-
dragLineIndex: null,
|
|
167
|
-
dragLineLevel: null,
|
|
168
|
-
childIndex: null,
|
|
169
|
-
insertionIndex: null,
|
|
170
169
|
item: tree.item("x21"),
|
|
171
170
|
});
|
|
172
171
|
});
|
|
@@ -179,10 +178,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
179
178
|
tree.do.startDrag("x111");
|
|
180
179
|
tree.do.dragOverAndDrop("x21");
|
|
181
180
|
tree.expect.dropped(["x111", "x112", "x113", "x114"], {
|
|
182
|
-
dragLineIndex: null,
|
|
183
|
-
dragLineLevel: null,
|
|
184
|
-
childIndex: null,
|
|
185
|
-
insertionIndex: null,
|
|
186
181
|
item: tree.item("x21"),
|
|
187
182
|
});
|
|
188
183
|
});
|
|
@@ -199,10 +194,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
199
194
|
draggedItems: [tree.item("x111")],
|
|
200
195
|
draggingOverItem: tree.item("x21"),
|
|
201
196
|
dragTarget: {
|
|
202
|
-
childIndex: null,
|
|
203
|
-
dragLineIndex: null,
|
|
204
|
-
dragLineLevel: null,
|
|
205
|
-
insertionIndex: null,
|
|
206
197
|
item: tree.item("x21"),
|
|
207
198
|
},
|
|
208
199
|
});
|
|
@@ -270,13 +261,15 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
270
261
|
tree.expect.defaultDragLineProps(1);
|
|
271
262
|
});
|
|
272
263
|
|
|
273
|
-
it("drop reparented two levels", () => {
|
|
264
|
+
it("drop reparented two levels", async () => {
|
|
265
|
+
tree.item("x14").expand();
|
|
266
|
+
await tree.resolveAsyncVisibleItems();
|
|
274
267
|
tree.do.ctrlSelectItem("x111");
|
|
275
268
|
tree.do.startDrag("x111");
|
|
276
269
|
const event = tree.createBottomDragEvent(0);
|
|
277
|
-
tree.setElementBoundingBox("
|
|
278
|
-
tree.setElementBoundingBox("
|
|
279
|
-
tree.do.dragOver("
|
|
270
|
+
tree.setElementBoundingBox("x2");
|
|
271
|
+
tree.setElementBoundingBox("x144");
|
|
272
|
+
tree.do.dragOver("x144", event);
|
|
280
273
|
tree.expect.defaultDragLineProps(0);
|
|
281
274
|
});
|
|
282
275
|
});
|
|
@@ -316,10 +309,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
316
309
|
expect(onDropForeignDragObject).toHaveBeenCalledWith(
|
|
317
310
|
event.dataTransfer,
|
|
318
311
|
{
|
|
319
|
-
childIndex: null,
|
|
320
|
-
dragLineIndex: null,
|
|
321
|
-
dragLineLevel: null,
|
|
322
|
-
insertionIndex: null,
|
|
323
312
|
item: tree.item("x11"),
|
|
324
313
|
},
|
|
325
314
|
);
|
|
@@ -371,10 +360,10 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
371
360
|
|
|
372
361
|
suiteTree.resetBeforeEach();
|
|
373
362
|
|
|
374
|
-
it("drags within same tree on folder", () => {
|
|
363
|
+
it("drags within same tree on expanded folder", async () => {
|
|
375
364
|
suiteTree.do.selectMultiple("x111", "x112");
|
|
376
365
|
suiteTree.do.startDrag("x111");
|
|
377
|
-
suiteTree.do.dragOverAndDrop("x21");
|
|
366
|
+
await suiteTree.do.dragOverAndDrop("x21");
|
|
378
367
|
expect(changeChildren).toHaveBeenCalledWith("x11", ["x113", "x114"]);
|
|
379
368
|
expect(changeChildren).toHaveBeenCalledWith("x21", [
|
|
380
369
|
"x211",
|
|
@@ -386,10 +375,26 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
386
375
|
]);
|
|
387
376
|
});
|
|
388
377
|
|
|
389
|
-
it("drags within same tree
|
|
378
|
+
it("drags within same tree on collapsed folder", async () => {
|
|
390
379
|
suiteTree.do.selectMultiple("x111", "x112");
|
|
391
380
|
suiteTree.do.startDrag("x111");
|
|
392
|
-
suiteTree.do.dragOverAndDrop(
|
|
381
|
+
suiteTree.do.dragOverAndDrop("x22");
|
|
382
|
+
await suiteTree.resolveAsyncVisibleItems();
|
|
383
|
+
expect(changeChildren).toHaveBeenCalledWith("x11", ["x113", "x114"]);
|
|
384
|
+
expect(changeChildren).toHaveBeenCalledWith("x22", [
|
|
385
|
+
"x221",
|
|
386
|
+
"x222",
|
|
387
|
+
"x223",
|
|
388
|
+
"x224",
|
|
389
|
+
"x111",
|
|
390
|
+
"x112",
|
|
391
|
+
]);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it("drags within same tree inside folder", async () => {
|
|
395
|
+
suiteTree.do.selectMultiple("x111", "x112");
|
|
396
|
+
suiteTree.do.startDrag("x111");
|
|
397
|
+
await suiteTree.do.dragOverAndDrop(
|
|
393
398
|
"x212",
|
|
394
399
|
suiteTree.createBottomDragEvent(2),
|
|
395
400
|
);
|
|
@@ -456,10 +461,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
456
461
|
const e = TestTree.dragEvent();
|
|
457
462
|
suiteTree.do.drop("x21", e);
|
|
458
463
|
expect(onDropForeignDragObject).toBeCalledWith(e.dataTransfer, {
|
|
459
|
-
childIndex: null,
|
|
460
|
-
dragLineIndex: null,
|
|
461
|
-
dragLineLevel: null,
|
|
462
|
-
insertionIndex: null,
|
|
463
464
|
item: suiteTree.item("x21"),
|
|
464
465
|
});
|
|
465
466
|
});
|
|
@@ -476,10 +477,13 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
476
477
|
expect(onDropForeignDragObject).not.toHaveBeenCalled();
|
|
477
478
|
});
|
|
478
479
|
|
|
479
|
-
it("drags multiple within in retained order (correct order)", () => {
|
|
480
|
+
it("drags multiple within in retained order (correct order)", async () => {
|
|
480
481
|
suiteTree.do.selectMultiple("x111", "x112", "x113", "x114");
|
|
481
482
|
suiteTree.do.startDrag("x111");
|
|
482
|
-
suiteTree.do.dragOverAndDrop(
|
|
483
|
+
await suiteTree.do.dragOverAndDrop(
|
|
484
|
+
"x212",
|
|
485
|
+
suiteTree.createBottomDragEvent(),
|
|
486
|
+
);
|
|
483
487
|
expect(changeChildren).toHaveBeenCalledWith("x11", []);
|
|
484
488
|
expect(changeChildren).toHaveBeenCalledWith("x21", [
|
|
485
489
|
"x211",
|
|
@@ -493,10 +497,13 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
493
497
|
]);
|
|
494
498
|
});
|
|
495
499
|
|
|
496
|
-
it("drags multiple within in retained order (inverse order)", () => {
|
|
500
|
+
it("drags multiple within in retained order (inverse order)", async () => {
|
|
497
501
|
suiteTree.do.selectMultiple("x114", "x113", "x112", "x111");
|
|
498
502
|
suiteTree.do.startDrag("x111");
|
|
499
|
-
suiteTree.do.dragOverAndDrop(
|
|
503
|
+
await suiteTree.do.dragOverAndDrop(
|
|
504
|
+
"x212",
|
|
505
|
+
suiteTree.createBottomDragEvent(),
|
|
506
|
+
);
|
|
500
507
|
expect(changeChildren).toHaveBeenCalledWith("x11", []);
|
|
501
508
|
expect(changeChildren).toHaveBeenCalledWith("x21", [
|
|
502
509
|
"x211",
|
|
@@ -510,10 +517,13 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
510
517
|
]);
|
|
511
518
|
});
|
|
512
519
|
|
|
513
|
-
it("drags multiple within in retained order (scrambled order)", () => {
|
|
520
|
+
it("drags multiple within in retained order (scrambled order)", async () => {
|
|
514
521
|
suiteTree.do.selectMultiple("x111", "x114", "x112", "x113");
|
|
515
522
|
suiteTree.do.startDrag("x111");
|
|
516
|
-
suiteTree.do.dragOverAndDrop(
|
|
523
|
+
await suiteTree.do.dragOverAndDrop(
|
|
524
|
+
"x212",
|
|
525
|
+
suiteTree.createBottomDragEvent(),
|
|
526
|
+
);
|
|
517
527
|
expect(changeChildren).toHaveBeenCalledWith("x11", []);
|
|
518
528
|
expect(changeChildren).toHaveBeenCalledWith("x21", [
|
|
519
529
|
"x211",
|
|
@@ -540,10 +550,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
540
550
|
testTree.do.startDrag("x111");
|
|
541
551
|
testTree.do.dragOverAndDrop("x212", testTree.createBottomDragEvent(2));
|
|
542
552
|
testTree.expect.dropped(["x111"], {
|
|
543
|
-
dragLineIndex: null,
|
|
544
|
-
dragLineLevel: null,
|
|
545
|
-
childIndex: null,
|
|
546
|
-
insertionIndex: null,
|
|
547
553
|
item: tree.item("x21"),
|
|
548
554
|
});
|
|
549
555
|
});
|
|
@@ -603,21 +609,9 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
603
609
|
tree.expect.dragOverNotAllowed("x2");
|
|
604
610
|
expect(canDrop).toHaveBeenCalledWith([tree.item("x111")], {
|
|
605
611
|
item: tree.item("x2"),
|
|
606
|
-
childIndex: null,
|
|
607
|
-
dragLineIndex: null,
|
|
608
|
-
dragLineLevel: null,
|
|
609
|
-
insertionIndex: null,
|
|
610
612
|
});
|
|
611
613
|
});
|
|
612
614
|
|
|
613
|
-
it.todo("item with canDrag=false is not draggable", () => {
|
|
614
|
-
const canDrag = tree.mockedHandler("canDrag").mockReturnValue(false);
|
|
615
|
-
expect(tree.instance.getItemInstance("x111").getProps().draggable).toBe(
|
|
616
|
-
false,
|
|
617
|
-
);
|
|
618
|
-
expect(canDrag).toHaveBeenCalledWith([tree.item("x111")]);
|
|
619
|
-
});
|
|
620
|
-
|
|
621
615
|
it("item with canDrag=false does not invoke drag handler when dragged", () => {
|
|
622
616
|
const canDrag = tree.mockedHandler("canDrag").mockReturnValue(false);
|
|
623
617
|
const setDndState = tree.mockedHandler("setDndState");
|
|
@@ -637,10 +631,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
637
631
|
tree.do.startDrag("x111");
|
|
638
632
|
tree.do.dragOverAndDrop("x21");
|
|
639
633
|
tree.expect.dropped(["x111", "x112", "x113"], {
|
|
640
|
-
dragLineIndex: null,
|
|
641
|
-
dragLineLevel: null,
|
|
642
|
-
childIndex: null,
|
|
643
|
-
insertionIndex: null,
|
|
644
634
|
item: tree.item("x21"),
|
|
645
635
|
});
|
|
646
636
|
});
|
|
@@ -652,10 +642,6 @@ describe("core-feature/drag-and-drop", () => {
|
|
|
652
642
|
tree.do.startDrag("x114");
|
|
653
643
|
tree.do.dragOverAndDrop("x21");
|
|
654
644
|
tree.expect.dropped(["x114"], {
|
|
655
|
-
dragLineIndex: null,
|
|
656
|
-
dragLineLevel: null,
|
|
657
|
-
childIndex: null,
|
|
658
|
-
insertionIndex: null,
|
|
659
645
|
item: tree.item("x21"),
|
|
660
646
|
});
|
|
661
647
|
});
|
|
@@ -30,7 +30,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
30
30
|
|
|
31
31
|
const treeBb = tree.getElement()?.getBoundingClientRect();
|
|
32
32
|
|
|
33
|
-
if (!target || !treeBb ||
|
|
33
|
+
if (!target || !treeBb || !("childIndex" in target)) return null;
|
|
34
34
|
|
|
35
35
|
const leftOffset = target.dragLineLevel * (tree.getConfig().indent ?? 1);
|
|
36
36
|
const targetItem = tree.getItems()[target.dragLineIndex];
|
|
@@ -77,8 +77,8 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
77
77
|
: { display: "none" };
|
|
78
78
|
},
|
|
79
79
|
|
|
80
|
-
getContainerProps: ({ prev }) => {
|
|
81
|
-
const prevProps = prev?.();
|
|
80
|
+
getContainerProps: ({ prev }, treeLabel) => {
|
|
81
|
+
const prevProps = prev?.(treeLabel);
|
|
82
82
|
return {
|
|
83
83
|
...prevProps,
|
|
84
84
|
style: {
|
|
@@ -93,7 +93,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
93
93
|
getProps: ({ tree, item, prev }) => ({
|
|
94
94
|
...prev?.(),
|
|
95
95
|
|
|
96
|
-
draggable:
|
|
96
|
+
draggable: true,
|
|
97
97
|
|
|
98
98
|
onDragStart: (e: DragEvent) => {
|
|
99
99
|
const selectedItems = tree.getSelectedItems();
|
|
@@ -179,7 +179,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
179
179
|
tree.getConfig().onCompleteForeignDrop?.(draggedItems);
|
|
180
180
|
},
|
|
181
181
|
|
|
182
|
-
onDrop: (e: DragEvent) => {
|
|
182
|
+
onDrop: async (e: DragEvent) => {
|
|
183
183
|
const dataRef = tree.getDataRef<DndDataRef>();
|
|
184
184
|
const target = getDropTarget(e, item, tree);
|
|
185
185
|
|
|
@@ -195,11 +195,10 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
195
195
|
tree.applySubStateUpdate("dnd", null);
|
|
196
196
|
|
|
197
197
|
if (draggedItems) {
|
|
198
|
-
config.onDrop?.(draggedItems, target);
|
|
198
|
+
await config.onDrop?.(draggedItems, target);
|
|
199
199
|
} else if (e.dataTransfer) {
|
|
200
|
-
config.onDropForeignDragObject?.(e.dataTransfer, target);
|
|
200
|
+
await config.onDropForeignDragObject?.(e.dataTransfer, target);
|
|
201
201
|
}
|
|
202
|
-
// TODO rebuild tree?
|
|
203
202
|
},
|
|
204
203
|
}),
|
|
205
204
|
|
|
@@ -213,7 +212,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
213
212
|
|
|
214
213
|
if (
|
|
215
214
|
!target ||
|
|
216
|
-
|
|
215
|
+
!("childIndex" in target) ||
|
|
217
216
|
target.item !== item.getParent()
|
|
218
217
|
)
|
|
219
218
|
return false;
|
|
@@ -225,7 +224,7 @@ export const dragAndDropFeature: FeatureImplementation = {
|
|
|
225
224
|
|
|
226
225
|
if (
|
|
227
226
|
!target ||
|
|
228
|
-
|
|
227
|
+
!("childIndex" in target) ||
|
|
229
228
|
target.item !== item.getParent()
|
|
230
229
|
)
|
|
231
230
|
return false;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { ItemInstance, SetStateFn } from "../../types/core";
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export interface DndDataRef {
|
|
4
4
|
lastDragCode?: string;
|
|
5
5
|
lastAllowDrop?: boolean;
|
|
6
|
-
}
|
|
6
|
+
}
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export interface DndState<T> {
|
|
9
9
|
draggedItems?: ItemInstance<T>[];
|
|
10
10
|
draggingOverItem?: ItemInstance<T>;
|
|
11
11
|
dragTarget?: DropTarget<T>;
|
|
12
|
-
}
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export interface DragLineData {
|
|
15
15
|
indent: number;
|
|
16
16
|
top: number;
|
|
17
17
|
left: number;
|
|
18
18
|
width: number;
|
|
19
|
-
}
|
|
19
|
+
}
|
|
20
20
|
|
|
21
21
|
export type DropTarget<T> =
|
|
22
22
|
| {
|
|
@@ -27,11 +27,7 @@ export type DropTarget<T> =
|
|
|
27
27
|
dragLineLevel: number;
|
|
28
28
|
}
|
|
29
29
|
| {
|
|
30
|
-
item: ItemInstance<T>;
|
|
31
|
-
childIndex: null;
|
|
32
|
-
insertionIndex: null;
|
|
33
|
-
dragLineIndex: null;
|
|
34
|
-
dragLineLevel: null;
|
|
30
|
+
item: ItemInstance<T>;
|
|
35
31
|
};
|
|
36
32
|
|
|
37
33
|
export enum DropTargetPosition {
|
|
@@ -53,8 +49,6 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
53
49
|
reorderAreaPercentage?: number;
|
|
54
50
|
canReorder?: boolean;
|
|
55
51
|
|
|
56
|
-
// TODO better document difference to canDrag(), or unify both
|
|
57
|
-
isItemDraggable?: (item: ItemInstance<T>) => boolean;
|
|
58
52
|
canDrag?: (items: ItemInstance<T>[]) => boolean;
|
|
59
53
|
canDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => boolean;
|
|
60
54
|
|
|
@@ -68,26 +62,20 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
68
62
|
dataTransfer: DataTransfer,
|
|
69
63
|
target: DropTarget<T>,
|
|
70
64
|
) => boolean;
|
|
71
|
-
onDrop?: (
|
|
65
|
+
onDrop?: (
|
|
66
|
+
items: ItemInstance<T>[],
|
|
67
|
+
target: DropTarget<T>,
|
|
68
|
+
) => void | Promise<void>;
|
|
72
69
|
onDropForeignDragObject?: (
|
|
73
70
|
dataTransfer: DataTransfer,
|
|
74
71
|
target: DropTarget<T>,
|
|
75
|
-
) => void
|
|
76
|
-
|
|
77
|
-
/** Runs in the onDragEnd event, if `ev.dataTransfer.dropEffect` is not `none`, i.e. the drop
|
|
78
|
-
* was not aborted. No target is provided as parameter since the target may be a foreign drop target.
|
|
79
|
-
* This is useful to seperate out the logic to move dragged items out of their previous parents.
|
|
80
|
-
* Use `onDrop` to handle drop-related logic.
|
|
81
|
-
*
|
|
82
|
-
* This ignores the `canDrop` handler, since the drop target is unknown in this handler.
|
|
83
|
-
*/
|
|
84
|
-
// onSuccessfulDragEnd?: (items: ItemInstance<T>[]) => void;
|
|
85
|
-
|
|
72
|
+
) => void | Promise<void>;
|
|
86
73
|
onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
|
|
87
74
|
};
|
|
88
75
|
treeInstance: {
|
|
89
76
|
getDropTarget: () => DropTarget<T> | null;
|
|
90
77
|
getDragLineData: () => DragLineData | null;
|
|
78
|
+
|
|
91
79
|
getDragLineStyle: (
|
|
92
80
|
topOffset?: number,
|
|
93
81
|
leftOffset?: number,
|
|
@@ -95,8 +83,8 @@ export type DragAndDropFeatureDef<T> = {
|
|
|
95
83
|
};
|
|
96
84
|
itemInstance: {
|
|
97
85
|
isDropTarget: () => boolean;
|
|
98
|
-
isDropTargetAbove: () => boolean;
|
|
99
|
-
isDropTargetBelow: () => boolean;
|
|
86
|
+
isDropTargetAbove: () => boolean;
|
|
87
|
+
isDropTargetBelow: () => boolean;
|
|
100
88
|
isDraggingOver: () => boolean;
|
|
101
89
|
};
|
|
102
90
|
hotkeys: never;
|
|
@@ -66,7 +66,7 @@ const getItemDropCategory = (item: ItemInstance<any>) => {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const parent = item.getParent();
|
|
69
|
-
if (parent && item.getIndexInParent() ===
|
|
69
|
+
if (parent && item.getIndexInParent() === item.getItemMeta().setSize - 1) {
|
|
70
70
|
return ItemDropCategory.LastInGroup;
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -88,8 +88,8 @@ const getTargetPlacement = (
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const bb = item.getElement()?.getBoundingClientRect();
|
|
91
|
-
const topPercent = bb ? (e.
|
|
92
|
-
const leftPixels = bb ? e.
|
|
91
|
+
const topPercent = bb ? (e.clientY - bb.top) / bb.height : 0.5;
|
|
92
|
+
const leftPixels = bb ? e.clientX - bb.left : 0;
|
|
93
93
|
const targetDropCategory = getItemDropCategory(item);
|
|
94
94
|
const reorderAreaPercentage = !canMakeChild
|
|
95
95
|
? 0.5
|
|
@@ -111,9 +111,10 @@ const getTargetPlacement = (
|
|
|
111
111
|
if (topPercent < 0.5) {
|
|
112
112
|
return { type: PlacementType.ReorderAbove };
|
|
113
113
|
}
|
|
114
|
+
const minLevel = item.getItemBelow()?.getItemMeta().level ?? 0;
|
|
114
115
|
return {
|
|
115
116
|
type: PlacementType.Reparent,
|
|
116
|
-
reparentLevel: Math.floor(leftPixels / indent),
|
|
117
|
+
reparentLevel: Math.max(minLevel, Math.floor(leftPixels / indent)),
|
|
117
118
|
};
|
|
118
119
|
}
|
|
119
120
|
// if not at left of item area, treat as if it was a normal item
|
|
@@ -161,22 +162,8 @@ export const getDropTarget = (
|
|
|
161
162
|
const draggedItems = tree.getState().dnd?.draggedItems ?? [];
|
|
162
163
|
const itemMeta = item.getItemMeta();
|
|
163
164
|
const parent = item.getParent();
|
|
164
|
-
const itemTarget: DropTarget<any> = {
|
|
165
|
-
|
|
166
|
-
childIndex: null,
|
|
167
|
-
insertionIndex: null,
|
|
168
|
-
dragLineIndex: null,
|
|
169
|
-
dragLineLevel: null,
|
|
170
|
-
};
|
|
171
|
-
const parentTarget: DropTarget<any> | null = parent
|
|
172
|
-
? {
|
|
173
|
-
item: parent,
|
|
174
|
-
childIndex: null,
|
|
175
|
-
insertionIndex: null,
|
|
176
|
-
dragLineIndex: null,
|
|
177
|
-
dragLineLevel: null,
|
|
178
|
-
}
|
|
179
|
-
: null;
|
|
165
|
+
const itemTarget: DropTarget<any> = { item };
|
|
166
|
+
const parentTarget: DropTarget<any> | null = parent ? { item: parent } : null;
|
|
180
167
|
const canBecomeSibling =
|
|
181
168
|
parentTarget && canDrop(e.dataTransfer, parentTarget, tree);
|
|
182
169
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FeatureImplementation } from "../../types/core";
|
|
2
|
-
import { poll } from "../../utils";
|
|
3
2
|
|
|
4
3
|
export const expandAllFeature: FeatureImplementation = {
|
|
5
4
|
key: "expand-all",
|
|
@@ -27,22 +26,47 @@ export const expandAllFeature: FeatureImplementation = {
|
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
item.expand();
|
|
30
|
-
await
|
|
29
|
+
await tree.waitForItemChildrenLoaded(item.getId());
|
|
31
30
|
await Promise.all(
|
|
32
31
|
item.getChildren().map(async (child) => {
|
|
33
|
-
await
|
|
34
|
-
() => !tree.getState().loadingItems.includes(child.getId()),
|
|
35
|
-
);
|
|
32
|
+
await tree.waitForItemChildrenLoaded(item.getId());
|
|
36
33
|
await child?.expandAll(cancelToken);
|
|
37
34
|
}),
|
|
38
35
|
);
|
|
39
36
|
},
|
|
40
37
|
|
|
41
38
|
collapseAll: ({ item }) => {
|
|
39
|
+
if (!item.isExpanded()) return;
|
|
42
40
|
for (const child of item.getChildren()) {
|
|
43
41
|
child?.collapseAll();
|
|
44
42
|
}
|
|
45
43
|
item.collapse();
|
|
46
44
|
},
|
|
47
45
|
},
|
|
46
|
+
|
|
47
|
+
hotkeys: {
|
|
48
|
+
expandSelected: {
|
|
49
|
+
hotkey: "Control+Shift+Plus",
|
|
50
|
+
handler: async (_, tree) => {
|
|
51
|
+
const cancelToken = { current: false };
|
|
52
|
+
const cancelHandler = (e: KeyboardEvent) => {
|
|
53
|
+
if (e.key === "Escape") {
|
|
54
|
+
cancelToken.current = true;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
document.addEventListener("keydown", cancelHandler);
|
|
58
|
+
await Promise.all(
|
|
59
|
+
tree.getSelectedItems().map((item) => item.expandAll(cancelToken)),
|
|
60
|
+
);
|
|
61
|
+
document.removeEventListener("keydown", cancelHandler);
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
collapseSelected: {
|
|
66
|
+
hotkey: "Control+Shift+-",
|
|
67
|
+
handler: (_, tree) => {
|
|
68
|
+
tree.getSelectedItems().forEach((item) => item.collapseAll());
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
48
72
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export interface ExpandAllDataRef {}
|
|
2
|
+
|
|
1
3
|
export type ExpandAllFeatureDef = {
|
|
2
4
|
state: {};
|
|
3
5
|
config: {};
|
|
@@ -9,5 +11,5 @@ export type ExpandAllFeatureDef = {
|
|
|
9
11
|
expandAll: (cancelToken?: { current: boolean }) => Promise<void>;
|
|
10
12
|
collapseAll: () => void;
|
|
11
13
|
};
|
|
12
|
-
hotkeys:
|
|
14
|
+
hotkeys: "expandSelected" | "collapseSelected";
|
|
13
15
|
};
|
|
@@ -8,6 +8,8 @@ import { HotkeyConfig, HotkeysCoreDataRef } from "./types";
|
|
|
8
8
|
const specialKeys: Record<string, RegExp> = {
|
|
9
9
|
Letter: /^[a-z]$/,
|
|
10
10
|
LetterOrNumber: /^[a-z0-9]$/,
|
|
11
|
+
Plus: /^\+$/,
|
|
12
|
+
Space: /^ $/,
|
|
11
13
|
};
|
|
12
14
|
|
|
13
15
|
const testHotkeyMatch = (
|
|
@@ -71,6 +73,7 @@ export const hotkeysCoreFeature: FeatureImplementation = {
|
|
|
71
73
|
if (hotkeyConfig.preventDefault) e.preventDefault();
|
|
72
74
|
|
|
73
75
|
hotkeyConfig.handler(e, tree as any);
|
|
76
|
+
tree.getConfig().onTreeHotkey?.(hotkeyName, e);
|
|
74
77
|
};
|
|
75
78
|
|
|
76
79
|
const keyup = (e: KeyboardEvent) => {
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CustomHotkeysConfig,
|
|
3
|
-
ItemInstance,
|
|
4
|
-
TreeInstance,
|
|
5
|
-
} from "../../types/core";
|
|
1
|
+
import { CustomHotkeysConfig, TreeInstance } from "../../types/core";
|
|
6
2
|
|
|
7
3
|
export interface HotkeyConfig<T> {
|
|
8
4
|
hotkey: string;
|
|
@@ -13,22 +9,17 @@ export interface HotkeyConfig<T> {
|
|
|
13
9
|
handler: (e: KeyboardEvent, tree: TreeInstance<T>) => void;
|
|
14
10
|
}
|
|
15
11
|
|
|
16
|
-
export
|
|
12
|
+
export interface HotkeysCoreDataRef {
|
|
17
13
|
keydownHandler?: (e: KeyboardEvent) => void;
|
|
18
14
|
keyupHandler?: (e: KeyboardEvent) => void;
|
|
19
15
|
pressedKeys: Set<string>;
|
|
20
|
-
}
|
|
16
|
+
}
|
|
21
17
|
|
|
22
18
|
export type HotkeysCoreFeatureDef<T> = {
|
|
23
19
|
state: {};
|
|
24
20
|
config: {
|
|
25
21
|
hotkeys?: CustomHotkeysConfig<T>;
|
|
26
|
-
onTreeHotkey?: (name: string,
|
|
27
|
-
onItemHotkey?: (
|
|
28
|
-
name: string,
|
|
29
|
-
item: ItemInstance<T>,
|
|
30
|
-
element: HTMLElement,
|
|
31
|
-
) => void;
|
|
22
|
+
onTreeHotkey?: (name: string, e: KeyboardEvent) => void;
|
|
32
23
|
};
|
|
33
24
|
treeInstance: {};
|
|
34
25
|
itemInstance: {};
|
|
@@ -34,9 +34,9 @@ export const propMemoizationFeature: FeatureImplementation = {
|
|
|
34
34
|
],
|
|
35
35
|
|
|
36
36
|
treeInstance: {
|
|
37
|
-
getContainerProps: ({ tree, prev }) => {
|
|
37
|
+
getContainerProps: ({ tree, prev }, treeLabel) => {
|
|
38
38
|
const dataRef = tree.getDataRef<PropMemoizationDataRef>();
|
|
39
|
-
const props = prev?.() ?? {};
|
|
39
|
+
const props = prev?.(treeLabel) ?? {};
|
|
40
40
|
return memoize(props, dataRef.current);
|
|
41
41
|
},
|
|
42
42
|
},
|