jqtree 1.7.4 → 1.8.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 (94) hide show
  1. package/.eslintrc +5 -1
  2. package/bower.json +1 -1
  3. package/config/babel.config.json +1 -1
  4. package/config/production +2 -0
  5. package/devserver/devserver_scroll.js +8 -0
  6. package/devserver/test_scroll.html +28 -0
  7. package/devserver/test_scroll_container.html +39 -0
  8. package/docs/_config.yml +1 -1
  9. package/docs/_entries/general/changelog.md +12 -0
  10. package/docs/package.json +1 -1
  11. package/docs/pnpm-lock.yaml +30 -30
  12. package/package.json +31 -27
  13. package/src/dataLoader.ts +44 -19
  14. package/src/dragAndDropHandler/dragElement.ts +42 -0
  15. package/src/dragAndDropHandler/hitAreasGenerator.ts +175 -0
  16. package/src/dragAndDropHandler/index.ts +470 -0
  17. package/src/dragAndDropHandler/types.ts +12 -0
  18. package/src/dragAndDropHandler/visibleNodeIterator.ts +97 -0
  19. package/src/elementsRenderer.ts +75 -40
  20. package/src/jqtreeMethodTypes.ts +40 -0
  21. package/src/jqtreeOptions.ts +43 -25
  22. package/src/keyHandler.ts +59 -38
  23. package/src/mouse.widget.ts +3 -3
  24. package/src/mouseWidgetTypes.ts +6 -0
  25. package/src/node.ts +32 -48
  26. package/src/nodeElement/borderDropHint.ts +32 -0
  27. package/src/nodeElement/folderElement.ts +133 -0
  28. package/src/nodeElement/ghostDropHint.ts +68 -0
  29. package/src/nodeElement/index.ts +101 -0
  30. package/src/nodeUtils.ts +10 -0
  31. package/src/playwright/coverage.ts +1 -4
  32. package/src/playwright/playwright.test.ts +203 -15
  33. package/src/playwright/testUtils.ts +23 -15
  34. package/src/saveStateHandler.ts +75 -26
  35. package/src/scrollHandler/containerScrollParent.ts +177 -0
  36. package/src/scrollHandler/createScrollParent.ts +50 -0
  37. package/src/scrollHandler/documentScrollParent.ts +182 -0
  38. package/src/scrollHandler/types.ts +7 -0
  39. package/src/scrollHandler.ts +36 -248
  40. package/src/selectNodeHandler.ts +10 -16
  41. package/src/test/jqTree/keyboard.test.ts +18 -23
  42. package/src/test/jqTree/loadOnDemand.test.ts +2 -3
  43. package/src/test/jqTree/methods.test.ts +33 -4
  44. package/src/test/jqTree/options.test.ts +15 -4
  45. package/src/test/node.test.ts +85 -26
  46. package/src/test/nodeUtils.test.ts +21 -0
  47. package/src/tree.jquery.ts +262 -83
  48. package/src/util.ts +3 -0
  49. package/src/version.ts +1 -1
  50. package/tree.jquery.debug.js +1922 -2608
  51. package/tree.jquery.debug.js.map +1 -1
  52. package/tree.jquery.js +2 -2
  53. package/tree.jquery.js.map +1 -1
  54. package/lib/dataLoader.js +0 -124
  55. package/lib/dragAndDropHandler.js +0 -596
  56. package/lib/elementsRenderer.js +0 -268
  57. package/lib/jqtreeOptions.js +0 -1
  58. package/lib/keyHandler.js +0 -115
  59. package/lib/mouse.widget.js +0 -256
  60. package/lib/node.js +0 -717
  61. package/lib/nodeElement.js +0 -277
  62. package/lib/playwright/coverage.js +0 -96
  63. package/lib/playwright/playwright.test.js +0 -228
  64. package/lib/playwright/testUtils.js +0 -184
  65. package/lib/saveStateHandler.js +0 -278
  66. package/lib/scrollHandler.js +0 -250
  67. package/lib/selectNodeHandler.js +0 -129
  68. package/lib/simple.widget.js +0 -159
  69. package/lib/test/global.d.js +0 -3
  70. package/lib/test/jqTree/accessibility.test.js +0 -37
  71. package/lib/test/jqTree/create.test.js +0 -48
  72. package/lib/test/jqTree/events.test.js +0 -210
  73. package/lib/test/jqTree/keyboard.test.js +0 -225
  74. package/lib/test/jqTree/loadOnDemand.test.js +0 -218
  75. package/lib/test/jqTree/methods.test.js +0 -1347
  76. package/lib/test/jqTree/options.test.js +0 -548
  77. package/lib/test/node.test.js +0 -1160
  78. package/lib/test/nodeUtil.test.js +0 -27
  79. package/lib/test/support/exampleData.js +0 -36
  80. package/lib/test/support/jqTreeMatchers.js +0 -70
  81. package/lib/test/support/matchers.d.js +0 -1
  82. package/lib/test/support/setupTests.js +0 -7
  83. package/lib/test/support/testUtil.js +0 -32
  84. package/lib/test/support/treeStructure.js +0 -39
  85. package/lib/test/util.test.js +0 -26
  86. package/lib/tree.jquery.d.js +0 -1
  87. package/lib/tree.jquery.js +0 -1106
  88. package/lib/types.js +0 -1
  89. package/lib/typings.d.js +0 -2
  90. package/lib/util.js +0 -18
  91. package/lib/version.js +0 -9
  92. package/src/dragAndDropHandler.ts +0 -719
  93. package/src/nodeElement.ts +0 -272
  94. package/src/types.ts +0 -19
@@ -0,0 +1,175 @@
1
+ import { HitArea } from "./types";
2
+ import { Node, Position } from "../node";
3
+ import { getOffsetTop } from "../util";
4
+ import VisibleNodeIterator from "./visibleNodeIterator";
5
+
6
+ class HitAreasGenerator extends VisibleNodeIterator {
7
+ private currentNode: Node;
8
+ private treeBottom: number;
9
+ private positions: HitArea[];
10
+ private lastTop: number;
11
+
12
+ constructor(tree: Node, currentNode: Node, treeBottom: number) {
13
+ super(tree);
14
+
15
+ this.currentNode = currentNode;
16
+ this.treeBottom = treeBottom;
17
+ }
18
+
19
+ public generate(): HitArea[] {
20
+ this.positions = [];
21
+ this.lastTop = 0;
22
+
23
+ this.iterate();
24
+
25
+ return this.generateHitAreas(this.positions);
26
+ }
27
+
28
+ protected generateHitAreas(positions: HitArea[]): HitArea[] {
29
+ let previousTop = positions[0]?.top ?? 0;
30
+ let group = [];
31
+ const hitAreas: HitArea[] = [];
32
+
33
+ for (const position of positions) {
34
+ if (position.top !== previousTop && group.length) {
35
+ this.generateHitAreasForGroup(
36
+ hitAreas,
37
+ group,
38
+ previousTop,
39
+ position.top,
40
+ );
41
+
42
+ previousTop = position.top;
43
+ group = [];
44
+ }
45
+
46
+ group.push(position);
47
+ }
48
+
49
+ this.generateHitAreasForGroup(
50
+ hitAreas,
51
+ group,
52
+ previousTop,
53
+ this.treeBottom,
54
+ );
55
+
56
+ return hitAreas;
57
+ }
58
+
59
+ protected handleOpenFolder(node: Node, element: HTMLElement): boolean {
60
+ if (node === this.currentNode) {
61
+ // Cannot move inside current item
62
+ // Stop iterating
63
+ return false;
64
+ }
65
+
66
+ // Cannot move before current item
67
+ if (node.children[0] !== this.currentNode) {
68
+ this.addPosition(node, Position.Inside, getOffsetTop(element));
69
+ }
70
+
71
+ // Continue iterating
72
+ return true;
73
+ }
74
+
75
+ protected handleClosedFolder(
76
+ node: Node,
77
+ nextNode: Node,
78
+ element: HTMLElement,
79
+ ): void {
80
+ const top = getOffsetTop(element);
81
+
82
+ if (node === this.currentNode) {
83
+ // Cannot move after current item
84
+ this.addPosition(node, Position.None, top);
85
+ } else {
86
+ this.addPosition(node, Position.Inside, top);
87
+
88
+ // Cannot move before current item
89
+ if (nextNode !== this.currentNode) {
90
+ this.addPosition(node, Position.After, top);
91
+ }
92
+ }
93
+ }
94
+
95
+ protected handleFirstNode(node: Node): void {
96
+ if (node !== this.currentNode) {
97
+ this.addPosition(node, Position.Before, getOffsetTop(node.element));
98
+ }
99
+ }
100
+
101
+ protected handleAfterOpenFolder(node: Node, nextNode: Node): void {
102
+ if (node === this.currentNode || nextNode === this.currentNode) {
103
+ // Cannot move before or after current item
104
+ this.addPosition(node, Position.None, this.lastTop);
105
+ } else {
106
+ this.addPosition(node, Position.After, this.lastTop);
107
+ }
108
+ }
109
+
110
+ protected handleNode(
111
+ node: Node,
112
+ nextNode: Node,
113
+ element: HTMLElement,
114
+ ): void {
115
+ const top = getOffsetTop(element);
116
+
117
+ if (node === this.currentNode) {
118
+ // Cannot move inside current item
119
+ this.addPosition(node, Position.None, top);
120
+ } else {
121
+ this.addPosition(node, Position.Inside, top);
122
+ }
123
+
124
+ if (nextNode === this.currentNode || node === this.currentNode) {
125
+ // Cannot move before or after current item
126
+ this.addPosition(node, Position.None, top);
127
+ } else {
128
+ this.addPosition(node, Position.After, top);
129
+ }
130
+ }
131
+
132
+ private addPosition(node: Node, position: number, top: number): void {
133
+ const area = {
134
+ top,
135
+ bottom: 0,
136
+ node,
137
+ position,
138
+ };
139
+
140
+ this.positions.push(area);
141
+ this.lastTop = top;
142
+ }
143
+
144
+ private generateHitAreasForGroup(
145
+ hitAreas: HitArea[],
146
+ positionsInGroup: HitArea[],
147
+ top: number,
148
+ bottom: number,
149
+ ): void {
150
+ // limit positions in group
151
+ const positionCount = Math.min(positionsInGroup.length, 4);
152
+
153
+ const areaHeight = Math.round((bottom - top) / positionCount);
154
+ let areaTop = top;
155
+
156
+ let i = 0;
157
+ while (i < positionCount) {
158
+ const position = positionsInGroup[i];
159
+
160
+ if (position) {
161
+ hitAreas.push({
162
+ top: areaTop,
163
+ bottom: areaTop + areaHeight,
164
+ node: position.node,
165
+ position: position.position,
166
+ });
167
+ }
168
+
169
+ areaTop += areaHeight;
170
+ i += 1;
171
+ }
172
+ }
173
+ }
174
+
175
+ export default HitAreasGenerator;
@@ -0,0 +1,470 @@
1
+ import { getPositionName, Node, Position } from "../node";
2
+ import { DropHint, HitArea } from "./types";
3
+ import { PositionInfo } from "../mouseWidgetTypes";
4
+ import NodeElement from "../nodeElement";
5
+ import DragElement from "./dragElement";
6
+ import HitAreasGenerator from "./hitAreasGenerator";
7
+ import {
8
+ OnCanMove,
9
+ OnCanMoveTo,
10
+ OnIsMoveHandle,
11
+ DragMethod,
12
+ } from "../jqtreeOptions";
13
+ import {
14
+ GetScrollLeft,
15
+ GetTree,
16
+ OpenNode,
17
+ RefreshElements,
18
+ TriggerEvent,
19
+ } from "../jqtreeMethodTypes";
20
+
21
+ interface Dimensions {
22
+ left: number;
23
+ top: number;
24
+ right: number;
25
+ bottom: number;
26
+ }
27
+
28
+ type GetNodeElement = (element: HTMLElement) => NodeElement | null;
29
+ type GetNodeElementForNode = (node: Node) => NodeElement;
30
+
31
+ interface DragAndDropHandlerParams {
32
+ autoEscape?: boolean;
33
+ getNodeElement: GetNodeElement;
34
+ getNodeElementForNode: GetNodeElementForNode;
35
+ getScrollLeft: GetScrollLeft;
36
+ getTree: GetTree;
37
+ onCanMove?: OnCanMove;
38
+ onCanMoveTo?: OnCanMoveTo;
39
+ onDragMove?: DragMethod;
40
+ onDragStop?: DragMethod;
41
+ onIsMoveHandle?: OnIsMoveHandle;
42
+ openFolderDelay: number | false;
43
+ openNode: OpenNode;
44
+ refreshElements: RefreshElements;
45
+ slide: boolean;
46
+ $treeElement: JQuery<HTMLElement>;
47
+ triggerEvent: TriggerEvent;
48
+ }
49
+
50
+ export class DragAndDropHandler {
51
+ public hitAreas: HitArea[];
52
+ public isDragging: boolean;
53
+ public currentItem: NodeElement | null;
54
+ public hoveredArea: HitArea | null;
55
+
56
+ private autoEscape?: boolean;
57
+ private dragElement: DragElement | null;
58
+ private getNodeElement: GetNodeElement;
59
+ private getNodeElementForNode: GetNodeElementForNode;
60
+ private getScrollLeft: GetScrollLeft;
61
+ private getTree: GetTree;
62
+ private onCanMove?: OnCanMove;
63
+ private onCanMoveTo?: OnCanMoveTo;
64
+ private onDragMove?: DragMethod;
65
+ private onDragStop?: DragMethod;
66
+ private onIsMoveHandle?: OnIsMoveHandle;
67
+ private openFolderDelay: number | false;
68
+ private openFolderTimer: number | null;
69
+ private openNode: OpenNode;
70
+ private previousGhost: DropHint | null;
71
+ private refreshElements: RefreshElements;
72
+ private slide: boolean;
73
+ private $treeElement: JQuery<HTMLElement>;
74
+ private triggerEvent: TriggerEvent;
75
+
76
+ constructor({
77
+ autoEscape,
78
+ getNodeElement,
79
+ getNodeElementForNode,
80
+ getScrollLeft,
81
+ getTree,
82
+ onCanMove,
83
+ onCanMoveTo,
84
+ onDragMove,
85
+ onDragStop,
86
+ onIsMoveHandle,
87
+ openNode,
88
+ refreshElements,
89
+ slide,
90
+ $treeElement,
91
+ triggerEvent,
92
+ }: DragAndDropHandlerParams) {
93
+ this.autoEscape = autoEscape;
94
+ this.getNodeElement = getNodeElement;
95
+ this.getNodeElementForNode = getNodeElementForNode;
96
+ this.getScrollLeft = getScrollLeft;
97
+ this.getTree = getTree;
98
+ this.onCanMove = onCanMove;
99
+ this.onCanMoveTo = onCanMoveTo;
100
+ this.onDragMove = onDragMove;
101
+ this.onDragStop = onDragStop;
102
+ this.onIsMoveHandle = onIsMoveHandle;
103
+ this.openNode = openNode;
104
+ this.refreshElements = refreshElements;
105
+ this.slide = slide;
106
+ this.$treeElement = $treeElement;
107
+ this.triggerEvent = triggerEvent;
108
+
109
+ this.hoveredArea = null;
110
+ this.hitAreas = [];
111
+ this.isDragging = false;
112
+ this.currentItem = null;
113
+ }
114
+
115
+ public mouseCapture(positionInfo: PositionInfo): boolean | null {
116
+ const element = positionInfo.target;
117
+
118
+ if (!this.mustCaptureElement(element)) {
119
+ return null;
120
+ }
121
+
122
+ if (this.onIsMoveHandle && !this.onIsMoveHandle(jQuery(element))) {
123
+ return null;
124
+ }
125
+
126
+ let nodeElement = this.getNodeElement(element);
127
+
128
+ if (nodeElement && this.onCanMove) {
129
+ if (!this.onCanMove(nodeElement.node)) {
130
+ nodeElement = null;
131
+ }
132
+ }
133
+
134
+ this.currentItem = nodeElement;
135
+ return this.currentItem != null;
136
+ }
137
+
138
+ public mouseStart(positionInfo: PositionInfo): boolean {
139
+ if (
140
+ !this.currentItem ||
141
+ positionInfo.pageX === undefined ||
142
+ positionInfo.pageY === undefined
143
+ ) {
144
+ return false;
145
+ }
146
+
147
+ this.refresh();
148
+
149
+ const offset = jQuery(positionInfo.target).offset();
150
+ const left = offset ? offset.left : 0;
151
+ const top = offset ? offset.top : 0;
152
+
153
+ const node = this.currentItem.node;
154
+
155
+ this.dragElement = new DragElement(
156
+ node.name,
157
+ positionInfo.pageX - left,
158
+ positionInfo.pageY - top,
159
+ this.$treeElement,
160
+ this.autoEscape ?? true,
161
+ );
162
+
163
+ this.isDragging = true;
164
+ this.currentItem.element.classList.add("jqtree-moving");
165
+
166
+ return true;
167
+ }
168
+
169
+ public mouseDrag(positionInfo: PositionInfo): boolean {
170
+ if (
171
+ !this.currentItem ||
172
+ !this.dragElement ||
173
+ positionInfo.pageX === undefined ||
174
+ positionInfo.pageY === undefined
175
+ ) {
176
+ return false;
177
+ }
178
+
179
+ this.dragElement.move(positionInfo.pageX, positionInfo.pageY);
180
+
181
+ const area = this.findHoveredArea(
182
+ positionInfo.pageX,
183
+ positionInfo.pageY,
184
+ );
185
+
186
+ if (area && this.canMoveToArea(area)) {
187
+ if (!area.node.isFolder()) {
188
+ this.stopOpenFolderTimer();
189
+ }
190
+
191
+ if (this.hoveredArea !== area) {
192
+ this.hoveredArea = area;
193
+
194
+ // If this is a closed folder, start timer to open it
195
+ if (this.mustOpenFolderTimer(area)) {
196
+ this.startOpenFolderTimer(area.node);
197
+ } else {
198
+ this.stopOpenFolderTimer();
199
+ }
200
+
201
+ this.updateDropHint();
202
+ }
203
+ } else {
204
+ this.removeDropHint();
205
+ this.stopOpenFolderTimer();
206
+ this.hoveredArea = area;
207
+ }
208
+
209
+ if (!area) {
210
+ if (this.onDragMove) {
211
+ this.onDragMove(
212
+ this.currentItem.node,
213
+ positionInfo.originalEvent,
214
+ );
215
+ }
216
+ }
217
+
218
+ return true;
219
+ }
220
+
221
+ public mouseStop(positionInfo: PositionInfo): boolean {
222
+ this.moveItem(positionInfo);
223
+ this.clear();
224
+ this.removeHover();
225
+ this.removeDropHint();
226
+ this.removeHitAreas();
227
+
228
+ const currentItem = this.currentItem;
229
+
230
+ if (this.currentItem) {
231
+ this.currentItem.element.classList.remove("jqtree-moving");
232
+ this.currentItem = null;
233
+ }
234
+
235
+ this.isDragging = false;
236
+
237
+ if (!this.hoveredArea && currentItem) {
238
+ if (this.onDragStop) {
239
+ this.onDragStop(currentItem.node, positionInfo.originalEvent);
240
+ }
241
+ }
242
+
243
+ return false;
244
+ }
245
+
246
+ public refresh(): void {
247
+ this.removeHitAreas();
248
+
249
+ if (this.currentItem) {
250
+ this.generateHitAreas();
251
+
252
+ this.currentItem = this.getNodeElementForNode(
253
+ this.currentItem.node,
254
+ );
255
+
256
+ if (this.isDragging) {
257
+ this.currentItem.element.classList.add("jqtree-moving");
258
+ }
259
+ }
260
+ }
261
+
262
+ private generateHitAreas(): void {
263
+ const tree = this.getTree();
264
+
265
+ if (!this.currentItem || !tree) {
266
+ this.hitAreas = [];
267
+ } else {
268
+ const hitAreasGenerator = new HitAreasGenerator(
269
+ tree,
270
+ this.currentItem.node,
271
+ this.getTreeDimensions().bottom,
272
+ );
273
+ this.hitAreas = hitAreasGenerator.generate();
274
+ }
275
+ }
276
+
277
+ private mustCaptureElement(element: HTMLElement): boolean {
278
+ const nodeName = element.nodeName;
279
+
280
+ return (
281
+ nodeName !== "INPUT" &&
282
+ nodeName !== "SELECT" &&
283
+ nodeName !== "TEXTAREA"
284
+ );
285
+ }
286
+
287
+ private canMoveToArea(area: HitArea): boolean {
288
+ if (!this.onCanMoveTo) {
289
+ return true;
290
+ }
291
+
292
+ if (!this.currentItem) {
293
+ return false;
294
+ }
295
+
296
+ const positionName = getPositionName(area.position);
297
+
298
+ return this.onCanMoveTo(this.currentItem.node, area.node, positionName);
299
+ }
300
+
301
+ private removeHitAreas(): void {
302
+ this.hitAreas = [];
303
+ }
304
+
305
+ private clear(): void {
306
+ if (this.dragElement) {
307
+ this.dragElement.remove();
308
+ this.dragElement = null;
309
+ }
310
+ }
311
+
312
+ private removeDropHint(): void {
313
+ if (this.previousGhost) {
314
+ this.previousGhost.remove();
315
+ }
316
+ }
317
+
318
+ private removeHover(): void {
319
+ this.hoveredArea = null;
320
+ }
321
+
322
+ private findHoveredArea(x: number, y: number): HitArea | null {
323
+ const dimensions = this.getTreeDimensions();
324
+
325
+ if (
326
+ x < dimensions.left ||
327
+ y < dimensions.top ||
328
+ x > dimensions.right ||
329
+ y > dimensions.bottom
330
+ ) {
331
+ return null;
332
+ }
333
+
334
+ let low = 0;
335
+ let high = this.hitAreas.length;
336
+ while (low < high) {
337
+ const mid = (low + high) >> 1;
338
+ const area = this.hitAreas[mid];
339
+
340
+ if (!area) {
341
+ return null;
342
+ }
343
+
344
+ if (y < area.top) {
345
+ high = mid;
346
+ } else if (y > area.bottom) {
347
+ low = mid + 1;
348
+ } else {
349
+ return area;
350
+ }
351
+ }
352
+
353
+ return null;
354
+ }
355
+
356
+ private mustOpenFolderTimer(area: HitArea): boolean {
357
+ const node = area.node;
358
+
359
+ return (
360
+ node.isFolder() &&
361
+ !node.is_open &&
362
+ area.position === Position.Inside
363
+ );
364
+ }
365
+
366
+ private updateDropHint(): void {
367
+ if (!this.hoveredArea) {
368
+ return;
369
+ }
370
+
371
+ // remove previous drop hint
372
+ this.removeDropHint();
373
+
374
+ // add new drop hint
375
+ const nodeElement = this.getNodeElementForNode(this.hoveredArea.node);
376
+ this.previousGhost = nodeElement.addDropHint(this.hoveredArea.position);
377
+ }
378
+
379
+ private startOpenFolderTimer(folder: Node): void {
380
+ const openFolder = (): void => {
381
+ this.openNode(folder, this.slide, () => {
382
+ this.refresh();
383
+ this.updateDropHint();
384
+ });
385
+ };
386
+
387
+ this.stopOpenFolderTimer();
388
+
389
+ const openFolderDelay = this.openFolderDelay;
390
+
391
+ if (openFolderDelay !== false) {
392
+ this.openFolderTimer = window.setTimeout(
393
+ openFolder,
394
+ openFolderDelay,
395
+ );
396
+ }
397
+ }
398
+
399
+ private stopOpenFolderTimer(): void {
400
+ if (this.openFolderTimer) {
401
+ clearTimeout(this.openFolderTimer);
402
+ this.openFolderTimer = null;
403
+ }
404
+ }
405
+
406
+ private moveItem(positionInfo: PositionInfo): void {
407
+ if (
408
+ this.currentItem &&
409
+ this.hoveredArea &&
410
+ this.hoveredArea.position !== Position.None &&
411
+ this.canMoveToArea(this.hoveredArea)
412
+ ) {
413
+ const movedNode = this.currentItem.node;
414
+ const targetNode = this.hoveredArea.node;
415
+ const position = this.hoveredArea.position;
416
+ const previousParent = movedNode.parent;
417
+
418
+ if (position === Position.Inside) {
419
+ this.hoveredArea.node.is_open = true;
420
+ }
421
+
422
+ const doMove = (): void => {
423
+ const tree = this.getTree();
424
+
425
+ if (tree) {
426
+ tree.moveNode(movedNode, targetNode, position);
427
+ this.$treeElement.empty();
428
+ this.refreshElements(null);
429
+ }
430
+ };
431
+
432
+ const event = this.triggerEvent("tree.move", {
433
+ move_info: {
434
+ moved_node: movedNode,
435
+ target_node: targetNode,
436
+ position: getPositionName(position),
437
+ previous_parent: previousParent,
438
+ do_move: doMove,
439
+ original_event: positionInfo.originalEvent,
440
+ },
441
+ });
442
+
443
+ if (!event.isDefaultPrevented()) {
444
+ doMove();
445
+ }
446
+ }
447
+ }
448
+
449
+ private getTreeDimensions(): Dimensions {
450
+ // Return the dimensions of the tree. Add a margin to the bottom to allow
451
+ // to drag-and-drop after the last element.
452
+ const offset = this.$treeElement.offset();
453
+
454
+ if (!offset) {
455
+ return { left: 0, top: 0, right: 0, bottom: 0 };
456
+ } else {
457
+ const el = this.$treeElement;
458
+ const width = el.width() || 0;
459
+ const height = el.height() || 0;
460
+ const left = offset.left + this.getScrollLeft();
461
+
462
+ return {
463
+ left,
464
+ top: offset.top,
465
+ right: left + width,
466
+ bottom: offset.top + height + 16,
467
+ };
468
+ }
469
+ }
470
+ }
@@ -0,0 +1,12 @@
1
+ import { Node, Position } from "../node";
2
+
3
+ export interface DropHint {
4
+ remove: () => void;
5
+ }
6
+
7
+ export interface HitArea {
8
+ top: number;
9
+ bottom: number;
10
+ node: Node;
11
+ position: Position;
12
+ }