@headless-tree/core 0.0.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/lib/cjs/core/create-tree.js +13 -4
  3. package/lib/cjs/features/async-data-loader/feature.js +73 -48
  4. package/lib/cjs/features/async-data-loader/types.d.ts +17 -14
  5. package/lib/cjs/features/drag-and-drop/feature.js +98 -93
  6. package/lib/cjs/features/drag-and-drop/types.d.ts +17 -29
  7. package/lib/cjs/features/drag-and-drop/types.js +7 -7
  8. package/lib/cjs/features/drag-and-drop/utils.d.ts +25 -3
  9. package/lib/cjs/features/drag-and-drop/utils.js +51 -51
  10. package/lib/cjs/features/expand-all/feature.js +26 -3
  11. package/lib/cjs/features/expand-all/types.d.ts +3 -1
  12. package/lib/cjs/features/hotkeys-core/feature.js +7 -3
  13. package/lib/cjs/features/hotkeys-core/types.d.ts +4 -5
  14. package/lib/cjs/features/keyboard-drag-and-drop/feature.d.ts +2 -0
  15. package/lib/cjs/features/keyboard-drag-and-drop/feature.js +206 -0
  16. package/lib/cjs/features/keyboard-drag-and-drop/types.d.ts +27 -0
  17. package/lib/cjs/features/keyboard-drag-and-drop/types.js +11 -0
  18. package/lib/cjs/features/prop-memoization/feature.js +33 -11
  19. package/lib/cjs/features/prop-memoization/types.d.ts +8 -3
  20. package/lib/cjs/features/renaming/feature.js +1 -1
  21. package/lib/cjs/features/search/feature.js +2 -0
  22. package/lib/cjs/features/search/types.d.ts +2 -2
  23. package/lib/cjs/features/selection/feature.js +4 -4
  24. package/lib/cjs/features/selection/types.d.ts +1 -1
  25. package/lib/cjs/features/sync-data-loader/feature.js +31 -5
  26. package/lib/cjs/features/sync-data-loader/types.d.ts +5 -5
  27. package/lib/cjs/features/tree/feature.js +4 -9
  28. package/lib/cjs/features/tree/types.d.ts +7 -5
  29. package/lib/cjs/index.d.ts +2 -0
  30. package/lib/cjs/index.js +2 -0
  31. package/lib/cjs/mddocs-entry.d.ts +10 -0
  32. package/lib/cjs/test-utils/test-tree-do.d.ts +2 -2
  33. package/lib/cjs/test-utils/test-tree-do.js +19 -6
  34. package/lib/cjs/test-utils/test-tree-expect.d.ts +5 -3
  35. package/lib/cjs/test-utils/test-tree-expect.js +3 -0
  36. package/lib/cjs/test-utils/test-tree.d.ts +2 -1
  37. package/lib/cjs/test-utils/test-tree.js +24 -21
  38. package/lib/cjs/types/core.d.ts +2 -1
  39. package/lib/cjs/utilities/create-on-drop-handler.d.ts +2 -2
  40. package/lib/cjs/utilities/create-on-drop-handler.js +13 -4
  41. package/lib/cjs/utilities/insert-items-at-target.d.ts +2 -2
  42. package/lib/cjs/utilities/insert-items-at-target.js +21 -12
  43. package/lib/cjs/utilities/remove-items-from-parents.d.ts +1 -1
  44. package/lib/cjs/utilities/remove-items-from-parents.js +12 -3
  45. package/lib/esm/core/create-tree.js +13 -4
  46. package/lib/esm/features/async-data-loader/feature.js +73 -48
  47. package/lib/esm/features/async-data-loader/types.d.ts +17 -14
  48. package/lib/esm/features/drag-and-drop/feature.js +99 -94
  49. package/lib/esm/features/drag-and-drop/types.d.ts +17 -29
  50. package/lib/esm/features/drag-and-drop/types.js +6 -6
  51. package/lib/esm/features/drag-and-drop/utils.d.ts +25 -3
  52. package/lib/esm/features/drag-and-drop/utils.js +45 -49
  53. package/lib/esm/features/expand-all/feature.js +26 -3
  54. package/lib/esm/features/expand-all/types.d.ts +3 -1
  55. package/lib/esm/features/hotkeys-core/feature.js +7 -3
  56. package/lib/esm/features/hotkeys-core/types.d.ts +4 -5
  57. package/lib/esm/features/keyboard-drag-and-drop/feature.d.ts +2 -0
  58. package/lib/esm/features/keyboard-drag-and-drop/feature.js +203 -0
  59. package/lib/esm/features/keyboard-drag-and-drop/types.d.ts +27 -0
  60. package/lib/esm/features/keyboard-drag-and-drop/types.js +8 -0
  61. package/lib/esm/features/prop-memoization/feature.js +33 -11
  62. package/lib/esm/features/prop-memoization/types.d.ts +8 -3
  63. package/lib/esm/features/renaming/feature.js +1 -1
  64. package/lib/esm/features/search/feature.js +2 -0
  65. package/lib/esm/features/search/types.d.ts +2 -2
  66. package/lib/esm/features/selection/feature.js +4 -4
  67. package/lib/esm/features/selection/types.d.ts +1 -1
  68. package/lib/esm/features/sync-data-loader/feature.js +31 -5
  69. package/lib/esm/features/sync-data-loader/types.d.ts +5 -5
  70. package/lib/esm/features/tree/feature.js +4 -9
  71. package/lib/esm/features/tree/types.d.ts +7 -5
  72. package/lib/esm/index.d.ts +2 -0
  73. package/lib/esm/index.js +2 -0
  74. package/lib/esm/mddocs-entry.d.ts +10 -0
  75. package/lib/esm/test-utils/test-tree-do.d.ts +2 -2
  76. package/lib/esm/test-utils/test-tree-do.js +19 -6
  77. package/lib/esm/test-utils/test-tree-expect.d.ts +5 -3
  78. package/lib/esm/test-utils/test-tree-expect.js +3 -0
  79. package/lib/esm/test-utils/test-tree.d.ts +2 -1
  80. package/lib/esm/test-utils/test-tree.js +24 -21
  81. package/lib/esm/types/core.d.ts +2 -1
  82. package/lib/esm/utilities/create-on-drop-handler.d.ts +2 -2
  83. package/lib/esm/utilities/create-on-drop-handler.js +13 -4
  84. package/lib/esm/utilities/insert-items-at-target.d.ts +2 -2
  85. package/lib/esm/utilities/insert-items-at-target.js +21 -12
  86. package/lib/esm/utilities/remove-items-from-parents.d.ts +1 -1
  87. package/lib/esm/utilities/remove-items-from-parents.js +12 -3
  88. package/package.json +2 -2
  89. package/src/core/core.spec.ts +31 -0
  90. package/src/core/create-tree.ts +15 -5
  91. package/src/features/async-data-loader/async-data-loader.spec.ts +10 -6
  92. package/src/features/async-data-loader/feature.ts +76 -48
  93. package/src/features/async-data-loader/types.ts +18 -11
  94. package/src/features/drag-and-drop/drag-and-drop.spec.ts +75 -89
  95. package/src/features/drag-and-drop/feature.ts +26 -22
  96. package/src/features/drag-and-drop/types.ts +23 -35
  97. package/src/features/drag-and-drop/utils.ts +70 -57
  98. package/src/features/expand-all/feature.ts +29 -5
  99. package/src/features/expand-all/types.ts +3 -1
  100. package/src/features/hotkeys-core/feature.ts +4 -0
  101. package/src/features/hotkeys-core/types.ts +4 -13
  102. package/src/features/keyboard-drag-and-drop/feature.ts +255 -0
  103. package/src/features/keyboard-drag-and-drop/keyboard-drag-and-drop.spec.ts +402 -0
  104. package/src/features/keyboard-drag-and-drop/types.ts +30 -0
  105. package/src/features/prop-memoization/feature.ts +27 -8
  106. package/src/features/prop-memoization/prop-memoization.spec.ts +2 -2
  107. package/src/features/prop-memoization/types.ts +8 -3
  108. package/src/features/renaming/feature.ts +8 -2
  109. package/src/features/search/feature.ts +2 -0
  110. package/src/features/search/types.ts +2 -2
  111. package/src/features/selection/feature.ts +4 -4
  112. package/src/features/selection/types.ts +1 -1
  113. package/src/features/sync-data-loader/feature.ts +26 -7
  114. package/src/features/sync-data-loader/types.ts +5 -5
  115. package/src/features/tree/feature.ts +8 -13
  116. package/src/features/tree/types.ts +7 -5
  117. package/src/index.ts +2 -0
  118. package/src/mddocs-entry.ts +16 -0
  119. package/src/test-utils/test-tree-do.ts +3 -3
  120. package/src/test-utils/test-tree-expect.ts +7 -2
  121. package/src/test-utils/test-tree.ts +26 -22
  122. package/src/types/core.ts +2 -0
  123. package/src/utilities/create-on-drop-handler.ts +4 -4
  124. package/src/utilities/insert-items-at-target.ts +18 -14
  125. 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("x114");
105
+ tree.setElementBoundingBox("x144");
116
106
  const event = tree.createBottomDragEvent(1);
117
- tree.do.dragOverAndDrop("x114", event);
107
+ tree.do.dragOverAndDrop("x144", event);
118
108
  tree.expect.dropped(["x111"], {
119
- dragLineIndex: 6,
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("x1"),
130
+ item: tree.item("x"),
124
131
  });
125
132
  });
126
133
 
127
- it("drop reparented two levels", () => {
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: 0,
142
+ dragLineLevel: 1,
136
143
  childIndex: 1,
137
144
  insertionIndex: 1,
138
- item: tree.item("x"),
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("x12");
278
- tree.setElementBoundingBox("x114");
279
- tree.do.dragOver("x114", event);
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 inside folder", () => {
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("x212", suiteTree.createBottomDragEvent());
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("x212", suiteTree.createBottomDragEvent());
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("x212", suiteTree.createBottomDragEvent());
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,30 +642,26 @@ 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
  });
662
648
  });
663
649
 
664
650
  describe("item instance methods", () => {
665
- it("returns isDropTarget() correct for folders", () => {
651
+ it("returns isDragTarget() correct for folders", () => {
666
652
  tree.do.startDrag("x111");
667
653
  tree.do.dragOver("x21");
668
- expect(tree.instance.getItemInstance("x21").isDropTarget()).toBe(true);
669
- expect(tree.instance.getItemInstance("x211").isDropTarget()).toBe(
654
+ expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
655
+ expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
670
656
  false,
671
657
  );
672
658
  });
673
659
 
674
- it("returns isDropTarget() correct for items", () => {
660
+ it("returns isDragTarget() correct for items", () => {
675
661
  tree.do.startDrag("x111");
676
662
  tree.do.dragOver("x211");
677
- expect(tree.instance.getItemInstance("x21").isDropTarget()).toBe(true);
678
- expect(tree.instance.getItemInstance("x211").isDropTarget()).toBe(
663
+ expect(tree.instance.getItemInstance("x21").isDragTarget()).toBe(true);
664
+ expect(tree.instance.getItemInstance("x211").isDragTarget()).toBe(
679
665
  false,
680
666
  );
681
667
  });
@@ -1,6 +1,11 @@
1
1
  import { FeatureImplementation } from "../../types/core";
2
2
  import { DndDataRef, DragLineData } from "./types";
3
- import { canDrop, getDragCode, getDropTarget } from "./utils";
3
+ import {
4
+ canDrop,
5
+ getDragCode,
6
+ getDragTarget,
7
+ isOrderedDragTarget,
8
+ } from "./utils";
4
9
  import { makeStateUpdater } from "../../utils";
5
10
 
6
11
  export const dragAndDropFeature: FeatureImplementation = {
@@ -20,17 +25,17 @@ export const dragAndDropFeature: FeatureImplementation = {
20
25
  },
21
26
 
22
27
  treeInstance: {
23
- getDropTarget: ({ tree }) => {
28
+ getDragTarget: ({ tree }) => {
24
29
  return tree.getState().dnd?.dragTarget ?? null;
25
30
  },
26
31
 
27
32
  getDragLineData: ({ tree }): DragLineData | null => {
28
- const target = tree.getDropTarget();
33
+ const target = tree.getDragTarget();
29
34
  const indent = (target?.item.getItemMeta().level ?? 0) + 1;
30
35
 
31
36
  const treeBb = tree.getElement()?.getBoundingClientRect();
32
37
 
33
- if (!target || !treeBb || target.childIndex === null) return null;
38
+ if (!target || !treeBb || !isOrderedDragTarget(target)) return null;
34
39
 
35
40
  const leftOffset = target.dragLineLevel * (tree.getConfig().indent ?? 1);
36
41
  const targetItem = tree.getItems()[target.dragLineIndex];
@@ -44,7 +49,7 @@ export const dragAndDropFeature: FeatureImplementation = {
44
49
  if (bb) {
45
50
  return {
46
51
  indent,
47
- top: bb.bottom - treeBb.bottom,
52
+ top: bb.bottom - treeBb.top,
48
53
  left: bb.left + leftOffset - treeBb.left,
49
54
  width: bb.width - leftOffset,
50
55
  };
@@ -77,8 +82,8 @@ export const dragAndDropFeature: FeatureImplementation = {
77
82
  : { display: "none" };
78
83
  },
79
84
 
80
- getContainerProps: ({ prev }) => {
81
- const prevProps = prev?.();
85
+ getContainerProps: ({ prev }, treeLabel) => {
86
+ const prevProps = prev?.(treeLabel);
82
87
  return {
83
88
  ...prevProps,
84
89
  style: {
@@ -93,7 +98,7 @@ export const dragAndDropFeature: FeatureImplementation = {
93
98
  getProps: ({ tree, item, prev }) => ({
94
99
  ...prev?.(),
95
100
 
96
- draggable: tree.getConfig().isItemDraggable?.(item) ?? true,
101
+ draggable: true,
97
102
 
98
103
  onDragStart: (e: DragEvent) => {
99
104
  const selectedItems = tree.getSelectedItems();
@@ -131,7 +136,7 @@ export const dragAndDropFeature: FeatureImplementation = {
131
136
  }
132
137
  dataRef.current.lastDragCode = nextDragCode;
133
138
 
134
- const target = getDropTarget(e, item, tree);
139
+ const target = getDragTarget(e, item, tree);
135
140
 
136
141
  if (
137
142
  !tree.getState().dnd?.draggedItems &&
@@ -179,9 +184,9 @@ export const dragAndDropFeature: FeatureImplementation = {
179
184
  tree.getConfig().onCompleteForeignDrop?.(draggedItems);
180
185
  },
181
186
 
182
- onDrop: (e: DragEvent) => {
187
+ onDrop: async (e: DragEvent) => {
183
188
  const dataRef = tree.getDataRef<DndDataRef>();
184
- const target = getDropTarget(e, item, tree);
189
+ const target = getDragTarget(e, item, tree);
185
190
 
186
191
  if (!canDrop(e.dataTransfer, target, tree)) {
187
192
  return;
@@ -195,37 +200,36 @@ export const dragAndDropFeature: FeatureImplementation = {
195
200
  tree.applySubStateUpdate("dnd", null);
196
201
 
197
202
  if (draggedItems) {
198
- config.onDrop?.(draggedItems, target);
203
+ await config.onDrop?.(draggedItems, target);
199
204
  } else if (e.dataTransfer) {
200
- config.onDropForeignDragObject?.(e.dataTransfer, target);
205
+ await config.onDropForeignDragObject?.(e.dataTransfer, target);
201
206
  }
202
- // TODO rebuild tree?
203
207
  },
204
208
  }),
205
209
 
206
- isDropTarget: ({ tree, item }) => {
207
- const target = tree.getDropTarget();
210
+ isDragTarget: ({ tree, item }) => {
211
+ const target = tree.getDragTarget();
208
212
  return target ? target.item.getId() === item.getId() : false;
209
213
  },
210
214
 
211
- isDropTargetAbove: ({ tree, item }) => {
212
- const target = tree.getDropTarget();
215
+ isDragTargetAbove: ({ tree, item }) => {
216
+ const target = tree.getDragTarget();
213
217
 
214
218
  if (
215
219
  !target ||
216
- target.childIndex === null ||
220
+ !isOrderedDragTarget(target) ||
217
221
  target.item !== item.getParent()
218
222
  )
219
223
  return false;
220
224
  return target.childIndex === item.getItemMeta().posInSet;
221
225
  },
222
226
 
223
- isDropTargetBelow: ({ tree, item }) => {
224
- const target = tree.getDropTarget();
227
+ isDragTargetBelow: ({ tree, item }) => {
228
+ const target = tree.getDragTarget();
225
229
 
226
230
  if (
227
231
  !target ||
228
- target.childIndex === null ||
232
+ !isOrderedDragTarget(target) ||
229
233
  target.item !== item.getParent()
230
234
  )
231
235
  return false;
@@ -1,24 +1,24 @@
1
1
  import { ItemInstance, SetStateFn } from "../../types/core";
2
2
 
3
- export type DndDataRef = {
3
+ export interface DndDataRef {
4
4
  lastDragCode?: string;
5
5
  lastAllowDrop?: boolean;
6
- };
6
+ }
7
7
 
8
- export type DndState<T> = {
8
+ export interface DndState<T> {
9
9
  draggedItems?: ItemInstance<T>[];
10
10
  draggingOverItem?: ItemInstance<T>;
11
- dragTarget?: DropTarget<T>;
12
- };
11
+ dragTarget?: DragTarget<T>;
12
+ }
13
13
 
14
- export type DragLineData = {
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
- export type DropTarget<T> =
21
+ export type DragTarget<T> =
22
22
  | {
23
23
  item: ItemInstance<T>;
24
24
  childIndex: number;
@@ -27,14 +27,10 @@ export type DropTarget<T> =
27
27
  dragLineLevel: number;
28
28
  }
29
29
  | {
30
- item: ItemInstance<T>; // TODO just omit values instead of nulls; or maybe just make it union of dropTarget+itemInstance?
31
- childIndex: null;
32
- insertionIndex: null;
33
- dragLineIndex: null;
34
- dragLineLevel: null;
30
+ item: ItemInstance<T>;
35
31
  };
36
32
 
37
- export enum DropTargetPosition {
33
+ export enum DragTargetPosition {
38
34
  Top = "top",
39
35
  Bottom = "bottom",
40
36
  Item = "item",
@@ -53,10 +49,8 @@ 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
- canDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => boolean;
53
+ canDrop?: (items: ItemInstance<T>[], target: DragTarget<T>) => boolean;
60
54
 
61
55
  indent?: number;
62
56
 
@@ -66,37 +60,31 @@ export type DragAndDropFeatureDef<T> = {
66
60
  };
67
61
  canDropForeignDragObject?: (
68
62
  dataTransfer: DataTransfer,
69
- target: DropTarget<T>,
63
+ target: DragTarget<T>,
70
64
  ) => boolean;
71
- onDrop?: (items: ItemInstance<T>[], target: DropTarget<T>) => void;
65
+ onDrop?: (
66
+ items: ItemInstance<T>[],
67
+ target: DragTarget<T>,
68
+ ) => void | Promise<void>;
72
69
  onDropForeignDragObject?: (
73
70
  dataTransfer: DataTransfer,
74
- 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
-
71
+ target: DragTarget<T>,
72
+ ) => void | Promise<void>;
86
73
  onCompleteForeignDrop?: (items: ItemInstance<T>[]) => void;
87
74
  };
88
75
  treeInstance: {
89
- getDropTarget: () => DropTarget<T> | null;
76
+ getDragTarget: () => DragTarget<T> | null;
90
77
  getDragLineData: () => DragLineData | null;
78
+
91
79
  getDragLineStyle: (
92
80
  topOffset?: number,
93
81
  leftOffset?: number,
94
82
  ) => Record<string, any>;
95
83
  };
96
84
  itemInstance: {
97
- isDropTarget: () => boolean;
98
- isDropTargetAbove: () => boolean; // TODO still correct?
99
- isDropTargetBelow: () => boolean; // TODO still correct?
85
+ isDragTarget: () => boolean;
86
+ isDragTargetAbove: () => boolean;
87
+ isDragTargetBelow: () => boolean;
100
88
  isDraggingOver: () => boolean;
101
89
  };
102
90
  hotkeys: never;