@limble/limble-tree 0.13.0 → 1.0.0-alpha.2

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 (163) hide show
  1. package/README.md +418 -96
  2. package/esm2020/lib/components/branch/branch.component.mjs +79 -0
  3. package/esm2020/lib/components/dropzone/dropzone.component.mjs +35 -0
  4. package/esm2020/lib/components/host-component.interface.mjs +2 -0
  5. package/esm2020/lib/components/node-component.interface.mjs +2 -0
  6. package/esm2020/lib/components/root/root.component.mjs +36 -0
  7. package/esm2020/lib/core/branch-options.interface.mjs +2 -0
  8. package/esm2020/lib/core/configuration/configuration.mjs +17 -0
  9. package/esm2020/lib/core/configuration/tree-options.interface.mjs +2 -0
  10. package/esm2020/lib/core/index.mjs +6 -0
  11. package/esm2020/lib/core/relationship.interface.mjs +2 -0
  12. package/esm2020/lib/core/tree-branch/branch-controller.mjs +99 -0
  13. package/esm2020/lib/core/tree-branch/tree-branch.mjs +224 -0
  14. package/esm2020/lib/core/tree-node-base.mjs +69 -0
  15. package/esm2020/lib/core/tree-root/root-controller.mjs +42 -0
  16. package/esm2020/lib/core/tree-root/tree-root.mjs +85 -0
  17. package/esm2020/lib/core/tree-service/tree.service.mjs +19 -0
  18. package/esm2020/lib/errors/index.mjs +2 -0
  19. package/esm2020/lib/errors/tree-error.mjs +3 -0
  20. package/esm2020/lib/events/drag/drag-end-event.mjs +28 -0
  21. package/esm2020/lib/events/drag/drag-start-event.mjs +12 -0
  22. package/esm2020/lib/events/drag/drop-event.mjs +20 -0
  23. package/esm2020/lib/events/drag/index.mjs +4 -0
  24. package/esm2020/lib/events/general/destruction-event.mjs +12 -0
  25. package/esm2020/lib/events/general/index.mjs +2 -0
  26. package/esm2020/lib/events/index.mjs +4 -0
  27. package/esm2020/lib/events/relational/graft-event.mjs +24 -0
  28. package/esm2020/lib/events/relational/index.mjs +4 -0
  29. package/esm2020/lib/events/relational/prune-event.mjs +24 -0
  30. package/esm2020/lib/events/relational/relational-tree-event.interface.mjs +2 -0
  31. package/esm2020/lib/extras/collapse/collapse.mjs +33 -0
  32. package/esm2020/lib/extras/collapse/collapse.module.mjs +15 -0
  33. package/esm2020/lib/extras/collapse/collapse.service.mjs +20 -0
  34. package/esm2020/lib/extras/collapse/index.mjs +3 -0
  35. package/esm2020/lib/extras/drag-and-drop/drag-and-drop.mjs +85 -0
  36. package/esm2020/lib/extras/drag-and-drop/drag-and-drop.module.mjs +19 -0
  37. package/esm2020/lib/extras/drag-and-drop/drag-and-drop.service.mjs +28 -0
  38. package/esm2020/lib/extras/drag-and-drop/drag-state.mjs +47 -0
  39. package/esm2020/lib/extras/drag-and-drop/draggable.directive.mjs +30 -0
  40. package/esm2020/lib/extras/drag-and-drop/dragover-no-change-detect.mjs +40 -0
  41. package/esm2020/lib/extras/drag-and-drop/dropzone-renderer.mjs +178 -0
  42. package/esm2020/lib/extras/drag-and-drop/index.mjs +5 -0
  43. package/esm2020/lib/legacy/index.mjs +7 -0
  44. package/esm2020/lib/legacy/legacy-component-obj.interface.mjs +2 -0
  45. package/esm2020/lib/legacy/legacy-tree-data.interface.mjs +2 -0
  46. package/esm2020/lib/legacy/legacy-tree-options.interface.mjs +2 -0
  47. package/esm2020/lib/legacy/legacy-tree.mjs +73 -0
  48. package/esm2020/lib/legacy/limble-tree-legacy.module.mjs +20 -0
  49. package/esm2020/lib/legacy/limble-tree-root/limble-tree-root.component.mjs +78 -0
  50. package/esm2020/lib/limble-tree.module.mjs +21 -47
  51. package/esm2020/lib/structure/branchable.interface.mjs +2 -0
  52. package/esm2020/lib/structure/component-container.interface.mjs +2 -0
  53. package/esm2020/lib/structure/event-conduit.interface.mjs +2 -0
  54. package/esm2020/lib/structure/graftable.interface.mjs +2 -0
  55. package/esm2020/lib/structure/index.mjs +10 -0
  56. package/esm2020/lib/structure/tree-branch-node.interface.mjs +2 -0
  57. package/esm2020/lib/structure/tree-event.interface.mjs +2 -0
  58. package/esm2020/lib/structure/tree-node.interface.mjs +2 -0
  59. package/esm2020/lib/structure/tree-plot.mjs +2 -0
  60. package/esm2020/lib/structure/tree-relationship.interface.mjs +2 -0
  61. package/esm2020/limble-limble-tree.mjs +4 -4
  62. package/esm2020/public-api.mjs +12 -6
  63. package/esm2020/shared/assert.mjs +7 -0
  64. package/fesm2015/limble-limble-tree.mjs +1404 -2226
  65. package/fesm2015/limble-limble-tree.mjs.map +1 -1
  66. package/fesm2020/limble-limble-tree.mjs +1396 -2132
  67. package/fesm2020/limble-limble-tree.mjs.map +1 -1
  68. package/index.d.ts +5 -5
  69. package/lib/components/branch/branch.component.d.ts +26 -0
  70. package/lib/components/dropzone/dropzone.component.d.ts +13 -0
  71. package/lib/components/host-component.interface.d.ts +6 -0
  72. package/lib/components/node-component.interface.d.ts +5 -0
  73. package/lib/components/root/root.component.d.ts +14 -0
  74. package/lib/core/branch-options.interface.d.ts +14 -0
  75. package/lib/core/configuration/configuration.d.ts +11 -0
  76. package/lib/core/configuration/tree-options.interface.d.ts +32 -0
  77. package/lib/core/index.d.ts +5 -0
  78. package/lib/core/relationship.interface.d.ts +5 -0
  79. package/lib/core/tree-branch/branch-controller.d.ts +25 -0
  80. package/lib/core/tree-branch/tree-branch.d.ts +44 -0
  81. package/lib/core/tree-node-base.d.ts +25 -0
  82. package/lib/core/tree-root/root-controller.d.ts +19 -0
  83. package/lib/core/tree-root/tree-root.d.ts +30 -0
  84. package/lib/core/tree-service/tree.service.d.ts +9 -0
  85. package/lib/errors/index.d.ts +1 -0
  86. package/lib/errors/tree-error.d.ts +2 -0
  87. package/lib/events/drag/drag-end-event.d.ts +24 -0
  88. package/lib/events/drag/drag-start-event.d.ts +8 -0
  89. package/lib/events/drag/drop-event.d.ts +13 -0
  90. package/lib/events/drag/index.d.ts +3 -0
  91. package/lib/events/general/destruction-event.d.ts +8 -0
  92. package/lib/events/general/index.d.ts +1 -0
  93. package/lib/events/index.d.ts +3 -0
  94. package/lib/events/relational/graft-event.d.ts +15 -0
  95. package/lib/events/relational/index.d.ts +3 -0
  96. package/lib/events/relational/prune-event.d.ts +15 -0
  97. package/lib/events/relational/relational-tree-event.interface.d.ts +6 -0
  98. package/lib/extras/collapse/collapse.d.ts +11 -0
  99. package/lib/extras/collapse/collapse.module.d.ts +6 -0
  100. package/lib/extras/collapse/collapse.service.d.ts +9 -0
  101. package/lib/extras/collapse/index.d.ts +2 -0
  102. package/lib/extras/drag-and-drop/drag-and-drop.d.ts +16 -0
  103. package/lib/extras/drag-and-drop/drag-and-drop.module.d.ts +8 -0
  104. package/lib/extras/drag-and-drop/drag-and-drop.service.d.ts +16 -0
  105. package/lib/extras/drag-and-drop/drag-state.d.ts +23 -0
  106. package/lib/extras/drag-and-drop/draggable.directive.d.ts +12 -0
  107. package/lib/{custom-event-bindings/dragover-no-change-detect.directive.d.ts → extras/drag-and-drop/dragover-no-change-detect.d.ts} +14 -14
  108. package/lib/extras/drag-and-drop/dropzone-renderer.d.ts +28 -0
  109. package/lib/extras/drag-and-drop/index.d.ts +4 -0
  110. package/lib/legacy/index.d.ts +6 -0
  111. package/lib/legacy/legacy-component-obj.interface.d.ts +13 -0
  112. package/lib/legacy/legacy-tree-data.interface.d.ts +18 -0
  113. package/lib/legacy/legacy-tree-options.interface.d.ts +34 -0
  114. package/lib/legacy/legacy-tree.d.ts +14 -0
  115. package/lib/legacy/limble-tree-legacy.module.d.ts +8 -0
  116. package/lib/legacy/limble-tree-root/limble-tree-root.component.d.ts +28 -0
  117. package/lib/limble-tree.module.d.ts +9 -14
  118. package/lib/structure/branchable.interface.d.ts +4 -0
  119. package/lib/structure/component-container.interface.d.ts +8 -0
  120. package/lib/structure/event-conduit.interface.d.ts +6 -0
  121. package/lib/structure/graftable.interface.d.ts +6 -0
  122. package/lib/structure/index.d.ts +9 -0
  123. package/lib/structure/tree-branch-node.interface.d.ts +5 -0
  124. package/lib/structure/tree-event.interface.d.ts +5 -0
  125. package/lib/structure/tree-node.interface.d.ts +11 -0
  126. package/lib/structure/tree-plot.d.ts +1 -0
  127. package/lib/structure/tree-relationship.interface.d.ts +7 -0
  128. package/package.json +6 -14
  129. package/public-api.d.ts +8 -3
  130. package/shared/assert.d.ts +1 -0
  131. package/esm2020/lib/classes/Branch.mjs +0 -153
  132. package/esm2020/lib/classes/DropZone.mjs +0 -71
  133. package/esm2020/lib/classes/DropZoneLocation.mjs +0 -16
  134. package/esm2020/lib/custom-event-bindings/dragleave-no-change-detect.directive.mjs +0 -33
  135. package/esm2020/lib/custom-event-bindings/dragover-no-change-detect.directive.mjs +0 -39
  136. package/esm2020/lib/drop-zone/drop-zone.component.mjs +0 -75
  137. package/esm2020/lib/limble-tree-branch/limble-tree-branch.component.mjs +0 -110
  138. package/esm2020/lib/limble-tree-node/limble-tree-node.component.mjs +0 -467
  139. package/esm2020/lib/limble-tree-placeholder/limble-tree-placeholder.component.mjs +0 -70
  140. package/esm2020/lib/limble-tree-root/drop-zone.service.mjs +0 -376
  141. package/esm2020/lib/limble-tree-root/limble-tree-root.component.mjs +0 -172
  142. package/esm2020/lib/limble-tree-root/tree-construction-status.service.mjs +0 -33
  143. package/esm2020/lib/limble-tree-root/tree.service.mjs +0 -297
  144. package/esm2020/lib/singletons/component-creator.service.mjs +0 -19
  145. package/esm2020/lib/singletons/drag-state.service.mjs +0 -63
  146. package/esm2020/lib/singletons/global-events.service.mjs +0 -136
  147. package/esm2020/lib/util.mjs +0 -74
  148. package/lib/classes/Branch.d.ts +0 -26
  149. package/lib/classes/DropZone.d.ts +0 -27
  150. package/lib/classes/DropZoneLocation.d.ts +0 -9
  151. package/lib/custom-event-bindings/dragleave-no-change-detect.directive.d.ts +0 -13
  152. package/lib/drop-zone/drop-zone.component.d.ts +0 -18
  153. package/lib/limble-tree-branch/limble-tree-branch.component.d.ts +0 -28
  154. package/lib/limble-tree-node/limble-tree-node.component.d.ts +0 -53
  155. package/lib/limble-tree-placeholder/limble-tree-placeholder.component.d.ts +0 -21
  156. package/lib/limble-tree-root/drop-zone.service.d.ts +0 -62
  157. package/lib/limble-tree-root/limble-tree-root.component.d.ts +0 -37
  158. package/lib/limble-tree-root/tree-construction-status.service.d.ts +0 -15
  159. package/lib/limble-tree-root/tree.service.d.ts +0 -132
  160. package/lib/singletons/component-creator.service.d.ts +0 -9
  161. package/lib/singletons/drag-state.service.d.ts +0 -35
  162. package/lib/singletons/global-events.service.d.ts +0 -13
  163. package/lib/util.d.ts +0 -13
@@ -1,2256 +1,1434 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, ChangeDetectionStrategy, Input, ViewContainerRef, ViewChild, ElementRef, EventEmitter, Directive, Output, NgZone, NgModule } from '@angular/core';
3
- import { Subject, BehaviorSubject, fromEvent, merge, EMPTY } from 'rxjs';
4
- import { tap, filter, debounce, throttleTime, skip, first, skipUntil, debounceTime } from 'rxjs/operators';
5
- import * as i2 from '@angular/common';
2
+ import { Injectable, NgModule, EventEmitter, Directive, Input, Output, Component, NgZone, ViewContainerRef, ViewChild, ViewChildren, createComponent, EnvironmentInjector, HostListener } from '@angular/core';
3
+ import { BehaviorSubject, Subject, fromEvent, merge, map, filter, first } from 'rxjs';
4
+ import * as i1 from '@angular/common';
6
5
  import { CommonModule } from '@angular/common';
6
+ import { throttleTime } from 'rxjs/operators';
7
7
 
8
- function arraysAreEqual(array1, array2) {
9
- if (array1.length !== array2.length) {
10
- return false;
11
- }
12
- for (const [index, value1] of array1.entries()) {
13
- const value2 = array2[index];
14
- if (value1 instanceof Array && value2 instanceof Array) {
15
- if (!arraysAreEqual(value1, value2)) {
16
- return false;
17
- }
18
- }
19
- else if (value1 !== value2) {
20
- return false;
21
- }
22
- }
23
- return true;
24
- }
25
- function isElementDescendant(potentialAncestor, potentialDescendant) {
26
- if (potentialAncestor === potentialDescendant) {
27
- return true;
28
- }
29
- let cursor = potentialDescendant.parentNode;
30
- while (cursor !== document) {
31
- if (cursor === null) {
32
- //Did not reach `document` or ancestor. potentialDescendant is not part of the DOM.
33
- return undefined;
34
- }
35
- if (cursor === potentialAncestor) {
36
- return true;
37
- }
38
- cursor = cursor.parentNode;
39
- }
40
- return false;
41
- }
42
- function isNestingAllowed(options, nodeData) {
43
- return (options !== undefined &&
44
- (options.allowNesting === true ||
45
- (typeof options.allowNesting === "function" &&
46
- nodeData !== undefined &&
47
- options.allowNesting(nodeData) === true)));
48
- }
49
- function isDraggingAllowed(options, nodeData) {
50
- return (options !== undefined &&
51
- (options.allowDragging === true ||
52
- (typeof options.allowDragging === "function" &&
53
- nodeData !== undefined &&
54
- options.allowDragging(nodeData) === true)));
55
- }
56
- function isFirefox() {
57
- return navigator.userAgent.includes("Firefox");
58
- }
59
- /** Because drop zones can disappear when the mouse moves, sometimes
60
- * moving the mouse just a little bit inside the tree causes the tree to
61
- * shrink such that the mouse is no longer over the tree. In this case,
62
- * a dragleave event may not fire, and we can't clear the drop zones. This
63
- * function is used to catch this edge case.
64
- */
65
- function suddenTreeExit(event) {
66
- if (event.target === null || !(event.target instanceof Element)) {
67
- throw new Error("failed to get event target element");
68
- }
69
- const treeEventHost = event.target.closest(".tree-event-host");
70
- if (treeEventHost === null) {
71
- console.log(event.target);
72
- throw new Error("failed to find treeEventHost");
73
- }
74
- const rect = treeEventHost.getBoundingClientRect();
75
- const clientY = event.clientY;
76
- if (clientY > rect.bottom || clientY < rect.top) {
77
- return true;
78
- }
79
- return false;
8
+ class TreeCollapser {
9
+ constructor() {
10
+ this.tempStorage = new Map();
11
+ }
12
+ collapse(treeBranch) {
13
+ if (treeBranch.branches().length === 0)
14
+ return;
15
+ const branches = [];
16
+ this.tempStorage.set(treeBranch, branches);
17
+ treeBranch.branches().forEach((branch) => {
18
+ branch.prune();
19
+ branches.push(branch);
20
+ });
21
+ }
22
+ expand(treeBranch) {
23
+ const branches = this.tempStorage.get(treeBranch);
24
+ if (branches === undefined)
25
+ return;
26
+ branches.forEach((branch) => {
27
+ branch.graftTo(treeBranch);
28
+ });
29
+ this.tempStorage.delete(treeBranch);
30
+ treeBranch.detectChanges();
31
+ }
32
+ isCollapsed(treeBranch) {
33
+ return this.tempStorage.has(treeBranch);
34
+ }
35
+ storePrecollapsedNode(parent, branch) {
36
+ var _a;
37
+ this.tempStorage.set(parent, ((_a = this.tempStorage.get(parent)) !== null && _a !== void 0 ? _a : []).concat(branch));
38
+ }
80
39
  }
40
+ const treeCollapser = new TreeCollapser();
81
41
 
82
- class DropZoneLocation {
83
- constructor(parentCoordinates, insertIndex) {
84
- this.parentCoordinates = parentCoordinates;
85
- this.insertIndex = insertIndex;
86
- }
87
- getFullInsertCoordinates() {
88
- return [...this.parentCoordinates, this.insertIndex];
89
- }
90
- setParentCoordinates(coordinates) {
91
- this.parentCoordinates = coordinates;
92
- }
93
- setInsertIndex(index) {
94
- this.insertIndex = index;
95
- }
42
+ class TreeCollapseService {
43
+ collapse(treeBranch) {
44
+ treeCollapser.collapse(treeBranch);
45
+ }
46
+ expand(treeBranch) {
47
+ treeCollapser.expand(treeBranch);
48
+ }
49
+ isCollapsed(treeBranch) {
50
+ return treeCollapser.isCollapsed(treeBranch);
51
+ }
96
52
  }
53
+ TreeCollapseService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
54
+ TreeCollapseService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService });
55
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseService, decorators: [{
56
+ type: Injectable
57
+ }] });
97
58
 
98
- class DropZone {
99
- constructor(parentCoordinates, insertIndex) {
100
- this.location = new DropZoneLocation(parentCoordinates, insertIndex);
101
- this.rendered = false;
102
- this.visible = false;
103
- this.active = false;
104
- this.commChannel = new Subject();
105
- }
106
- static dropZoneLocationsAreEqual(valueA, valueB) {
107
- return arraysAreEqual(valueA.getFullInsertCoordinates(), valueB.getFullInsertCoordinates());
108
- }
109
- isRendered(set = undefined) {
110
- if (set !== undefined) {
111
- this.rendered = set;
112
- if (this.commChannel !== undefined) {
113
- this.commChannel.next("checkRendered");
114
- }
115
- if (this.rendered === false) {
116
- this.isVisible(false);
117
- }
118
- }
119
- return this.rendered;
120
- }
121
- isVisible(set = undefined) {
122
- if (set !== undefined) {
123
- this.visible = set;
124
- if (this.commChannel !== undefined) {
125
- this.commChannel.next("checkVisible");
126
- }
127
- if (this.visible === false) {
128
- this.isActive(false);
129
- }
130
- }
131
- return this.visible;
132
- }
133
- isActive(set = undefined) {
134
- if (set !== undefined) {
135
- this.active = set;
136
- if (this.commChannel !== undefined) {
137
- this.commChannel.next("checkActive");
138
- }
139
- }
140
- return this.active;
141
- }
142
- getLocation() {
143
- return this.location;
144
- }
145
- getFamily() {
146
- return this.family;
147
- }
148
- setFamily(family) {
149
- this.family = family;
150
- }
151
- getCommChannel() {
152
- return this.commChannel;
153
- }
154
- getFullInsertCoordinates() {
155
- return this.location.getFullInsertCoordinates();
156
- }
157
- setHost(host) {
158
- this.host = host;
159
- return this.host;
160
- }
161
- getHost() {
162
- return this.host;
163
- }
59
+ class TreeCollapseModule {
164
60
  }
61
+ TreeCollapseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
62
+ TreeCollapseModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule });
63
+ TreeCollapseModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, providers: [TreeCollapseService] });
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, decorators: [{
65
+ type: NgModule,
66
+ args: [{
67
+ providers: [TreeCollapseService]
68
+ }]
69
+ }] });
165
70
 
166
- class DragStateService {
167
- constructor() {
168
- this.state = "idle";
169
- this.state$ = new BehaviorSubject(this.state);
170
- }
171
- /** Called to indicate that something is being dragged. Stores that something for later. */
172
- dragging(branch, parentContainer) {
173
- this._tempData = {
174
- branch: branch,
175
- parentContainer: parentContainer
176
- };
177
- this.state = "dragging";
178
- this.state$.next(this.state);
179
- }
180
- /** Called to indicate that there is a valid active drop zone. Drop is now possible. */
181
- droppable() {
182
- if (this.state !== "dragging") {
183
- throw new Error("Can only call `droppable` when state is `dragging`");
184
- }
185
- this.state = "droppable";
186
- this.state$.next(this.state);
187
- }
188
- /** Called to indicate that there is no longer a valid active drop zone. Drop is no longer possible. */
189
- notDroppable() {
190
- if (this.state !== "droppable") {
191
- throw new Error("Can only call `notDroppable` when state is `droppable`");
192
- }
193
- this.state = "dragging";
194
- this.state$.next(this.state);
195
- }
196
- /** Called to indicate that a drop into a valid drop zone has occurred. Returns the item that was dropped. */
197
- capture() {
198
- var _a;
199
- if (this.state !== "droppable") {
200
- throw new Error("Can only move to `captured` state from `droppable` state");
201
- }
202
- this.state = "captured";
203
- this.state$.next(this.state);
204
- return (_a = this._tempData) === null || _a === void 0 ? void 0 : _a.branch;
205
- }
206
- /** Called to reset the service for future drags */
207
- release() {
208
- this._tempData = undefined;
209
- this.state = "idle";
210
- this.state$.next(this.state);
211
- }
212
- /** gets the current thing being dragged, if any. */
213
- getData() {
214
- return this._tempData;
215
- }
216
- /** gets the current state */
217
- getState() {
218
- return this.state;
219
- }
220
- }
221
- DragStateService.ɵfac = function DragStateService_Factory(t) { return new (t || DragStateService)(); };
222
- DragStateService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DragStateService, factory: DragStateService.ɵfac });
223
- (function () {
224
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DragStateService, [{
225
- type: Injectable
226
- }], function () { return []; }, null);
227
- })();
71
+ class Configuration {
72
+ constructor() {
73
+ this.configStorage = new Map();
74
+ this.configStorage = new Map();
75
+ }
76
+ setConfig(root, options) {
77
+ this.configStorage.set(root, options);
78
+ }
79
+ getConfig(root) {
80
+ return this.configStorage.get(root);
81
+ }
82
+ delete(root) {
83
+ this.configStorage.delete(root);
84
+ }
85
+ }
86
+ const config = new Configuration();
228
87
 
229
- class TreeConstructionStatus {
230
- constructor() {
231
- this.beingBuilt = 0;
232
- this.isReady = false;
233
- this.stable$ = new BehaviorSubject(this.treeIsStable());
234
- }
235
- constructing() {
236
- this.beingBuilt++;
237
- this.emit();
238
- }
239
- doneConstructing() {
240
- this.beingBuilt--;
241
- this.emit();
242
- }
243
- treeIsStable() {
244
- return this.isReady === true && this.beingBuilt === 0;
245
- }
246
- ready(val) {
247
- this.isReady = val;
248
- }
249
- emit() {
250
- this.stable$.next(this.treeIsStable());
251
- }
252
- }
253
- TreeConstructionStatus.ɵfac = function TreeConstructionStatus_Factory(t) { return new (t || TreeConstructionStatus)(); };
254
- TreeConstructionStatus.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TreeConstructionStatus, factory: TreeConstructionStatus.ɵfac });
255
- (function () {
256
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TreeConstructionStatus, [{
257
- type: Injectable
258
- }], function () { return []; }, null);
259
- })();
88
+ class TreeError extends Error {
89
+ }
260
90
 
261
- function sortFamily(memberA, memberB) {
262
- const aCoordinates = memberA.getFullInsertCoordinates();
263
- const bCoordinates = memberB.getFullInsertCoordinates();
264
- if (aCoordinates.length > bCoordinates.length) {
265
- return -1;
266
- }
267
- if (aCoordinates.length < bCoordinates.length) {
268
- return 1;
269
- }
270
- return 0;
271
- }
272
- class DropZoneService {
273
- constructor(dragStateService, treeConstructionStatus) {
274
- this.dragStateService = dragStateService;
275
- this.dropZoneArchive = new Set();
276
- this.dropZoneInventory = [];
277
- this.dropZoneFamilies = [];
278
- this.visibleFamily = null;
279
- this.activeDropZone = null;
280
- this.tempFamilies = [];
281
- this.setActiveDropZone(null);
282
- let treeIsStable = false;
283
- const treeIsStable$ = treeConstructionStatus.stable$.pipe(tap((value) => {
284
- treeIsStable = value;
285
- }), filter((value) => value === true));
286
- this.update$ = new Subject();
287
- this.update$
288
- .pipe(debounce(() => {
289
- if (treeIsStable === true) {
290
- //If tree is stable, continue right away
291
- return Promise.resolve();
292
- }
293
- //If tree is not stable, wait for it to become so.
294
- return treeIsStable$;
295
- }))
296
- .subscribe(() => {
297
- setTimeout(() => {
298
- this.updateDropZones();
299
- });
300
- });
301
- }
302
- addDropZone(newDropZone) {
303
- this.dropZoneArchive.add(newDropZone);
304
- }
305
- /** hides all drop zones */
306
- clearVisibleZones() {
307
- if (this.visibleFamily !== null) {
308
- for (const member of this.visibleFamily.members) {
309
- member.isVisible(false);
310
- }
311
- this.visibleFamily = null;
312
- }
313
- this.setActiveDropZone(null);
314
- }
315
- getActiveDropZone() {
316
- return this.activeDropZone;
317
- }
318
- getDropZone(coordinates) {
319
- const parent = [...coordinates];
320
- parent.pop();
321
- const index = coordinates[coordinates.length - 1];
322
- const location = new DropZoneLocation(parent, index);
323
- return this.dropZoneInventory.find((dropZone) => DropZone.dropZoneLocationsAreEqual(dropZone, location));
324
- }
325
- init(tree, treeOptions) {
326
- this.tree = tree;
327
- this.treeOptions = treeOptions;
328
- this.update();
329
- }
330
- removeDropZone(dropZone) {
331
- this.dropZoneArchive.delete(dropZone);
332
- }
333
- /** hides all drop zones, deletes all the family assignments,
334
- * and empties the dropZoneInventory
335
- */
336
- reset() {
337
- this.clearVisibleZones();
338
- this.dropZoneFamilies.length = 0;
339
- this.dropZoneInventory.length = 0;
340
- }
341
- /**
342
- * Restores the service to its initial state: hides all drop zones,
343
- * deletes all the family assignments, and empties the dropZoneInventory
344
- * and dropZoneArchive.
345
- */
346
- restart() {
347
- this.reset();
348
- this.dropZoneArchive.clear();
349
- }
350
- restoreFamilies() {
351
- if (this.tempFamilies.length === 2) {
352
- this.dropZoneFamilies.pop();
353
- this.dropZoneFamilies.push(this.tempFamilies[0]);
354
- for (const member of this.tempFamilies[0].members) {
355
- member.setFamily(this.tempFamilies[0]);
356
- }
357
- if (this.tempFamilies[1] !== null) {
358
- this.dropZoneFamilies.push(this.tempFamilies[1]);
359
- for (const member of this.tempFamilies[1].members) {
360
- member.setFamily(this.tempFamilies[1]);
361
- }
362
- }
363
- this.tempFamilies = [];
364
- }
365
- }
366
- /**
367
- * Shows the drop zone family of the drop zone indicated by `coordinates`.
368
- */
369
- showDropZoneFamily(
370
- /** Note: this drop zone may not exist in the dropZoneInventory; we have to search the inventory based on its location */
371
- dropZone, options = { joinFamilies: false, activateLowestInsteadOfFounder: false }) {
372
- if (this.activeDropZone !== null &&
373
- DropZone.dropZoneLocationsAreEqual(this.activeDropZone, dropZone)) {
374
- //Already showing the family with the appropriate active drop zone
375
- return;
376
- }
377
- if (this.visibleFamily !== null || this.activeDropZone !== null) {
378
- this.clearVisibleZones();
379
- }
380
- const target = this.dropZoneInventory.find((zone) => DropZone.dropZoneLocationsAreEqual(zone, dropZone));
381
- if (target === undefined) {
382
- throw new Error(`Could not find drop zone to show. location: ${JSON.stringify(dropZone.getLocation())}`);
383
- }
384
- const family = target.getFamily();
385
- if (options.joinFamilies === true) {
386
- const location1 = dropZone.getLocation();
387
- const location2 = new DropZoneLocation([...location1.parentCoordinates], location1.insertIndex + 1);
388
- const target2 = this.dropZoneInventory.find((zone) => DropZone.dropZoneLocationsAreEqual(zone, location2));
389
- if (target2 === undefined) {
390
- throw new Error("Could not find drop zone to show");
391
- }
392
- const family2 = target2.getFamily();
393
- if (family === undefined || family2 === undefined) {
394
- throw new Error("No family");
395
- }
396
- const newFamily = {
397
- founder: family.founder,
398
- members: [...family.members]
399
- };
400
- this.showDropZone(family.founder, true);
401
- for (const member of family.members.sort(sortFamily)) {
402
- member.setFamily(newFamily);
403
- if (member !== family.founder) {
404
- if (this.activeDropZone === null) {
405
- //Failed to activate a zone so far, so activate this one instead
406
- this.showDropZone(member, true);
407
- }
408
- else {
409
- this.showDropZone(member);
410
- }
411
- }
412
- }
413
- for (const member of family2.members) {
414
- member.setFamily(newFamily);
415
- if (member.getLocation().parentCoordinates.length <
416
- target2.getLocation().parentCoordinates.length) {
417
- newFamily.members.push(member);
418
- this.showDropZone(member);
419
- }
420
- }
421
- //Temporarily store the old families
422
- this.tempFamilies = [family, family2];
423
- //Remove the old families
424
- const familyIndex = this.dropZoneFamilies.indexOf(family);
425
- this.dropZoneFamilies.splice(familyIndex, 1);
426
- const family2Index = this.dropZoneFamilies.indexOf(family2);
427
- this.dropZoneFamilies.splice(family2Index, 1);
428
- //Add the new family
429
- this.dropZoneFamilies.push(newFamily);
430
- this.visibleFamily = newFamily;
431
- }
432
- else {
433
- if (family === undefined) {
434
- throw new Error("No family");
435
- }
436
- this.visibleFamily = family;
437
- this.showDropZone(family.founder, true);
438
- if (family.members.length > 1) {
439
- for (const member of family.members.sort(sortFamily)) {
440
- if (member !== family.founder) {
441
- if (this.activeDropZone === null) {
442
- //Failed to activate a zone so far, so activate this one instead
443
- this.showDropZone(member, true);
444
- }
445
- else {
446
- this.showDropZone(member);
447
- }
448
- }
449
- }
450
- }
451
- }
452
- if (options.activateLowestInsteadOfFounder === true &&
453
- this.visibleFamily.members.length > 1) {
454
- const lowestMember = [...this.visibleFamily.members]
455
- .sort(sortFamily)
456
- .pop();
457
- if (lowestMember === undefined) {
458
- throw new Error("Could not get lowest member");
459
- }
460
- this.swapActiveDropZone(lowestMember);
461
- }
462
- }
463
- swapActiveDropZone(newActiveDropZone) {
464
- if (this.visibleFamily === null) {
465
- throw new Error("No visible family available for swapping");
466
- }
467
- const index = this.visibleFamily.members.findIndex((dropZone) => dropZone === newActiveDropZone);
468
- if (index === -1) {
469
- throw new Error("failed to swap active drop zone");
470
- }
471
- this.setActiveDropZone(newActiveDropZone);
472
- }
473
- update() {
474
- this.update$.next(null);
475
- }
476
- assignFamilies() {
477
- const orphanZones = [...this.dropZoneInventory];
478
- const deepestMembers = orphanZones
479
- .filter((zone) => {
480
- const location = zone.getLocation();
481
- return (location.insertIndex === 0 &&
482
- location.parentCoordinates.length > 0);
483
- })
484
- .sort((valueA, valueB) => {
485
- var _a, _b, _c, _d;
486
- const aCoordinates = valueA.getFullInsertCoordinates();
487
- const bCoordinates = valueB.getFullInsertCoordinates();
488
- const length = Math.max(aCoordinates.length, bCoordinates.length);
489
- for (let index = 0; index < length; index++) {
490
- if (((_a = aCoordinates[index]) !== null && _a !== void 0 ? _a : -1) > ((_b = bCoordinates[index]) !== null && _b !== void 0 ? _b : -1)) {
491
- return -1;
492
- }
493
- else if (((_c = aCoordinates[index]) !== null && _c !== void 0 ? _c : -1) < ((_d = bCoordinates[index]) !== null && _d !== void 0 ? _d : -1)) {
494
- return 1;
495
- }
496
- }
497
- return 0;
498
- });
499
- for (const dropZone of deepestMembers) {
500
- if (!orphanZones.includes(dropZone)) {
501
- continue;
502
- }
503
- const family = {
504
- founder: dropZone,
505
- members: []
506
- };
507
- dropZone.setFamily(family);
508
- //See if there are any orphans that belong to this family and claim them.
509
- const cursor = [...dropZone.getFullInsertCoordinates()];
510
- while (cursor.length > 0) {
511
- const familyMemberIndex = orphanZones.findIndex((zone) => arraysAreEqual(zone.getFullInsertCoordinates(), cursor));
512
- if (familyMemberIndex !== -1) {
513
- const familyMember = orphanZones.splice(familyMemberIndex, 1)[0];
514
- family.members.push(familyMember);
515
- familyMember.setFamily(family);
516
- }
517
- cursor.pop();
518
- cursor[cursor.length - 1]++;
519
- }
520
- this.dropZoneFamilies.push(family);
521
- }
522
- for (const dropZone of orphanZones.filter((zone) => zone.getFullInsertCoordinates().length === 1)) {
523
- const family = {
524
- founder: dropZone,
525
- members: [dropZone]
526
- };
527
- dropZone.setFamily(family);
528
- this.dropZoneFamilies.push(family);
529
- orphanZones.splice(orphanZones.indexOf(dropZone), 1);
530
- }
531
- if (orphanZones.length !== 0) {
532
- let orphans = "";
533
- for (const zone of orphanZones) {
534
- orphans += `${JSON.stringify(zone.getLocation())}, `;
535
- }
536
- orphans = orphans.slice(0, orphans.length - 2);
537
- throw new Error(`Some zones were not assigned to a family. The orphan zones have the following locations: ${orphans}`);
538
- }
539
- }
540
- buildInventory() {
541
- //We do this funky string array because it is faster than doing direct array comparisons
542
- const inventoryCoordinates = [];
543
- for (const dropZone of this.dropZoneArchive) {
544
- const coordinates = dropZone.getFullInsertCoordinates().join(",");
545
- if (inventoryCoordinates.includes(coordinates)) {
546
- dropZone.isRendered(false);
547
- }
548
- else {
549
- this.dropZoneInventory.push(dropZone);
550
- inventoryCoordinates.push(coordinates);
551
- dropZone.isRendered(true);
552
- }
553
- }
554
- }
555
- setActiveDropZone(dropZone) {
556
- if (this.activeDropZone !== null) {
557
- this.activeDropZone.isActive(false);
558
- }
559
- this.activeDropZone = dropZone;
560
- if (this.activeDropZone !== null &&
561
- this.dragStateService.getState() !== "droppable") {
562
- this.dragStateService.droppable();
563
- }
564
- else if (this.activeDropZone === null &&
565
- this.dragStateService.getState() === "droppable") {
566
- this.dragStateService.notDroppable();
567
- }
568
- if (this.activeDropZone !== null) {
569
- this.activeDropZone.isActive(true);
570
- }
571
- }
572
- showDropZone(dropZone, active = false) {
573
- if (this.tree === undefined) {
574
- throw new Error("DropZoneService not initialized");
575
- }
576
- if (!this.zoneIsAllowed(dropZone)) {
577
- //User settings indicate to skip this drop zone
578
- return false;
579
- }
580
- const parent = this.tree.findByCoordinates(dropZone.getLocation().parentCoordinates);
581
- if (parent === undefined) {
582
- throw new Error("Bad family member");
583
- }
584
- dropZone.isVisible(true);
585
- if (active === true) {
586
- this.setActiveDropZone(dropZone);
587
- }
588
- return true;
589
- }
590
- updateDropZones() {
591
- this.reset();
592
- this.buildInventory();
593
- this.assignFamilies();
594
- }
595
- zoneIsAllowed(dropZone) {
596
- if (this.treeOptions === undefined || this.tree === undefined) {
597
- throw new Error("dropZoneService not initialized");
598
- }
599
- const data = this.dragStateService.getData();
600
- if (data === undefined) {
601
- throw new Error("Can't get dragged node");
602
- }
603
- const parentCoordinates = dropZone.getLocation().parentCoordinates;
604
- const dropZoneParent = this.tree.findByCoordinates(parentCoordinates);
605
- if (dropZoneParent === undefined) {
606
- throw new Error("Could not get drop zone parent");
607
- }
608
- if (parentCoordinates.length > 0 &&
609
- !isNestingAllowed(this.treeOptions, dropZoneParent.data)) {
610
- return false;
611
- }
612
- const dropZoneIndex = dropZone.getLocation().insertIndex;
613
- if (dropZoneIndex === undefined) {
614
- throw new Error("Could not get drop zone index");
615
- }
616
- const draggedNode = data.branch;
617
- if (!this.treeOptions.allowDrop(draggedNode.data, dropZoneParent.data, dropZoneIndex)) {
618
- return false;
619
- }
620
- return true;
621
- }
622
- }
623
- DropZoneService.ɵfac = function DropZoneService_Factory(t) { return new (t || DropZoneService)(i0.ɵɵinject(DragStateService), i0.ɵɵinject(TreeConstructionStatus)); };
624
- DropZoneService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DropZoneService, factory: DropZoneService.ɵfac });
625
- (function () {
626
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropZoneService, [{
627
- type: Injectable
628
- }], function () { return [{ type: DragStateService }, { type: TreeConstructionStatus }]; }, null);
629
- })();
91
+ class DragEndEvent {
92
+ constructor(source, endpoints) {
93
+ this._source = source;
94
+ this._oldParent = endpoints.oldParent;
95
+ this._oldIndex = endpoints.oldIndex;
96
+ this._newParent = endpoints.newParent;
97
+ this._newIndex = endpoints.newIndex;
98
+ }
99
+ type() {
100
+ return "drag end";
101
+ }
102
+ source() {
103
+ return this._source;
104
+ }
105
+ newIndex() {
106
+ return this._newIndex;
107
+ }
108
+ newParent() {
109
+ return this._newParent;
110
+ }
111
+ oldIndex() {
112
+ return this._oldIndex;
113
+ }
114
+ oldParent() {
115
+ return this._oldParent;
116
+ }
117
+ }
630
118
 
631
- class Branch {
632
- constructor(data) {
633
- this.data = data;
634
- this.children = [];
635
- this.parent = null;
636
- }
637
- isRoot() {
638
- return this.parent === null;
639
- }
640
- getParent() {
641
- return this.parent;
642
- }
643
- setParent(parent) {
644
- this.parent = parent;
645
- }
646
- findByCoordinates(relativeCoordinates) {
647
- let cursor = this;
648
- for (const index of relativeCoordinates.values()) {
649
- cursor = cursor.getChild(index);
650
- if (cursor === undefined) {
651
- return undefined;
652
- }
653
- }
654
- return cursor;
655
- }
656
- getCoordinates() {
657
- const coordinates = [];
658
- let cursor = this;
659
- while (cursor.parent !== null) {
660
- const cursorIndex = cursor.getIndex();
661
- if (cursorIndex === undefined || cursorIndex === null) {
662
- throw new Error("Could not get cursor index");
663
- }
664
- coordinates.unshift(cursorIndex);
665
- cursor = cursor.parent;
666
- }
667
- return coordinates;
668
- }
669
- getChild(index) {
670
- return this.children[index];
671
- }
672
- getChildren() {
673
- return this.children;
674
- }
675
- clearChildren() {
676
- for (const child of this.children) {
677
- child.setParent(null);
678
- }
679
- this.children.length = 0;
680
- }
681
- getIndex() {
682
- if (this.parent === null) {
683
- return null;
684
- }
685
- const index = this.parent.children.findIndex((branch) => branch === this);
686
- if (index === -1) {
687
- return undefined;
688
- }
689
- return index;
690
- }
691
- getDescendant(relativeCoordinates) {
692
- let cursor = this;
693
- for (const index of relativeCoordinates) {
694
- cursor = cursor.children[index];
695
- if (cursor === undefined) {
696
- return undefined;
697
- }
698
- }
699
- return cursor;
700
- }
701
- findDescendant(predicate) {
702
- if (predicate(this.data) === true) {
703
- return this;
704
- }
705
- if (this.children.length > 0) {
706
- for (const child of this.children) {
707
- const foundDeeper = child.findDescendant(predicate);
708
- if (foundDeeper !== undefined) {
709
- return foundDeeper;
710
- }
711
- }
712
- }
713
- return undefined;
714
- }
715
- getAncestors() {
716
- const result = [];
717
- let cursor = this;
718
- while (cursor.parent !== null) {
719
- result.push(cursor.parent);
720
- cursor = cursor.parent;
721
- }
722
- return result;
723
- }
724
- appendChild(child) {
725
- if (child.getParent() !== null) {
726
- child.remove();
727
- }
728
- child.setParent(this);
729
- this.children.push(child);
730
- return child;
731
- }
732
- insertChild(child, index) {
733
- const isOwnChild = this.children.indexOf(child);
734
- if (isOwnChild === -1) {
735
- if (child.getParent() !== null) {
736
- child.remove();
737
- }
738
- child.setParent(this);
739
- this.children.splice(index, 0, child);
740
- }
741
- else {
742
- if (index > isOwnChild) {
743
- //Insert first, then remove
744
- this.children.splice(index, 0, child);
745
- this.removeChild(isOwnChild);
746
- child.setParent(this);
747
- }
748
- else {
749
- //remove first, then insert
750
- child.remove();
751
- this.children.splice(index, 0, child);
752
- child.setParent(this);
753
- }
754
- }
755
- return child;
756
- }
757
- removeChild(index) {
758
- const target = this.children.splice(index, 1)[0];
759
- target.setParent(null);
760
- return target;
761
- }
762
- remove() {
763
- const index = this.getIndex();
764
- if (this.parent === null || index === undefined || index === null) {
765
- throw new Error("can't remove root");
766
- }
767
- return this.parent.removeChild(index);
768
- }
769
- copy() {
770
- const copy = this.copyHelper();
771
- copy.setParent(null);
772
- return copy;
773
- }
774
- copyHelper() {
775
- const copy = new Branch(this.data);
776
- for (const child of this.children) {
777
- const newChild = copy.appendChild(child.copyHelper());
778
- newChild.parent = copy;
779
- }
780
- return copy;
781
- }
119
+ class DragStartEvent {
120
+ constructor(source) {
121
+ this._source = source;
122
+ }
123
+ type() {
124
+ return "drag start";
125
+ }
126
+ source() {
127
+ return this._source;
128
+ }
782
129
  }
783
130
 
784
- const _c0$3 = function (a0, a1) { return { active: a0, related: a1 }; };
785
- function DropZoneComponent_div_0_Template(rf, ctx) {
786
- if (rf & 1) {
787
- const _r2 = i0.ɵɵgetCurrentView();
788
- i0.ɵɵelementStart(0, "div", 1);
789
- i0.ɵɵlistener("dragenter", function DropZoneComponent_div_0_Template_div_dragenter_0_listener() { i0.ɵɵrestoreView(_r2); const ctx_r1 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r1.dragenterHandler()); });
790
- i0.ɵɵelement(1, "div", 2);
791
- i0.ɵɵelementEnd();
792
- }
793
- if (rf & 2) {
794
- const ctx_r0 = i0.ɵɵnextContext();
795
- i0.ɵɵadvance(1);
796
- i0.ɵɵproperty("ngClass", i0.ɵɵpureFunction2(1, _c0$3, ctx_r0.active, !ctx_r0.active));
797
- }
798
- }
799
- class DropZoneComponent {
800
- constructor(dropZoneService, changeDetectorRef) {
801
- this.dropZoneService = dropZoneService;
802
- this.changeDetectorRef = changeDetectorRef;
803
- this.visible = false;
804
- this.active = false;
805
- }
806
- dragenterHandler() {
807
- if (this.dropZone === undefined || this.active === true) {
808
- return;
809
- }
810
- this.dropZoneService.swapActiveDropZone(this.dropZone);
811
- }
812
- ngOnInit() {
813
- if (this.dropZone === undefined) {
814
- throw new Error("No drop zone object at component initialization");
815
- }
816
- this.commSubscription = this.dropZone
817
- .getCommChannel()
818
- .subscribe((message) => {
819
- var _a, _b, _c, _d;
820
- switch (message) {
821
- case "checkVisible": {
822
- this.visible = (_b = (_a = this.dropZone) === null || _a === void 0 ? void 0 : _a.isVisible()) !== null && _b !== void 0 ? _b : false;
823
- break;
824
- }
825
- case "checkActive": {
826
- this.active = (_d = (_c = this.dropZone) === null || _c === void 0 ? void 0 : _c.isActive()) !== null && _d !== void 0 ? _d : false;
827
- break;
828
- }
829
- case "checkRendered": {
830
- //Do nothing. This message is for other subscribers
831
- break;
832
- }
833
- default: {
834
- throw new Error("unhandled comm message");
835
- }
836
- }
837
- this.changeDetectorRef.detectChanges();
838
- });
839
- }
840
- ngOnDestroy() {
841
- if (this.commSubscription !== undefined) {
842
- this.commSubscription.unsubscribe();
843
- }
844
- }
845
- }
846
- DropZoneComponent.ɵfac = function DropZoneComponent_Factory(t) { return new (t || DropZoneComponent)(i0.ɵɵdirectiveInject(DropZoneService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef)); };
847
- DropZoneComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DropZoneComponent, selectors: [["drop-zone"]], inputs: { dropZone: "dropZone" }, decls: 1, vars: 1, consts: [["class", "dropZoneContainer", 3, "dragenter", 4, "ngIf"], [1, "dropZoneContainer", 3, "dragenter"], [3, "ngClass"]], template: function DropZoneComponent_Template(rf, ctx) {
848
- if (rf & 1) {
849
- i0.ɵɵtemplate(0, DropZoneComponent_div_0_Template, 2, 4, "div", 0);
850
- }
851
- if (rf & 2) {
852
- i0.ɵɵproperty("ngIf", ctx.visible);
853
- }
854
- }, dependencies: [i2.NgClass, i2.NgIf], styles: [".active[_ngcontent-%COMP%]{margin:10px 0;width:calc(100% - 20px);height:105px;border-radius:5px;background:#f0f9ff;border:2px dashed #bed2db;box-sizing:border-box}.related[_ngcontent-%COMP%]{margin:10px 0;width:calc(100% - 20px);height:30px;border-radius:5px;background:#fff6f0;border:1px dashed #dbccbe;box-sizing:border-box;opacity:.8}.dropZoneContainer[_ngcontent-%COMP%]{position:relative}"], changeDetection: 0 });
855
- (function () {
856
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DropZoneComponent, [{
857
- type: Component,
858
- args: [{ selector: "drop-zone", changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"dropZoneContainer\" (dragenter)=\"dragenterHandler()\" *ngIf=\"visible\">\n <div [ngClass]=\"{ active: active, related: !active }\"></div>\n</div>\n", styles: [".active{margin:10px 0;width:calc(100% - 20px);height:105px;border-radius:5px;background:#f0f9ff;border:2px dashed #bed2db;box-sizing:border-box}.related{margin:10px 0;width:calc(100% - 20px);height:30px;border-radius:5px;background:#fff6f0;border:1px dashed #dbccbe;box-sizing:border-box;opacity:.8}.dropZoneContainer{position:relative}\n"] }]
859
- }], function () { return [{ type: DropZoneService }, { type: i0.ChangeDetectorRef }]; }, { dropZone: [{
860
- type: Input
861
- }] });
862
- })();
131
+ function assert(condition) {
132
+ if (condition) {
133
+ return;
134
+ }
135
+ throw new Error("Assertion Failed!");
136
+ }
863
137
 
864
- const _c0$2 = ["children"];
865
- function LimbleTreeBranchComponent_drop_zone_1_Template(rf, ctx) {
866
- if (rf & 1) {
867
- i0.ɵɵelement(0, "drop-zone", 3);
868
- }
869
- if (rf & 2) {
870
- const ctx_r0 = i0.ɵɵnextContext();
871
- i0.ɵɵproperty("dropZone", ctx_r0.dropZoneInside);
872
- }
873
- }
874
- function LimbleTreeBranchComponent_ng_template_3_Template(rf, ctx) { }
875
- class LimbleTreeBranchComponent {
876
- constructor(treeService, changeDetectorRef, dropZoneService, treeConstructionStatus, ngZone) {
877
- var _a;
878
- this.treeService = treeService;
879
- this.changeDetectorRef = changeDetectorRef;
880
- this.dropZoneService = dropZoneService;
881
- this.treeConstructionStatus = treeConstructionStatus;
882
- this.ngZone = ngZone;
883
- this.treeConstructionStatus.constructing();
884
- this.indent = (_a = this.treeService.treeOptions) === null || _a === void 0 ? void 0 : _a.indent;
885
- this.renderDropZoneInside = false;
886
- }
887
- ngOnInit() {
888
- this.addDropZoneInside();
889
- this.ngZone.runOutsideAngular(() => {
890
- if (this.dropZoneInside === undefined) {
891
- throw new Error("drop zone inside is not defined");
892
- }
893
- this.dropZoneInside
894
- .getCommChannel()
895
- .pipe(filter((message) => message === "checkRendered"))
896
- .subscribe(() => {
897
- if (this.dropZoneInside === undefined ||
898
- this.branch === undefined) {
899
- throw new Error("Zones not registered");
900
- }
901
- if (isNestingAllowed(this.treeService.treeOptions, this.branch.data)) {
902
- this.renderDropZoneInside = this.dropZoneInside.isRendered();
903
- }
904
- });
905
- });
906
- }
907
- ngAfterViewInit() {
908
- this.reRender();
909
- this.setDropZoneHost();
910
- this.treeConstructionStatus.doneConstructing();
911
- this.changeDetectorRef.detectChanges();
912
- }
913
- ngOnDestroy() {
914
- if (this.dropZoneInside !== undefined) {
915
- this.dropZoneService.removeDropZone(this.dropZoneInside);
916
- }
917
- this.treeService.cleanupSignal$.next(true);
918
- }
919
- addDropZoneInside() {
920
- if (this.branch === undefined) {
921
- throw new Error("failed to register drop zone inside");
922
- }
923
- this.dropZoneInside = new DropZone([...this.branch.getCoordinates()], 0);
924
- this.dropZoneService.addDropZone(this.dropZoneInside);
925
- }
926
- reRender() {
927
- if (this.children === undefined || this.branch === undefined) {
928
- throw new Error("Failed to render limble tree branch");
929
- }
930
- this.treeService.renderBranch(this.children, this.branch);
931
- }
932
- setDropZoneHost() {
933
- if (this.children === undefined || this.dropZoneInside === undefined) {
934
- throw new Error("Failed to add drop zone host");
935
- }
936
- this.dropZoneInside.setHost(this.children);
937
- }
938
- }
939
- LimbleTreeBranchComponent.ɵfac = function LimbleTreeBranchComponent_Factory(t) { return new (t || LimbleTreeBranchComponent)(i0.ɵɵdirectiveInject(TreeService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(DropZoneService), i0.ɵɵdirectiveInject(TreeConstructionStatus), i0.ɵɵdirectiveInject(i0.NgZone)); };
940
- LimbleTreeBranchComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LimbleTreeBranchComponent, selectors: [["limble-tree-branch"]], viewQuery: function LimbleTreeBranchComponent_Query(rf, ctx) {
941
- if (rf & 1) {
942
- i0.ɵɵviewQuery(_c0$2, 5, ViewContainerRef);
943
- }
944
- if (rf & 2) {
945
- let _t;
946
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.children = _t.first);
947
- }
948
- }, inputs: { branch: "branch" }, decls: 5, vars: 4, consts: [[3, "dropZone", 4, "ngIf"], [1, "limble-child-nodes", 3, "hidden"], ["children", ""], [3, "dropZone"]], template: function LimbleTreeBranchComponent_Template(rf, ctx) {
949
- if (rf & 1) {
950
- i0.ɵɵelementStart(0, "div");
951
- i0.ɵɵtemplate(1, LimbleTreeBranchComponent_drop_zone_1_Template, 1, 1, "drop-zone", 0);
952
- i0.ɵɵelementStart(2, "span", 1);
953
- i0.ɵɵtemplate(3, LimbleTreeBranchComponent_ng_template_3_Template, 0, 0, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
954
- i0.ɵɵelementEnd()();
955
- }
956
- if (rf & 2) {
957
- i0.ɵɵstyleProp("margin-left", ctx.indent, "px");
958
- i0.ɵɵadvance(1);
959
- i0.ɵɵproperty("ngIf", ctx.renderDropZoneInside);
960
- i0.ɵɵadvance(1);
961
- i0.ɵɵproperty("hidden", ctx.branch && ctx.branch.data.collapsed);
962
- }
963
- }, dependencies: [i2.NgIf, DropZoneComponent] });
964
- (function () {
965
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreeBranchComponent, [{
966
- type: Component,
967
- args: [{ selector: "limble-tree-branch", template: "<div [style.marginLeft.px]=\"indent\">\n <drop-zone\n *ngIf=\"renderDropZoneInside\"\n [dropZone]=\"dropZoneInside\"\n ></drop-zone>\n <span [hidden]=\"branch && branch.data.collapsed\" class=\"limble-child-nodes\">\n <ng-template #children></ng-template>\n </span>\n</div>\n" }]
968
- }], function () { return [{ type: TreeService }, { type: i0.ChangeDetectorRef }, { type: DropZoneService }, { type: TreeConstructionStatus }, { type: i0.NgZone }]; }, { branch: [{
969
- type: Input
970
- }], children: [{
971
- type: ViewChild,
972
- args: ["children", { read: ViewContainerRef }]
973
- }] });
974
- })();
138
+ var DragStates;
139
+ (function (DragStates) {
140
+ DragStates[DragStates["Idle"] = 0] = "Idle";
141
+ DragStates[DragStates["Starting"] = 1] = "Starting";
142
+ DragStates[DragStates["Dragging"] = 2] = "Dragging";
143
+ DragStates[DragStates["Dropped"] = 3] = "Dropped";
144
+ })(DragStates || (DragStates = {}));
145
+ class DragState {
146
+ constructor() {
147
+ this._state = DragStates.Idle;
148
+ this.state$ = new BehaviorSubject(DragStates.Idle);
149
+ this.state$.subscribe((state) => {
150
+ this._state = state;
151
+ });
152
+ this.dragData = undefined;
153
+ }
154
+ getDragData() {
155
+ return this.dragData;
156
+ }
157
+ starting(treeBranch) {
158
+ assert(this._state === DragStates.Idle);
159
+ this.dragData = treeBranch;
160
+ this.state$.next(DragStates.Starting);
161
+ }
162
+ dragging() {
163
+ assert(this._state === DragStates.Starting);
164
+ this.state$.next(DragStates.Dragging);
165
+ }
166
+ dropped() {
167
+ assert(this._state === DragStates.Dragging);
168
+ this.state$.next(DragStates.Dropped);
169
+ }
170
+ restart() {
171
+ this.dragData = undefined;
172
+ this.state$.next(DragStates.Idle);
173
+ }
174
+ events() {
175
+ return this.state$;
176
+ }
177
+ state() {
178
+ return this._state;
179
+ }
180
+ }
181
+ const dragState = new DragState();
975
182
 
976
- class ComponentCreatorService {
977
- constructor(factoryResolver) {
978
- this.factoryResolver = factoryResolver;
979
- this.factoryResolver = factoryResolver;
980
- }
981
- appendComponent(component, viewContainerRef, index = undefined) {
982
- const componentFactory = this.factoryResolver.resolveComponentFactory(component);
983
- const componentRef = viewContainerRef.createComponent(componentFactory, index);
984
- return componentRef;
985
- }
986
- }
987
- ComponentCreatorService.ɵfac = function ComponentCreatorService_Factory(t) { return new (t || ComponentCreatorService)(i0.ɵɵinject(i0.ComponentFactoryResolver)); };
988
- ComponentCreatorService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ComponentCreatorService, factory: ComponentCreatorService.ɵfac });
989
- (function () {
990
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ComponentCreatorService, [{
991
- type: Injectable
992
- }], function () { return [{ type: i0.ComponentFactoryResolver }]; }, null);
993
- })();
183
+ class DropEvent {
184
+ constructor(source, parent, index) {
185
+ this._source = source;
186
+ this._parent = parent;
187
+ this._index = index;
188
+ }
189
+ type() {
190
+ return "drag end";
191
+ }
192
+ source() {
193
+ return this._source;
194
+ }
195
+ index() {
196
+ return this._index;
197
+ }
198
+ parent() {
199
+ return this._parent;
200
+ }
201
+ }
994
202
 
995
- function getScrollParent(element) {
996
- var _a;
997
- const regex = /(auto|scroll)/;
998
- const parents = (_node, parentList) => {
999
- if (_node === null || _node.parentNode === null) {
1000
- return parentList;
1001
- }
1002
- return parents(_node.parentElement, parentList.concat([_node]));
1003
- };
1004
- const style = (_node, prop) => getComputedStyle(_node, null).getPropertyValue(prop);
1005
- const overflow = (_node) => style(_node, "overflow") +
1006
- style(_node, "overflow-y") +
1007
- style(_node, "overflow-x");
1008
- const scroll = (_node) => regex.test(overflow(_node));
1009
- const parentList = parents(element.parentElement, []);
1010
- for (const parent of parentList) {
1011
- if (scroll(parent)) {
1012
- return parent;
1013
- }
1014
- }
1015
- return ((_a = document.scrollingElement) !== null && _a !== void 0 ? _a : document.documentElement);
1016
- }
1017
- class GlobalEventsService {
1018
- constructor(ngZone) {
1019
- this.ngZone = ngZone;
1020
- this.ngZone.runOutsideAngular(() => {
1021
- this.globalDrag$ = fromEvent(document, "drag");
1022
- });
1023
- this.scrolling = false;
1024
- }
1025
- addScrolling() {
1026
- this.ngZone.runOutsideAngular(() => {
1027
- if (this.globalDragSubscription !== undefined) {
1028
- return;
1029
- }
1030
- if (this.globalDrag$ === undefined) {
1031
- throw new Error("Could not get observable");
1032
- }
1033
- let viewPortHeight;
1034
- let scrollAreaSize;
1035
- let edgeTop;
1036
- let edgeBottom;
1037
- let isInTopScrollArea;
1038
- let isInBottomScrollArea;
1039
- let timer;
1040
- let scrollableDiv;
1041
- let relativeY;
1042
- this.globalDragSubscription = this.globalDrag$
1043
- .pipe(throttleTime(25), filter((event) => {
1044
- if (!event.target) {
1045
- return false;
1046
- }
1047
- scrollableDiv = getScrollParent(event.target);
1048
- viewPortHeight = scrollableDiv.clientHeight;
1049
- const viewPortWidth = scrollableDiv.clientWidth;
1050
- let relativeX;
1051
- if (window
1052
- .getComputedStyle(scrollableDiv)
1053
- .getPropertyValue("position")
1054
- .toLowerCase() === "fixed") {
1055
- relativeX = event.clientX;
1056
- relativeY = event.clientY;
1057
- }
1058
- else {
1059
- const boundingRect = scrollableDiv.getBoundingClientRect();
1060
- const scrollableDivAncestor = getScrollParent(scrollableDiv);
1061
- relativeX =
1062
- event.clientX -
1063
- (boundingRect.left + scrollableDivAncestor.scrollLeft);
1064
- relativeY =
1065
- event.clientY -
1066
- (boundingRect.top + scrollableDivAncestor.scrollTop);
1067
- }
1068
- if (relativeX < 0 ||
1069
- relativeX > viewPortWidth ||
1070
- relativeY < 0 ||
1071
- relativeY > viewPortHeight) {
1072
- //Outside of scrollable div
1073
- return false;
1074
- }
1075
- scrollAreaSize = Math.max(viewPortHeight * 0.1, 100);
1076
- edgeTop = scrollAreaSize;
1077
- edgeBottom = viewPortHeight - scrollAreaSize;
1078
- isInTopScrollArea = relativeY < edgeTop;
1079
- isInBottomScrollArea = relativeY > edgeBottom;
1080
- return isInTopScrollArea || isInBottomScrollArea;
1081
- }))
1082
- .subscribe(() => {
1083
- if (scrollableDiv === null) {
1084
- return;
1085
- }
1086
- const height = scrollableDiv.scrollHeight;
1087
- const maxScrollY = height - viewPortHeight;
1088
- const currentScrollY = scrollableDiv.scrollTop;
1089
- const canScrollUp = currentScrollY > 0;
1090
- const canScrollDown = currentScrollY < maxScrollY;
1091
- let nextScrollY;
1092
- const maxStep = 75;
1093
- if (isInTopScrollArea && canScrollUp) {
1094
- const intensity = (edgeTop - relativeY) / scrollAreaSize;
1095
- nextScrollY = currentScrollY - maxStep * intensity;
1096
- }
1097
- else if (isInBottomScrollArea && canScrollDown) {
1098
- const intensity = (relativeY - edgeBottom) / scrollAreaSize;
1099
- nextScrollY = currentScrollY + maxStep * intensity;
1100
- }
1101
- else {
1102
- return;
1103
- }
1104
- nextScrollY = Math.max(0, Math.min(maxScrollY, nextScrollY));
1105
- if (nextScrollY !== currentScrollY) {
1106
- scrollableDiv.scrollTo({ top: nextScrollY });
1107
- this.scrolling = true;
1108
- clearTimeout(timer);
1109
- timer = setTimeout(() => {
1110
- this.scrolling = false;
1111
- }, 100);
1112
- }
1113
- });
1114
- });
1115
- }
1116
- removeScrolling() {
1117
- if (this.globalDragSubscription !== undefined) {
1118
- this.globalDragSubscription.unsubscribe();
1119
- }
1120
- }
1121
- }
1122
- GlobalEventsService.ɵfac = function GlobalEventsService_Factory(t) { return new (t || GlobalEventsService)(i0.ɵɵinject(i0.NgZone)); };
1123
- GlobalEventsService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: GlobalEventsService, factory: GlobalEventsService.ɵfac });
1124
- (function () {
1125
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(GlobalEventsService, [{
1126
- type: Injectable
1127
- }], function () { return [{ type: i0.NgZone }]; }, null);
1128
- })();
203
+ class DragAndDrop {
204
+ constructor() {
205
+ this.dragAborted$ = new Subject();
206
+ }
207
+ dragStart(treeBranch, event) {
208
+ if (!this.draggingAllowed(treeBranch)) {
209
+ event.preventDefault();
210
+ return;
211
+ }
212
+ treeBranch.dispatch(new DragStartEvent(treeBranch));
213
+ this.setDragEffects(treeBranch, event);
214
+ this.watchForDragend(treeBranch, event);
215
+ // We have to do a setTimeout because DOM changes are not allowed during a
216
+ // dragstart event.
217
+ setTimeout(() => {
218
+ dragState.starting(treeBranch);
219
+ treeBranch.prune();
220
+ dragState.dragging();
221
+ });
222
+ }
223
+ drop(parent, index) {
224
+ const treeBranch = dragState.getDragData();
225
+ if (treeBranch === undefined) {
226
+ throw new TreeError("Cannot get dragged branch");
227
+ }
228
+ this.graftDraggedBranch(treeBranch, parent, index);
229
+ treeBranch.dispatch(new DropEvent(treeBranch, parent, index));
230
+ }
231
+ getDragImageOffsets(event, element) {
232
+ const bounds = element.getBoundingClientRect();
233
+ const xOffset = event.clientX - bounds.left;
234
+ const yOffset = event.clientY - bounds.top;
235
+ return [xOffset, yOffset];
236
+ }
237
+ setDragEffects(treeBranch, event) {
238
+ const dataTransfer = event.dataTransfer;
239
+ assert(dataTransfer instanceof DataTransfer);
240
+ const nativeElement = treeBranch.getNativeElement();
241
+ const [xOffset, yOffset] = this.getDragImageOffsets(event, nativeElement);
242
+ dataTransfer.setDragImage(nativeElement, xOffset, yOffset);
243
+ }
244
+ watchForDragend(treeBranch, event) {
245
+ var _a;
246
+ const oldParent = treeBranch.parent();
247
+ const oldIndex = treeBranch.index();
248
+ assert(oldParent !== undefined && oldIndex !== undefined);
249
+ (_a = event.target) === null || _a === void 0 ? void 0 : _a.addEventListener("dragend", (dragend) => {
250
+ if (dragState.state() !== DragStates.Dropped) {
251
+ //The drag ended but a drop never occurred, so put the dragged branch back where it started.
252
+ this.dragAborted$.next(dragend);
253
+ this.graftDraggedBranch(treeBranch, oldParent, oldIndex);
254
+ }
255
+ dragState.restart();
256
+ const newParent = treeBranch.parent();
257
+ assert(newParent !== undefined);
258
+ const newIndex = treeBranch.index();
259
+ assert(newIndex !== undefined);
260
+ treeBranch.dispatch(new DragEndEvent(treeBranch, {
261
+ oldParent,
262
+ oldIndex,
263
+ newParent,
264
+ newIndex
265
+ }));
266
+ }, { once: true });
267
+ }
268
+ draggingAllowed(treeBranch) {
269
+ var _a, _b, _c;
270
+ const allowDragging = (_c = (_b = (_a = config.getConfig(treeBranch.root())) === null || _a === void 0 ? void 0 : _a.dragAndDrop) === null || _b === void 0 ? void 0 : _b.allowDragging) !== null && _c !== void 0 ? _c : (() => true);
271
+ return allowDragging(treeBranch);
272
+ }
273
+ graftDraggedBranch(treeBranch, parent, index) {
274
+ treeBranch.graftTo(parent, index);
275
+ treeBranch.getNativeElement().style.display = "block";
276
+ dragState.dropped();
277
+ }
278
+ }
279
+ const dragAndDrop = new DragAndDrop();
1129
280
 
1130
- const _c0$1 = ["nodeHost"];
1131
- const _c1 = ["draggableDiv"];
1132
- const _c2 = ["nodeHostContainer"];
1133
- const _c3 = ["innerBranch"];
1134
- function LimbleTreeNodeComponent_drop_zone_0_Template(rf, ctx) {
1135
- if (rf & 1) {
1136
- i0.ɵɵelement(0, "drop-zone", 7);
1137
- }
1138
- if (rf & 2) {
1139
- const ctx_r0 = i0.ɵɵnextContext();
1140
- i0.ɵɵproperty("dropZone", ctx_r0.dropZoneAbove);
1141
- }
1142
- }
1143
- function LimbleTreeNodeComponent_ng_template_5_Template(rf, ctx) { }
1144
- function LimbleTreeNodeComponent_limble_tree_branch_7_Template(rf, ctx) {
1145
- if (rf & 1) {
1146
- i0.ɵɵelement(0, "limble-tree-branch", 8, 9);
1147
- }
1148
- if (rf & 2) {
1149
- const ctx_r5 = i0.ɵɵnextContext();
1150
- i0.ɵɵproperty("branch", ctx_r5.branch);
1151
- }
1152
- }
1153
- function LimbleTreeNodeComponent_drop_zone_8_Template(rf, ctx) {
1154
- if (rf & 1) {
1155
- i0.ɵɵelement(0, "drop-zone", 7);
1156
- }
1157
- if (rf & 2) {
1158
- const ctx_r6 = i0.ɵɵnextContext();
1159
- i0.ɵɵproperty("dropZone", ctx_r6.dropZoneBelow);
1160
- }
1161
- }
1162
- class LimbleTreeNodeComponent {
1163
- constructor(componentCreatorService, changeDetectorRef, dragStateService, dropZoneService, treeService, globalEventsService, ngZone, treeConstructionStatus) {
1164
- this.componentCreatorService = componentCreatorService;
1165
- this.changeDetectorRef = changeDetectorRef;
1166
- this.dragStateService = dragStateService;
1167
- this.dropZoneService = dropZoneService;
1168
- this.treeService = treeService;
1169
- this.globalEventsService = globalEventsService;
1170
- this.ngZone = ngZone;
1171
- this.treeConstructionStatus = treeConstructionStatus;
1172
- this.treeConstructionStatus.constructing();
1173
- if (this.treeService.treeOptions !== undefined &&
1174
- this.treeService.treeOptions.listMode !== true) {
1175
- this.renderInnerBranch = true;
1176
- }
1177
- else {
1178
- this.renderInnerBranch = false;
1179
- }
1180
- this.renderDropZoneBelow = false;
1181
- this.renderDropZoneAbove = false;
1182
- this.treeChangeSubscription = this.treeService.changes$
1183
- .pipe(
1184
- //The first one is the initial tree render, which we can ignore
1185
- skip(1))
1186
- .subscribe(() => {
1187
- this.treeChangeHandler();
1188
- });
1189
- }
1190
- treeChangeHandler() {
1191
- if (this.branch !== undefined &&
1192
- this.currentBranchCoordinates !== undefined &&
1193
- !arraysAreEqual(this.branch.getCoordinates(), this.currentBranchCoordinates)) {
1194
- this.updateDropZones();
1195
- }
1196
- }
1197
- ngOnInit() {
1198
- var _a, _b, _c;
1199
- if (((_a = this.treeService.treeOptions) === null || _a === void 0 ? void 0 : _a.allowDragging) === false) {
1200
- return;
1201
- }
1202
- const parent = (_b = this.branch) === null || _b === void 0 ? void 0 : _b.getParent();
1203
- if ((parent === null || parent === void 0 ? void 0 : parent.data) !== null) {
1204
- const parentData = parent === null || parent === void 0 ? void 0 : parent.data;
1205
- if (!isNestingAllowed(this.treeService.treeOptions, parentData)) {
1206
- this.renderInnerBranch = false;
1207
- return;
1208
- }
1209
- }
1210
- this.registerDropZones();
1211
- this.currentBranchCoordinates = (_c = this.branch) === null || _c === void 0 ? void 0 : _c.getCoordinates();
1212
- this.ngZone.runOutsideAngular(() => {
1213
- if (this.dropZoneAbove === undefined ||
1214
- this.dropZoneBelow === undefined) {
1215
- throw new Error("Zones not registered");
1216
- }
1217
- merge(this.dropZoneAbove.getCommChannel(), this.dropZoneBelow.getCommChannel())
1218
- .pipe(filter((message) => message === "checkRendered"))
1219
- .subscribe(() => {
1220
- if (this.dropZoneAbove === undefined ||
1221
- this.dropZoneBelow === undefined ||
1222
- this.branch === undefined) {
1223
- throw new Error("Zones not registered");
1224
- }
1225
- this.renderDropZoneAbove = this.dropZoneAbove.isRendered();
1226
- this.renderDropZoneBelow = this.dropZoneBelow.isRendered();
1227
- });
1228
- });
1229
- }
1230
- ngAfterViewInit() {
1231
- this.renderNode();
1232
- this.setDropZoneHosts();
1233
- this.checkForHandle();
1234
- this.treeConstructionStatus.doneConstructing();
1235
- this.changeDetectorRef.detectChanges();
1236
- }
1237
- ngOnDestroy() {
1238
- this.treeChangeSubscription.unsubscribe();
1239
- if (this.dropZoneAbove !== undefined) {
1240
- this.dropZoneService.removeDropZone(this.dropZoneAbove);
1241
- }
1242
- if (this.dropZoneBelow !== undefined) {
1243
- this.dropZoneService.removeDropZone(this.dropZoneBelow);
1244
- }
1245
- this.treeService.cleanupSignal$.next(true);
1246
- }
1247
- dragstartHandler(event) {
1248
- var _a;
1249
- event.stopPropagation();
1250
- if (event.dataTransfer === null ||
1251
- this.branch === undefined ||
1252
- this.parentHost === undefined) {
1253
- throw new Error("failed to run dragstartHandler");
1254
- }
1255
- const draggedElement = event.target;
1256
- if (((_a = draggedElement.parentElement) === null || _a === void 0 ? void 0 : _a.tagName) !== "LIMBLE-TREE-NODE") {
1257
- //Don't drag stuff that isn't part of the tree
1258
- event.preventDefault();
1259
- return;
1260
- }
1261
- event.dataTransfer.effectAllowed = "move";
1262
- this.dragStateService.dragging(this.branch, this.parentHost);
1263
- const treeElement = draggedElement.closest("limble-tree-root");
1264
- if (treeElement === null) {
1265
- throw new Error("could not get root of tree");
1266
- }
1267
- this.ngZone.runOutsideAngular(() => {
1268
- //We have to use a setTimeout due to a bug in chrome: https://stackoverflow.com/a/20733870/8796651
1269
- setTimeout(() => {
1270
- var _a, _b;
1271
- draggedElement.classList.add("dragging");
1272
- if (((_a = this.treeService.treeData) === null || _a === void 0 ? void 0 : _a.length) === 1 &&
1273
- ((_b = this.branch) === null || _b === void 0 ? void 0 : _b.getCoordinates().length) === 1) {
1274
- //We are dragging the only element in the tree, so we have to use the placeholder system
1275
- this.treeService.placeholder$.next(true);
1276
- }
1277
- });
1278
- //We use this weird subscription/timeout combo in order to avoid a strange bug where the dragleave event
1279
- //does not fire if the user drags out of the tree too quickly. This issue would make the drop zone
1280
- //remain in the UI, potentially causing drop zones to appear in multiple trees at a time. This subscription
1281
- //waits for the dragover event on the tree to fire before rendering any drop zones. If the dragover
1282
- //event does not fire within a half second, we know the mouse left the tree too quickly, and we won't
1283
- //render the drop zone at all.
1284
- const dragSubscription = fromEvent(treeElement, "dragover")
1285
- .pipe(first())
1286
- .subscribe((dragoverEvent) => {
1287
- dragoverEvent.stopPropagation();
1288
- if (this.branch === undefined) {
1289
- throw new Error("Could not show surrounding drop zones");
1290
- }
1291
- const parent = this.branch.getParent();
1292
- let parentData;
1293
- let parentNestingAllowed = true;
1294
- if ((parent === null || parent === void 0 ? void 0 : parent.data) !== null) {
1295
- parentData = parent === null || parent === void 0 ? void 0 : parent.data;
1296
- parentNestingAllowed = isNestingAllowed(this.treeService.treeOptions, parentData);
1297
- }
1298
- if (this.dropZoneAbove !== undefined && parentNestingAllowed) {
1299
- this.dropZoneService.showDropZoneFamily(this.dropZoneAbove, {
1300
- joinFamilies: true
1301
- });
1302
- }
1303
- });
1304
- setTimeout(() => {
1305
- if (!dragSubscription.closed) {
1306
- dragSubscription.unsubscribe();
1307
- }
1308
- }, 500);
1309
- });
1310
- }
1311
- dragendHandler(event) {
1312
- var _a, _b;
1313
- event === null || event === void 0 ? void 0 : event.stopPropagation();
1314
- if (this.draggableDiv === undefined) {
1315
- throw new Error("could not get draggable div");
1316
- }
1317
- this.draggableDiv.nativeElement.classList.remove("dragging");
1318
- if (this.dragStateService.getState() === "captured") {
1319
- if (this.treeService.captured === false) {
1320
- //Dropped in a different tree. Remove the one in this tree
1321
- if (this.branch === undefined) {
1322
- throw new Error("could not get branch in dragendHandler");
1323
- }
1324
- this.treeService.cleanupSignal$.next(true);
1325
- this.treeService.captured = false;
1326
- }
1327
- this.dragStateService.release();
1328
- }
1329
- else {
1330
- //Wasn't dropped into a valid tree, so reset for next drag and
1331
- //don't do anything else.
1332
- this.dragStateService.release();
1333
- this.dropZoneService.clearVisibleZones();
1334
- this.dropZoneService.restoreFamilies();
1335
- if (((_a = this.treeService.treeData) === null || _a === void 0 ? void 0 : _a.length) === 1 &&
1336
- ((_b = this.branch) === null || _b === void 0 ? void 0 : _b.getCoordinates().length) === 1) {
1337
- //We were dragging the only element in the tree, so we have to
1338
- //remove the placeholder that we added in the dragstart
1339
- this.treeService.placeholder$.next(false);
1340
- }
1341
- }
1342
- }
1343
- dragoverHandler(event) {
1344
- var _a, _b, _c;
1345
- if (this.globalEventsService.scrolling === true) {
1346
- return;
1347
- }
1348
- if (this.branch === undefined) {
1349
- throw new Error("Can't get current branch during dragover event");
1350
- }
1351
- const data = this.dragStateService.getData();
1352
- if (data === undefined) {
1353
- //They might be dragging something that isn't a node. Just ignore it.
1354
- return;
1355
- }
1356
- const sourceBranch = data.branch;
1357
- //If trying to drop on self, return.
1358
- if (sourceBranch === this.branch ||
1359
- this.branch.getAncestors().includes(sourceBranch)) {
1360
- return;
1361
- }
1362
- const target = event.currentTarget.closest(".node-host-container");
1363
- if (!(target instanceof HTMLElement)) {
1364
- throw new Error("Failed to find node host container while dragging");
1365
- }
1366
- let topLine;
1367
- let bottomLine;
1368
- if (((_a = this.innerBranch) === null || _a === void 0 ? void 0 : _a.renderDropZoneInside) === false) {
1369
- topLine = target.offsetHeight / 2 - 6;
1370
- bottomLine = topLine;
1371
- }
1372
- else {
1373
- topLine = target.offsetHeight / 3 - 3; //an imaginary line 1/3 of the way down from the top of the element;
1374
- bottomLine = topLine * 2; //an imaginary line 1/3 of the way up from the bottom of the element;
1375
- }
1376
- const parent = this.branch.getParent();
1377
- let parentData;
1378
- let parentNestingAllowed = true;
1379
- if ((parent === null || parent === void 0 ? void 0 : parent.data) !== null) {
1380
- parentData = parent === null || parent === void 0 ? void 0 : parent.data;
1381
- parentNestingAllowed = isNestingAllowed(this.treeService.treeOptions, parentData);
1382
- }
1383
- /** The y-coordinates of the mouse in relation to the node it is hovering over */
1384
- const offsetY = event.clientY - target.getBoundingClientRect().top;
1385
- const activeDropZone = this.dropZoneService.getActiveDropZone();
1386
- if (offsetY < topLine &&
1387
- this.dropZoneAbove !== undefined &&
1388
- parentNestingAllowed &&
1389
- (activeDropZone === null ||
1390
- !DropZone.dropZoneLocationsAreEqual(activeDropZone, this.dropZoneAbove))) {
1391
- const index = this.branch.getIndex();
1392
- if (index === undefined || index === null) {
1393
- throw new Error("can't get branch index");
1394
- }
1395
- this.dropZoneService.showDropZoneFamily(this.dropZoneAbove, {
1396
- activateLowestInsteadOfFounder: true
1397
- });
1398
- if (suddenTreeExit(event)) {
1399
- this.dropZoneService.clearVisibleZones();
1400
- }
1401
- }
1402
- else if (offsetY < bottomLine &&
1403
- offsetY > topLine &&
1404
- ((_b = this.innerBranch) === null || _b === void 0 ? void 0 : _b.renderDropZoneInside) === true &&
1405
- ((_c = this.innerBranch) === null || _c === void 0 ? void 0 : _c.dropZoneInside) !== undefined &&
1406
- (activeDropZone === null ||
1407
- !DropZone.dropZoneLocationsAreEqual(activeDropZone, this.innerBranch.dropZoneInside))) {
1408
- this.dropZoneService.showDropZoneFamily(this.innerBranch.dropZoneInside);
1409
- if (suddenTreeExit(event)) {
1410
- this.dropZoneService.clearVisibleZones();
1411
- }
1412
- }
1413
- else if (offsetY >= bottomLine &&
1414
- this.dropZoneBelow !== undefined &&
1415
- parentNestingAllowed &&
1416
- (activeDropZone === null ||
1417
- !DropZone.dropZoneLocationsAreEqual(activeDropZone, this.dropZoneBelow)) &&
1418
- this.branch.getChildren().length === 0) {
1419
- const index = this.branch.getIndex();
1420
- if (index === undefined || index === null) {
1421
- throw new Error("can't get branch index");
1422
- }
1423
- this.dropZoneService.showDropZoneFamily(this.dropZoneBelow);
1424
- if (suddenTreeExit(event)) {
1425
- this.dropZoneService.clearVisibleZones();
1426
- }
1427
- }
1428
- }
1429
- renderNode() {
1430
- var _a;
1431
- if (this.nodeHost === undefined || this.branch === undefined) {
1432
- throw new Error("Failed to render tree node");
1433
- }
1434
- let component = this.branch.data.component;
1435
- if (component === undefined) {
1436
- component = (_a = this.treeService.treeOptions) === null || _a === void 0 ? void 0 : _a.defaultComponent;
1437
- }
1438
- if (component === undefined) {
1439
- throw new Error("limbleTree requires a component to render");
1440
- }
1441
- const componentRef = this.componentCreatorService.appendComponent(component.class, this.nodeHost);
1442
- componentRef.instance.nodeData = this.branch.data;
1443
- for (const binding in component.bindings) {
1444
- componentRef.instance[binding] = component.bindings[binding];
1445
- }
1446
- }
1447
- registerDropZones() {
1448
- this.addDropZoneAbove();
1449
- this.addDropZoneBelow();
1450
- }
1451
- addDropZoneAbove() {
1452
- var _a;
1453
- if (this.branch === undefined) {
1454
- throw new Error("failed to register drop zone above");
1455
- }
1456
- const parent = this.branch.getParent();
1457
- const currentCoordinates = this.branch.getCoordinates();
1458
- const index = currentCoordinates[currentCoordinates.length - 1];
1459
- this.dropZoneAbove = new DropZone([...((_a = parent === null || parent === void 0 ? void 0 : parent.getCoordinates()) !== null && _a !== void 0 ? _a : [])], index);
1460
- this.dropZoneService.addDropZone(this.dropZoneAbove);
1461
- }
1462
- addDropZoneBelow() {
1463
- var _a;
1464
- if (this.branch === undefined) {
1465
- throw new Error("failed to register drop zone below");
1466
- }
1467
- const parent = this.branch.getParent();
1468
- const currentCoordinates = this.branch.getCoordinates();
1469
- const index = currentCoordinates[currentCoordinates.length - 1];
1470
- this.dropZoneBelow = new DropZone([...((_a = parent === null || parent === void 0 ? void 0 : parent.getCoordinates()) !== null && _a !== void 0 ? _a : [])], index + 1);
1471
- this.dropZoneService.addDropZone(this.dropZoneBelow);
1472
- }
1473
- updateDropZones() {
1474
- var _a;
1475
- this.currentBranchCoordinates = (_a = this.branch) === null || _a === void 0 ? void 0 : _a.getCoordinates();
1476
- this.updateDropZoneAbove();
1477
- this.updateDropZoneBelow();
1478
- this.updateDropZoneInside();
1479
- this.setDropZoneHosts();
1480
- }
1481
- updateDropZoneAbove() {
1482
- var _a;
1483
- if (this.branch === undefined || this.dropZoneAbove === undefined) {
1484
- throw new Error("failed to update drop zone above");
1485
- }
1486
- const parent = this.branch.getParent();
1487
- const currentCoordinates = this.branch.getCoordinates();
1488
- const index = currentCoordinates[currentCoordinates.length - 1];
1489
- const location = this.dropZoneAbove.getLocation();
1490
- location.setParentCoordinates([...((_a = parent === null || parent === void 0 ? void 0 : parent.getCoordinates()) !== null && _a !== void 0 ? _a : [])]);
1491
- location.setInsertIndex(index);
1492
- }
1493
- updateDropZoneBelow() {
1494
- var _a;
1495
- if (this.branch === undefined || this.dropZoneBelow === undefined) {
1496
- throw new Error("failed to update drop zone below");
1497
- }
1498
- const parent = this.branch.getParent();
1499
- const currentCoordinates = this.branch.getCoordinates();
1500
- const index = currentCoordinates[currentCoordinates.length - 1];
1501
- const location = this.dropZoneBelow.getLocation();
1502
- location.setParentCoordinates([...((_a = parent === null || parent === void 0 ? void 0 : parent.getCoordinates()) !== null && _a !== void 0 ? _a : [])]);
1503
- location.setInsertIndex(index + 1);
1504
- }
1505
- updateDropZoneInside() {
1506
- var _a;
1507
- if (((_a = this.innerBranch) === null || _a === void 0 ? void 0 : _a.dropZoneInside) === undefined) {
1508
- return;
1509
- }
1510
- if (this.branch === undefined) {
1511
- throw new Error("failed to update drop zone inside");
1512
- }
1513
- const location = this.innerBranch.dropZoneInside.getLocation();
1514
- location.setParentCoordinates([...this.branch.getCoordinates()]);
1515
- }
1516
- setDropZoneHosts() {
1517
- if (this.dropZoneAbove === undefined ||
1518
- this.dropZoneBelow === undefined) {
1519
- return;
1520
- }
1521
- this.dropZoneAbove.setHost(this.parentHost);
1522
- this.dropZoneBelow.setHost(this.parentHost);
1523
- }
1524
- checkForHandle() {
1525
- var _a;
1526
- if (this.nodeHostContainer === undefined ||
1527
- this.draggableDiv === undefined) {
1528
- return;
1529
- }
1530
- const nodeHostContainerElement = this.nodeHostContainer.nativeElement;
1531
- const handle = nodeHostContainerElement.querySelector(".limble-tree-handle");
1532
- const draggableDivElement = this.draggableDiv.nativeElement;
1533
- if (!isDraggingAllowed(this.treeService.treeOptions, (_a = this.branch) === null || _a === void 0 ? void 0 : _a.data)) {
1534
- draggableDivElement.setAttribute("draggable", "false");
1535
- }
1536
- else if (handle === null) {
1537
- draggableDivElement.setAttribute("draggable", "true");
1538
- }
1539
- else {
1540
- handle.addEventListener("mousedown", () => {
1541
- draggableDivElement.setAttribute("draggable", "true");
1542
- //For some reason mouseup doesn't fire after a drag, so we use this observable sequence instead.
1543
- const dragging = this.dragStateService.state$.pipe(filter((state) => state === "dragging"), first());
1544
- this.dragStateService.state$
1545
- .pipe(skipUntil(dragging), filter((state) => state === "idle"), first())
1546
- .subscribe(() => {
1547
- draggableDivElement.setAttribute("draggable", "false");
1548
- });
1549
- });
1550
- }
1551
- }
1552
- }
1553
- LimbleTreeNodeComponent.ɵfac = function LimbleTreeNodeComponent_Factory(t) { return new (t || LimbleTreeNodeComponent)(i0.ɵɵdirectiveInject(ComponentCreatorService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(DragStateService), i0.ɵɵdirectiveInject(DropZoneService), i0.ɵɵdirectiveInject(TreeService), i0.ɵɵdirectiveInject(GlobalEventsService), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(TreeConstructionStatus)); };
1554
- LimbleTreeNodeComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LimbleTreeNodeComponent, selectors: [["limble-tree-node"]], viewQuery: function LimbleTreeNodeComponent_Query(rf, ctx) {
1555
- if (rf & 1) {
1556
- i0.ɵɵviewQuery(_c0$1, 5, ViewContainerRef);
1557
- i0.ɵɵviewQuery(_c1, 5, ElementRef);
1558
- i0.ɵɵviewQuery(_c2, 5, ElementRef);
1559
- i0.ɵɵviewQuery(_c3, 5, LimbleTreeBranchComponent);
1560
- }
1561
- if (rf & 2) {
1562
- let _t;
1563
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.nodeHost = _t.first);
1564
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.draggableDiv = _t.first);
1565
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.nodeHostContainer = _t.first);
1566
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.innerBranch = _t.first);
1567
- }
1568
- }, inputs: { branch: "branch", parentHost: "parentHost" }, decls: 9, vars: 4, consts: [[3, "dropZone", 4, "ngIf"], [1, "limble-parent-container", 3, "dragstart", "dragend"], ["draggableDiv", ""], [1, "node-host-container", 3, "dragoverEventThrottle", "dragoverNoChangeDetect"], ["nodeHostContainer", ""], ["nodeHost", ""], [3, "branch", 4, "ngIf"], [3, "dropZone"], [3, "branch"], ["innerBranch", ""]], template: function LimbleTreeNodeComponent_Template(rf, ctx) {
1569
- if (rf & 1) {
1570
- i0.ɵɵtemplate(0, LimbleTreeNodeComponent_drop_zone_0_Template, 1, 1, "drop-zone", 0);
1571
- i0.ɵɵelementStart(1, "div", 1, 2);
1572
- i0.ɵɵlistener("dragstart", function LimbleTreeNodeComponent_Template_div_dragstart_1_listener($event) { return ctx.dragstartHandler($event); })("dragend", function LimbleTreeNodeComponent_Template_div_dragend_1_listener($event) { return ctx.dragendHandler($event); });
1573
- i0.ɵɵelementStart(3, "div", 3, 4);
1574
- i0.ɵɵlistener("dragoverNoChangeDetect", function LimbleTreeNodeComponent_Template_div_dragoverNoChangeDetect_3_listener($event) { return ctx.dragoverHandler($event); });
1575
- i0.ɵɵtemplate(5, LimbleTreeNodeComponent_ng_template_5_Template, 0, 0, "ng-template", null, 5, i0.ɵɵtemplateRefExtractor);
1576
- i0.ɵɵelementEnd();
1577
- i0.ɵɵtemplate(7, LimbleTreeNodeComponent_limble_tree_branch_7_Template, 2, 1, "limble-tree-branch", 6);
1578
- i0.ɵɵelementEnd();
1579
- i0.ɵɵtemplate(8, LimbleTreeNodeComponent_drop_zone_8_Template, 1, 1, "drop-zone", 0);
1580
- }
1581
- if (rf & 2) {
1582
- i0.ɵɵproperty("ngIf", ctx.renderDropZoneAbove === true);
1583
- i0.ɵɵadvance(3);
1584
- i0.ɵɵproperty("dragoverEventThrottle", 10);
1585
- i0.ɵɵadvance(4);
1586
- i0.ɵɵproperty("ngIf", ctx.branch !== undefined && ctx.renderInnerBranch === true);
1587
- i0.ɵɵadvance(1);
1588
- i0.ɵɵproperty("ngIf", ctx.renderDropZoneBelow === true);
1589
- }
1590
- }, styles: [".dragging[_ngcontent-%COMP%]{position:absolute;transition:transform .01s;transform:translate(-9999px)}"] });
1591
- (function () {
1592
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreeNodeComponent, [{
1593
- type: Component,
1594
- args: [{ selector: "limble-tree-node", template: "<drop-zone\n *ngIf=\"renderDropZoneAbove === true\"\n [dropZone]=\"dropZoneAbove\"\n></drop-zone>\n<div\n (dragstart)=\"dragstartHandler($event)\"\n (dragend)=\"dragendHandler($event)\"\n class=\"limble-parent-container\"\n #draggableDiv\n>\n <div\n class=\"node-host-container\"\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n [dragoverEventThrottle]=\"10\"\n #nodeHostContainer\n >\n <ng-template #nodeHost></ng-template>\n </div>\n <limble-tree-branch\n *ngIf=\"branch !== undefined && renderInnerBranch === true\"\n [branch]=\"branch\"\n #innerBranch\n ></limble-tree-branch>\n</div>\n<drop-zone\n *ngIf=\"renderDropZoneBelow === true\"\n [dropZone]=\"dropZoneBelow\"\n></drop-zone>\n", styles: [".dragging{position:absolute;transition:transform .01s;transform:translate(-9999px)}\n"] }]
1595
- }], function () { return [{ type: ComponentCreatorService }, { type: i0.ChangeDetectorRef }, { type: DragStateService }, { type: DropZoneService }, { type: TreeService }, { type: GlobalEventsService }, { type: i0.NgZone }, { type: TreeConstructionStatus }]; }, { branch: [{
1596
- type: Input
1597
- }], nodeHost: [{
1598
- type: ViewChild,
1599
- args: ["nodeHost", { read: ViewContainerRef }]
1600
- }], draggableDiv: [{
1601
- type: ViewChild,
1602
- args: ["draggableDiv", { read: ElementRef }]
1603
- }], nodeHostContainer: [{
1604
- type: ViewChild,
1605
- args: ["nodeHostContainer", { read: ElementRef }]
1606
- }], parentHost: [{
1607
- type: Input
1608
- }], innerBranch: [{
1609
- type: ViewChild,
1610
- args: ["innerBranch", { read: LimbleTreeBranchComponent }]
1611
- }] });
1612
- })();
281
+ class DragoverNoChangeDetectDirective {
282
+ constructor(ngZone, el) {
283
+ this.ngZone = ngZone;
284
+ this.el = el;
285
+ this.dragoverNoChangeDetect = new EventEmitter();
286
+ this.dragoverEventThrottle = 25;
287
+ }
288
+ ngOnInit() {
289
+ this.ngZone.runOutsideAngular(() => {
290
+ this.eventSubscription = fromEvent(this.el.nativeElement, "dragover")
291
+ .pipe(throttleTime(this.dragoverEventThrottle))
292
+ .subscribe(($event) => {
293
+ this.dragoverNoChangeDetect.emit($event);
294
+ });
295
+ });
296
+ }
297
+ ngOnDestroy() {
298
+ if (this.eventSubscription !== undefined) {
299
+ this.eventSubscription.unsubscribe();
300
+ }
301
+ }
302
+ }
303
+ DragoverNoChangeDetectDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DragoverNoChangeDetectDirective, deps: [{ token: i0.NgZone }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
304
+ DragoverNoChangeDetectDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DragoverNoChangeDetectDirective, isStandalone: true, selector: "[dragoverNoChangeDetect]", inputs: { dragoverEventThrottle: "dragoverEventThrottle" }, outputs: { dragoverNoChangeDetect: "dragoverNoChangeDetect" }, ngImport: i0 });
305
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DragoverNoChangeDetectDirective, decorators: [{
306
+ type: Directive,
307
+ args: [{
308
+ standalone: true,
309
+ selector: "[dragoverNoChangeDetect]"
310
+ }]
311
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { dragoverEventThrottle: [{
312
+ type: Input
313
+ }], dragoverNoChangeDetect: [{
314
+ type: Output
315
+ }] } });
1613
316
 
1614
- /** The default value for the `indent` option */
1615
- const INDENT = 45;
1616
- class TreeService {
1617
- constructor(componentCreatorService, dropZoneService, dragStateService, treeConstructionStatus) {
1618
- this.componentCreatorService = componentCreatorService;
1619
- this.dropZoneService = dropZoneService;
1620
- this.dragStateService = dragStateService;
1621
- this.treeConstructionStatus = treeConstructionStatus;
1622
- this.changes$ = new Subject();
1623
- this.drops$ = new Subject();
1624
- this.treeModel = new Branch(null);
1625
- this.placeholder = false;
1626
- this.captured = false;
1627
- this.cleanupSignal$ = new Subject();
1628
- let rebuild = false;
1629
- let treeIsStable = false;
1630
- const treeIsStable$ = this.treeConstructionStatus.stable$.pipe(tap((value) => {
1631
- treeIsStable = value;
1632
- }), filter((value) => value === true));
1633
- this.cleanupSignal$
1634
- .pipe(tap((value) => {
1635
- rebuild = value;
1636
- }), debounce(() => {
1637
- if (treeIsStable === true) {
1638
- //If tree is stable, continue right away
1639
- return EMPTY;
1640
- }
1641
- //If tree is not stable, wait for it to become so.
1642
- return treeIsStable$;
1643
- }),
1644
- //We use this timed debounce to throttle chained destruction of components
1645
- debounceTime(5))
1646
- .subscribe(() => {
1647
- this.cleanup(rebuild);
1648
- rebuild = false;
1649
- });
1650
- this.placeholder$ = new BehaviorSubject(false);
1651
- this.placeholder$.subscribe((value) => {
1652
- this.placeholder = value;
1653
- });
1654
- }
1655
- drop(source, targetCoordinates) {
1656
- var _a;
1657
- //prep
1658
- const sourceParent = source.getParent();
1659
- if (sourceParent === null) {
1660
- throw new Error("can't drop root of tree");
1661
- }
1662
- const sourceIndex = source.getIndex();
1663
- if (sourceIndex === undefined || sourceIndex === null) {
1664
- throw new Error("Cannot move the hidden root node");
1665
- }
1666
- let targetParentCoordinates;
1667
- let newIndex;
1668
- if (this.placeholder === true) {
1669
- targetParentCoordinates = [];
1670
- newIndex = 0;
1671
- }
1672
- else {
1673
- targetParentCoordinates = [...targetCoordinates];
1674
- newIndex = targetParentCoordinates.pop();
1675
- }
1676
- if (newIndex === undefined) {
1677
- throw new Error("target coordinates are empty");
1678
- }
1679
- const targetParent = this.treeModel.getDescendant(targetParentCoordinates);
1680
- if (targetParent === undefined) {
1681
- throw new Error("could not get to target");
1682
- }
1683
- const target = this.dropZoneService.getDropZone(targetCoordinates);
1684
- const targetIndex = target === null || target === void 0 ? void 0 : target.getLocation().insertIndex;
1685
- const targetHost = target === null || target === void 0 ? void 0 : target.getHost();
1686
- const sourceHost = (_a = this.dragStateService.getData()) === null || _a === void 0 ? void 0 : _a.parentContainer;
1687
- if (this.placeholder === true) {
1688
- this.placeholder$.next(false);
1689
- }
1690
- //Change the treeModel
1691
- targetParent.insertChild(source, newIndex);
1692
- //Prepare to update the view
1693
- if (targetHost === undefined ||
1694
- sourceHost === undefined ||
1695
- targetIndex === undefined) {
1696
- //Hitting this means there is a bug, but not a fatal one.
1697
- //Just render the whole tree again.
1698
- console.warn("Could not perform a precise update. Re-rendering the entire tree instead");
1699
- this.render();
1700
- this.changes$.next(null);
1701
- return;
1702
- }
1703
- //Update the view
1704
- const nodesInSource = sourceHost.length;
1705
- const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, targetHost, newIndex);
1706
- componentRef.instance.branch = source;
1707
- componentRef.instance.parentHost = targetHost;
1708
- if (targetIndex < sourceIndex &&
1709
- sourceHost.length > nodesInSource &&
1710
- arraysAreEqual(sourceParent.getCoordinates(), targetParentCoordinates)) {
1711
- sourceHost.remove(sourceIndex + 1);
1712
- }
1713
- else {
1714
- sourceHost.remove(sourceIndex);
1715
- }
1716
- //Update the tree data
1717
- this.rebuildTreeData();
1718
- //Publish drop data
1719
- this.drops$.next({
1720
- target: source.data,
1721
- oldParent: sourceParent.data,
1722
- oldIndex: sourceIndex,
1723
- newParent: targetParent.data,
1724
- newIndex: newIndex
1725
- });
1726
- this.cleanupSignal$.next(false);
1727
- }
1728
- /** Initializes the service and renders the tree.
1729
- * @param host - The ViewContainerRef into which the tree will be rendered.
1730
- * @param data - The data array that was passed in to LimbleTreeRoot, which is
1731
- * the users' representation of the tree
1732
- * @param options - The options object that was passed in to LimbleTreeRoot
1733
- */
1734
- init(host, data, options, itemsPerPage, page) {
1735
- this.host = host;
1736
- this.originalData = data;
1737
- this.treeOptions = this.processOptions(options, itemsPerPage, page);
1738
- if (this.treeOptions.listMode === true) {
1739
- let start = this.treeOptions.itemsPerPage * (this.treeOptions.page - 1);
1740
- if (isNaN(start)) {
1741
- //This catches the case where itemsPerPage was not passed by the user,
1742
- //causing `start` to equal infinity*0, which is NaN.
1743
- start = 0;
1744
- }
1745
- const end = start + this.treeOptions.itemsPerPage;
1746
- this.treeData = this.originalData.slice(start, end);
1747
- }
1748
- else {
1749
- this.treeData = [...this.originalData];
1750
- }
1751
- this.render();
1752
- }
1753
- cleanup(rebuild = false) {
1754
- var _a;
1755
- if (rebuild) {
1756
- this.rebuildTreeData();
1757
- }
1758
- if (((_a = this.treeData) === null || _a === void 0 ? void 0 : _a.length) === 0) {
1759
- //We do a full render here because it isn't actually any slower
1760
- //when there are no nodes, and it is a little more straightforward
1761
- this.render();
1762
- }
1763
- else {
1764
- this.changes$.next(null);
1765
- this.dropZoneService.update();
1766
- }
1767
- }
1768
- /** Renders the entire tree from root to leaves */
1769
- render() {
1770
- if (this.host === undefined ||
1771
- this.treeData === undefined ||
1772
- this.treeOptions === undefined) {
1773
- throw new Error("TreeModel not initialized");
1774
- }
1775
- this.treeConstructionStatus.ready(false);
1776
- this.host.clear();
1777
- this.dropZoneService.restart();
1778
- this.placeholder$.next(false);
1779
- this.treeModel = new Branch(null);
1780
- if (this.treeData.length === 0) {
1781
- //Tree is empty, but we have to to have something there so other trees' items can be dropped into it
1782
- this.placeholder$.next(true);
1783
- }
1784
- else {
1785
- for (const node of this.treeData) {
1786
- const branch = new Branch(node);
1787
- this.treeModel.appendChild(branch);
1788
- }
1789
- for (const branch of this.treeModel.getChildren()) {
1790
- const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, this.host);
1791
- componentRef.instance.branch = branch;
1792
- componentRef.instance.parentHost = this.host;
1793
- //The LimbleTreeNodeComponent will (indirectly) call the `renderBranch` method of this service to render
1794
- //its own children
1795
- }
1796
- }
1797
- this.treeConstructionStatus.ready(true);
1798
- this.changes$.next(null);
1799
- this.dropZoneService.init(this.treeModel, this.treeOptions);
1800
- }
1801
- /** Renders a branch of the tree and all of its descendants */
1802
- renderBranch(host, branch) {
1803
- var _a, _b;
1804
- if (this.treeModel === undefined) {
1805
- throw new Error("TreeModel not initialized");
1806
- }
1807
- host.clear();
1808
- branch.clearChildren();
1809
- for (const node of (_b = (_a = branch.data) === null || _a === void 0 ? void 0 : _a.nodes) !== null && _b !== void 0 ? _b : []) {
1810
- const newBranch = new Branch(node);
1811
- branch.appendChild(newBranch);
1812
- const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, host);
1813
- componentRef.instance.branch = newBranch;
1814
- componentRef.instance.parentHost = host;
1815
- //The LimbleTreeNodeComponent will (indirectly) call the `renderBranch` method of this service to render
1816
- //its own children
1817
- }
1818
- }
1819
- processOptions(options = {}, itemsPerPage = Infinity, page = 1) {
1820
- var _a, _b, _c, _d, _e;
1821
- if (options.listMode === true &&
1822
- options.allowNesting !== undefined &&
1823
- options.allowNesting !== false) {
1824
- console.warn("The value of `allowNesting` will be ignored; it must be false when `listMode` is true");
1825
- }
1826
- const result = {
1827
- defaultComponent: options.defaultComponent,
1828
- indent: (_a = options.indent) !== null && _a !== void 0 ? _a : INDENT,
1829
- allowNesting: options.listMode !== true && ((_b = options.allowNesting) !== null && _b !== void 0 ? _b : true),
1830
- allowDragging: (_c = options.allowDragging) !== null && _c !== void 0 ? _c : true,
1831
- allowDrop: (_d = options.allowDrop) !== null && _d !== void 0 ? _d : (() => true),
1832
- listMode: (_e = options.listMode) !== null && _e !== void 0 ? _e : false,
1833
- itemsPerPage: options.listMode ? itemsPerPage : undefined,
1834
- page: options.listMode ? page : undefined
1835
- };
1836
- return result;
1837
- }
1838
- rebuildTreeData() {
1839
- if (this.originalData === undefined ||
1840
- this.treeData === undefined ||
1841
- this.treeOptions === undefined ||
1842
- this.host === undefined) {
1843
- throw new Error("Tree data not initialized");
1844
- }
1845
- this.treeData = [];
1846
- for (const branch of this.treeModel.getChildren()) {
1847
- this.treeData.push(this.rebuildBranch(branch));
1848
- }
1849
- if (this.treeOptions.listMode === true &&
1850
- this.treeOptions.itemsPerPage < Infinity) {
1851
- const itemsPerPage = this.treeOptions.itemsPerPage;
1852
- const start = itemsPerPage * (this.treeOptions.page - 1);
1853
- this.originalData.splice(start, itemsPerPage, ...this.treeData);
1854
- if (this.treeData.length !== itemsPerPage) {
1855
- let action = false;
1856
- if (this.treeData.length < itemsPerPage &&
1857
- start + itemsPerPage <= this.originalData.length) {
1858
- //The current page does not have enough nodes. Add some to the view from the next page.
1859
- const count = itemsPerPage - this.treeData.length;
1860
- for (let index = itemsPerPage - 1; index < itemsPerPage + count - 1; index++) {
1861
- const branch = new Branch(this.originalData[start + index]);
1862
- this.treeModel.appendChild(branch);
1863
- const componentRef = this.componentCreatorService.appendComponent(LimbleTreeNodeComponent, this.host);
1864
- componentRef.instance.branch = branch;
1865
- componentRef.instance.parentHost = this.host;
1866
- }
1867
- action = true;
1868
- }
1869
- else if (this.treeData.length > itemsPerPage) {
1870
- //The current page has too many nodes. Remove some of them from the view.
1871
- const count = this.treeData.length - itemsPerPage;
1872
- for (let index = itemsPerPage + count - 1; index >= itemsPerPage; index--) {
1873
- this.treeModel.removeChild(index);
1874
- this.host.remove(index);
1875
- }
1876
- action = true;
1877
- }
1878
- if (action === true) {
1879
- const end = start + itemsPerPage;
1880
- this.treeData = this.originalData.slice(start, end);
1881
- }
1882
- }
1883
- }
1884
- else {
1885
- this.originalData.length = 0;
1886
- this.originalData.push(...this.treeData);
1887
- }
1888
- }
1889
- rebuildBranch(branch) {
1890
- const temp = branch.data;
1891
- temp.nodes = [];
1892
- for (const child of branch.getChildren()) {
1893
- temp.nodes.push(this.rebuildBranch(child));
1894
- }
1895
- return temp;
1896
- }
1897
- }
1898
- TreeService.ɵfac = function TreeService_Factory(t) { return new (t || TreeService)(i0.ɵɵinject(ComponentCreatorService), i0.ɵɵinject(DropZoneService), i0.ɵɵinject(DragStateService), i0.ɵɵinject(TreeConstructionStatus)); };
1899
- TreeService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: TreeService, factory: TreeService.ɵfac });
1900
- (function () {
1901
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TreeService, [{
1902
- type: Injectable
1903
- }], function () { return [{ type: ComponentCreatorService }, { type: DropZoneService }, { type: DragStateService }, { type: TreeConstructionStatus }]; }, null);
1904
- })();
317
+ class DropzoneComponent {
318
+ constructor() {
319
+ this.dropped = new EventEmitter();
320
+ this.active = false;
321
+ }
322
+ dragenterHandler() {
323
+ this.active = true;
324
+ }
325
+ dragleaveHandler() {
326
+ this.active = false;
327
+ }
328
+ dragoverHandler(event) {
329
+ event.preventDefault();
330
+ event.dataTransfer.dropEffect = "move";
331
+ }
332
+ dropHandler(event) {
333
+ this.dropped.emit(event);
334
+ }
335
+ }
336
+ DropzoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
337
+ DropzoneComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: DropzoneComponent, isStandalone: true, selector: "dropzone", inputs: { placement: "placement" }, outputs: { dropped: "dropped" }, ngImport: i0, template: "<div\n class=\"dropzone\"\n [ngClass]=\"{ active: active }\"\n (dragenter)=\"dragenterHandler()\"\n (dragleave)=\"dragleaveHandler()\"\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n (drop)=\"dropHandler($event)\"\n></div>\n", styles: [".dropzone{border-radius:8px;border:1px dashed #727374;background-color:#ededed;height:20px;margin:8px 0;transition:height .2s ease-out;animation:animation .2s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:48px}@keyframes animation{0%{height:0px;opacity:0}to{height:20px;opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: DragoverNoChangeDetectDirective, selector: "[dragoverNoChangeDetect]", inputs: ["dragoverEventThrottle"], outputs: ["dragoverNoChangeDetect"] }] });
338
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, decorators: [{
339
+ type: Component,
340
+ args: [{ standalone: true, selector: "dropzone", imports: [CommonModule, DragoverNoChangeDetectDirective], template: "<div\n class=\"dropzone\"\n [ngClass]=\"{ active: active }\"\n (dragenter)=\"dragenterHandler()\"\n (dragleave)=\"dragleaveHandler()\"\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n (drop)=\"dropHandler($event)\"\n></div>\n", styles: [".dropzone{border-radius:8px;border:1px dashed #727374;background-color:#ededed;height:20px;margin:8px 0;transition:height .2s ease-out;animation:animation .2s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:48px}@keyframes animation{0%{height:0px;opacity:0}to{height:20px;opacity:1}}\n"] }]
341
+ }], propDecorators: { placement: [{
342
+ type: Input
343
+ }], dropped: [{
344
+ type: Output
345
+ }] } });
1905
346
 
1906
- class DragoverNoChangeDetectDirective {
1907
- constructor(ngZone, el) {
1908
- this.ngZone = ngZone;
1909
- this.el = el;
1910
- this.dragoverNoChangeDetect = new EventEmitter();
1911
- this.dragoverEventThrottle = 25;
1912
- }
1913
- ngOnInit() {
1914
- this.ngZone.runOutsideAngular(() => {
1915
- this.eventSubscription = fromEvent(this.el.nativeElement, "dragover")
1916
- .pipe(throttleTime(this.dragoverEventThrottle))
1917
- .subscribe(($event) => {
1918
- this.dragoverNoChangeDetect.emit($event);
1919
- });
1920
- });
1921
- }
1922
- ngOnDestroy() {
1923
- if (this.eventSubscription !== undefined) {
1924
- this.eventSubscription.unsubscribe();
1925
- }
1926
- }
1927
- }
1928
- DragoverNoChangeDetectDirective.ɵfac = function DragoverNoChangeDetectDirective_Factory(t) { return new (t || DragoverNoChangeDetectDirective)(i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i0.ElementRef)); };
1929
- DragoverNoChangeDetectDirective.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: DragoverNoChangeDetectDirective, selectors: [["", "dragoverNoChangeDetect", ""]], inputs: { dragoverEventThrottle: "dragoverEventThrottle" }, outputs: { dragoverNoChangeDetect: "dragoverNoChangeDetect" } });
1930
- (function () {
1931
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DragoverNoChangeDetectDirective, [{
1932
- type: Directive,
1933
- args: [{
1934
- selector: "[dragoverNoChangeDetect]"
1935
- }]
1936
- }], function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, { dragoverEventThrottle: [{
1937
- type: Input
1938
- }], dragoverNoChangeDetect: [{
1939
- type: Output
1940
- }] });
1941
- })();
347
+ class BranchComponent {
348
+ constructor(appRef) {
349
+ this.appRef = appRef;
350
+ this.branchesContainer = undefined;
351
+ this.contentContainer = undefined;
352
+ this.dropzones = undefined;
353
+ this.contentCreated = new EventEmitter();
354
+ this.showDropzones = new EventEmitter();
355
+ this.dropped = new EventEmitter();
356
+ this.showInnerDropzone = false;
357
+ this.showLateralDropzone = false;
358
+ }
359
+ ngAfterViewInit() {
360
+ assert(this.contentContainer !== undefined);
361
+ assert(this.contentToHost !== undefined);
362
+ this.hostedContent = this.contentContainer.createComponent(this.contentToHost);
363
+ this.contentCreated.emit(this.hostedContent.instance);
364
+ assert(this.dropzones !== undefined);
365
+ const inner = this.dropzones.get(0);
366
+ const lateral = this.dropzones.get(1);
367
+ assert(inner !== undefined && lateral !== undefined);
368
+ merge(inner.dropped.pipe(map(() => "inner")), lateral.dropped.pipe(map(() => "lateral"))).subscribe(this.dropped);
369
+ this.hostedContent.changeDetectorRef.detectChanges();
370
+ }
371
+ getHostedContent() {
372
+ return this.hostedContent;
373
+ }
374
+ triggerChangeDetection() {
375
+ if (!NgZone.isInAngularZone()) {
376
+ this.appRef.tick();
377
+ }
378
+ }
379
+ dragoverHandler(event) {
380
+ const elementHeight = event.currentTarget.getBoundingClientRect().height;
381
+ if (event.offsetY < elementHeight / 2) {
382
+ this.showDropzones.emit("upper");
383
+ }
384
+ else {
385
+ this.showDropzones.emit("lower");
386
+ }
387
+ }
388
+ ngOnDestroy() {
389
+ //I'm not 100% sure why, but we have to remove any reference to the
390
+ //componentRef otherwise Angular will never release it for garbage
391
+ //collection.
392
+ this.hostedContent = undefined;
393
+ }
394
+ }
395
+ BranchComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, deps: [{ token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Component });
396
+ BranchComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: BranchComponent, isStandalone: true, selector: "branch", inputs: { contentToHost: "contentToHost" }, outputs: { contentCreated: "contentCreated", showDropzones: "showDropzones", dropped: "dropped" }, viewQueries: [{ propertyName: "branchesContainer", first: true, predicate: ["branchesContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "contentContainer", first: true, predicate: ["contentContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dropzones", predicate: DropzoneComponent, descendants: true }], ngImport: i0, template: "<div class=\"content\" (dragoverNoChangeDetect)=\"dragoverHandler($event)\">\n <div #contentContainer></div>\n</div>\n<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n<dropzone placement=\"lateral\" [hidden]=\"!showLateralDropzone\"></dropzone>\n", styles: [".branches-container{margin-left:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DropzoneComponent, selector: "dropzone", inputs: ["placement"], outputs: ["dropped"] }, { kind: "directive", type: DragoverNoChangeDetectDirective, selector: "[dragoverNoChangeDetect]", inputs: ["dragoverEventThrottle"], outputs: ["dragoverNoChangeDetect"] }] });
397
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, decorators: [{
398
+ type: Component,
399
+ args: [{ standalone: true, selector: "branch", imports: [CommonModule, DropzoneComponent, DragoverNoChangeDetectDirective], template: "<div class=\"content\" (dragoverNoChangeDetect)=\"dragoverHandler($event)\">\n <div #contentContainer></div>\n</div>\n<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n<dropzone placement=\"lateral\" [hidden]=\"!showLateralDropzone\"></dropzone>\n", styles: [".branches-container{margin-left:16px}\n"] }]
400
+ }], ctorParameters: function () { return [{ type: i0.ApplicationRef }]; }, propDecorators: { branchesContainer: [{
401
+ type: ViewChild,
402
+ args: ["branchesContainer", { read: ViewContainerRef }]
403
+ }], contentContainer: [{
404
+ type: ViewChild,
405
+ args: ["contentContainer", { read: ViewContainerRef }]
406
+ }], dropzones: [{
407
+ type: ViewChildren,
408
+ args: [DropzoneComponent]
409
+ }], contentToHost: [{
410
+ type: Input
411
+ }], contentCreated: [{
412
+ type: Output
413
+ }], showDropzones: [{
414
+ type: Output
415
+ }], dropped: [{
416
+ type: Output
417
+ }] } });
1942
418
 
1943
- class LimbleTreePlaceholderComponent {
1944
- constructor(dropZoneService, changeDetectorRef, treeService, treeConstructionStatus) {
1945
- this.dropZoneService = dropZoneService;
1946
- this.changeDetectorRef = changeDetectorRef;
1947
- this.treeService = treeService;
1948
- this.treeConstructionStatus = treeConstructionStatus;
1949
- this.treeConstructionStatus.constructing();
1950
- //This logic is very similar to what the lifecycle hooks of this component do.
1951
- //We use this subscription because sometimes we can't wait for the lifecycle hooks:
1952
- //Specifically, the drop zone registration and deregistration sometimes can't happen
1953
- //asynchronously without causing bugs. So we handle it synchronously here as well.
1954
- this.placeholderSubscription = this.treeService.placeholder$.subscribe((value) => {
1955
- if (this.dropZone === undefined) {
1956
- return;
1957
- }
1958
- this.dropZoneService.removeDropZone(this.dropZone);
1959
- if (value === true) {
1960
- this.dropZoneService.addDropZone(this.dropZone);
1961
- this.dropZone.setHost(this.treeService.host);
1962
- }
1963
- });
1964
- }
1965
- ngOnInit() {
1966
- this.dropZone = new DropZone([], 0);
1967
- this.dropZoneService.addDropZone(this.dropZone);
1968
- }
1969
- ngAfterViewInit() {
1970
- if (this.dropZone === undefined) {
1971
- throw new Error("placeholder drop zone is not defined");
1972
- }
1973
- this.dropZone.setHost(this.treeService.host);
1974
- this.treeConstructionStatus.doneConstructing();
1975
- this.changeDetectorRef.detectChanges();
1976
- }
1977
- dragoverHandler() {
1978
- if (this.dropZone === undefined) {
1979
- return;
1980
- }
1981
- this.dropZoneService.showDropZoneFamily(this.dropZone);
1982
- }
1983
- ngOnDestroy() {
1984
- this.placeholderSubscription.unsubscribe();
1985
- if (this.dropZone === undefined) {
1986
- throw new Error("could not remove placeholder drop zone");
1987
- }
1988
- this.dropZoneService.removeDropZone(this.dropZone);
1989
- }
1990
- }
1991
- LimbleTreePlaceholderComponent.ɵfac = function LimbleTreePlaceholderComponent_Factory(t) { return new (t || LimbleTreePlaceholderComponent)(i0.ɵɵdirectiveInject(DropZoneService), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(TreeService), i0.ɵɵdirectiveInject(TreeConstructionStatus)); };
1992
- LimbleTreePlaceholderComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LimbleTreePlaceholderComponent, selectors: [["limble-tree-placeholder"]], decls: 2, vars: 1, consts: [[3, "dropZone"], [1, "placeholder", 3, "dragoverNoChangeDetect"]], template: function LimbleTreePlaceholderComponent_Template(rf, ctx) {
1993
- if (rf & 1) {
1994
- i0.ɵɵelement(0, "drop-zone", 0);
1995
- i0.ɵɵelementStart(1, "div", 1);
1996
- i0.ɵɵlistener("dragoverNoChangeDetect", function LimbleTreePlaceholderComponent_Template_div_dragoverNoChangeDetect_1_listener() { return ctx.dragoverHandler(); });
1997
- i0.ɵɵelementEnd();
1998
- }
1999
- if (rf & 2) {
2000
- i0.ɵɵproperty("dropZone", ctx.dropZone);
2001
- }
2002
- }, dependencies: [DropZoneComponent, DragoverNoChangeDetectDirective], styles: [".placeholder[_ngcontent-%COMP%]{width:100%;height:20px}"], changeDetection: 0 });
2003
- (function () {
2004
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreePlaceholderComponent, [{
2005
- type: Component,
2006
- args: [{ selector: "limble-tree-placeholder", changeDetection: ChangeDetectionStrategy.OnPush, template: "<drop-zone [dropZone]=\"dropZone\"></drop-zone>\n<div class=\"placeholder\" (dragoverNoChangeDetect)=\"dragoverHandler()\"></div>\n", styles: [".placeholder{width:100%;height:20px}\n"] }]
2007
- }], function () { return [{ type: DropZoneService }, { type: i0.ChangeDetectorRef }, { type: TreeService }, { type: TreeConstructionStatus }]; }, null);
2008
- })();
419
+ class GraftEvent {
420
+ constructor(source, relationship) {
421
+ this._source = source;
422
+ this._child = relationship.child;
423
+ this._parent = relationship.parent;
424
+ this._index = relationship.index;
425
+ }
426
+ child() {
427
+ return this._child;
428
+ }
429
+ type() {
430
+ return "graft";
431
+ }
432
+ index() {
433
+ return this._index;
434
+ }
435
+ parent() {
436
+ return this._parent;
437
+ }
438
+ source() {
439
+ return this._source;
440
+ }
441
+ }
2009
442
 
2010
- class DragleaveNoChangeDetectDirective {
2011
- constructor(ngZone, el) {
2012
- this.ngZone = ngZone;
2013
- this.el = el;
2014
- this.dragleaveNoChangeDetect = new EventEmitter();
2015
- }
2016
- ngOnInit() {
2017
- this.ngZone.runOutsideAngular(() => {
2018
- this.eventSubscription = fromEvent(this.el.nativeElement, "dragleave").subscribe(($event) => {
2019
- this.dragleaveNoChangeDetect.emit($event);
2020
- });
2021
- });
2022
- }
2023
- ngOnDestroy() {
2024
- if (this.eventSubscription !== undefined) {
2025
- this.eventSubscription.unsubscribe();
2026
- }
2027
- }
2028
- }
2029
- DragleaveNoChangeDetectDirective.ɵfac = function DragleaveNoChangeDetectDirective_Factory(t) { return new (t || DragleaveNoChangeDetectDirective)(i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i0.ElementRef)); };
2030
- DragleaveNoChangeDetectDirective.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: DragleaveNoChangeDetectDirective, selectors: [["", "dragleaveNoChangeDetect", ""]], outputs: { dragleaveNoChangeDetect: "dragleaveNoChangeDetect" } });
2031
- (function () {
2032
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DragleaveNoChangeDetectDirective, [{
2033
- type: Directive,
2034
- args: [{
2035
- selector: "[dragleaveNoChangeDetect]"
2036
- }]
2037
- }], function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, { dragleaveNoChangeDetect: [{
2038
- type: Output
2039
- }] });
2040
- })();
443
+ class PruneEvent {
444
+ constructor(source, relationship) {
445
+ this._source = source;
446
+ this._child = relationship.child;
447
+ this._parent = relationship.parent;
448
+ this._index = relationship.index;
449
+ }
450
+ child() {
451
+ return this._child;
452
+ }
453
+ type() {
454
+ return "prune";
455
+ }
456
+ index() {
457
+ return this._index;
458
+ }
459
+ parent() {
460
+ return this._parent;
461
+ }
462
+ source() {
463
+ return this._source;
464
+ }
465
+ }
2041
466
 
2042
- const _c0 = ["host"];
2043
- function LimbleTreeRootComponent_limble_tree_placeholder_1_Template(rf, ctx) {
2044
- if (rf & 1) {
2045
- i0.ɵɵelement(0, "limble-tree-placeholder");
2046
- }
2047
- }
2048
- function LimbleTreeRootComponent_ng_template_2_Template(rf, ctx) { }
2049
- class LimbleTreeRootComponent {
2050
- constructor(treeService, dropZoneService, dragStateService, globalEventsService, ngZone, changeDetectorRef, el) {
2051
- this.treeService = treeService;
2052
- this.dropZoneService = dropZoneService;
2053
- this.dragStateService = dragStateService;
2054
- this.globalEventsService = globalEventsService;
2055
- this.ngZone = ngZone;
2056
- this.changeDetectorRef = changeDetectorRef;
2057
- this.el = el;
2058
- this.treeChange = new EventEmitter();
2059
- this.treeDrop = new EventEmitter();
2060
- this.changesSubscription = this.treeService.changes$.subscribe(() => {
2061
- //"In dev mode, Angular performs an additional check after each change
2062
- //detection run, to ensure the bindings haven’t changed." We use a timeout here
2063
- //to preclude the possibility of causing a binding to update in the parent
2064
- //component after change detection runs but before the additional check.
2065
- //See https://angular.io/errors/NG0100 for details.
2066
- setTimeout(() => {
2067
- this.treeChange.emit();
2068
- });
2069
- });
2070
- this.dropSubscription = this.treeService.drops$.subscribe((drop) => {
2071
- setTimeout(() => {
2072
- this.treeDrop.emit(drop);
2073
- });
2074
- });
2075
- this.placeholder = false;
2076
- this.treeService.placeholder$.subscribe((value) => {
2077
- this.placeholder = value;
2078
- if (!NgZone.isInAngularZone()) {
2079
- this.changeDetectorRef.detectChanges();
2080
- }
2081
- });
2082
- }
2083
- ngAfterViewInit() {
2084
- var _a;
2085
- if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.listMode) !== true &&
2086
- (this.itemsPerPage !== undefined || this.page !== undefined)) {
2087
- console.warn("pagination is only allowed in listMode; `itemsPerPage` and `page` inputs will be ignored");
2088
- }
2089
- this.update();
2090
- this.changeDetectorRef.detectChanges();
2091
- this.ngZone.runOutsideAngular(() => {
2092
- //this is for mac os - without this dragover handler drop events aren't firing correctly
2093
- this.el.nativeElement.addEventListener("dragover", (event) => {
2094
- event.preventDefault();
2095
- });
2096
- });
2097
- }
2098
- ngOnChanges() {
2099
- if (this.host !== undefined && this.data !== undefined) {
2100
- this.update();
2101
- }
2102
- }
2103
- /** Rebuild the tree */
2104
- update() {
2105
- if (this.host === undefined) {
2106
- throw new Error("Failed to render limble tree. Failure occurred at root.");
2107
- }
2108
- if (this.data === undefined) {
2109
- throw new Error(`limbleTree requires a data object`);
2110
- }
2111
- this.treeService.init(this.host, this.data, this.options, this.itemsPerPage, this.page);
2112
- //We check for firefox here because there is a bug in Firefox that causes the
2113
- //custom scrolling to break. See https://bugzilla.mozilla.org/show_bug.cgi?id=505521#c80
2114
- if (!isFirefox()) {
2115
- this.globalEventsService.addScrolling();
2116
- }
2117
- }
2118
- dragoverHandler(event) {
2119
- if (event.dataTransfer === null) {
2120
- return;
2121
- }
2122
- event.stopPropagation();
2123
- event.preventDefault();
2124
- event.dataTransfer.dropEffect = "move";
2125
- }
2126
- dragleaveHandler(event) {
2127
- const currentTarget = event.currentTarget;
2128
- const relatedTarget = event.relatedTarget;
2129
- if (!(currentTarget instanceof Node) ||
2130
- !(relatedTarget instanceof Node) ||
2131
- isElementDescendant(currentTarget, relatedTarget) !== false) {
2132
- //event came from deeper in the tree. Ignore it.
2133
- return;
2134
- }
2135
- //Mouse has left the tree, so clear the drop zones
2136
- this.dropZoneService.clearVisibleZones();
2137
- this.changeDetectorRef.detectChanges();
2138
- }
2139
- dropHandler(event) {
2140
- event.stopPropagation();
2141
- if (this.dragStateService.getState() !== "droppable") {
2142
- return;
2143
- }
2144
- const sourceBranch = this.dragStateService.capture();
2145
- if (sourceBranch === undefined) {
2146
- throw new Error("failed to get current branch in dragendHandler");
2147
- }
2148
- const dropZone = this.dropZoneService.getActiveDropZone();
2149
- if (dropZone === null) {
2150
- throw new Error("failed to get active drop zone at drop handler");
2151
- }
2152
- this.treeService.captured = true;
2153
- this.dragStateService.state$
2154
- .pipe(first((message) => message === "idle"))
2155
- .subscribe(() => {
2156
- this.treeService.captured = false;
2157
- });
2158
- this.dropZoneService.clearVisibleZones();
2159
- this.treeService.drop(sourceBranch, dropZone.getFullInsertCoordinates());
2160
- }
2161
- ngOnDestroy() {
2162
- this.changesSubscription.unsubscribe();
2163
- this.dropSubscription.unsubscribe();
2164
- }
2165
- }
2166
- LimbleTreeRootComponent.ɵfac = function LimbleTreeRootComponent_Factory(t) { return new (t || LimbleTreeRootComponent)(i0.ɵɵdirectiveInject(TreeService), i0.ɵɵdirectiveInject(DropZoneService), i0.ɵɵdirectiveInject(DragStateService), i0.ɵɵdirectiveInject(GlobalEventsService), i0.ɵɵdirectiveInject(i0.NgZone), i0.ɵɵdirectiveInject(i0.ChangeDetectorRef), i0.ɵɵdirectiveInject(i0.ElementRef)); };
2167
- LimbleTreeRootComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: LimbleTreeRootComponent, selectors: [["limble-tree-root"]], viewQuery: function LimbleTreeRootComponent_Query(rf, ctx) {
2168
- if (rf & 1) {
2169
- i0.ɵɵviewQuery(_c0, 5, ViewContainerRef);
2170
- }
2171
- if (rf & 2) {
2172
- let _t;
2173
- i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.host = _t.first);
2174
- }
2175
- }, inputs: { data: "data", options: "options", itemsPerPage: "itemsPerPage", page: "page" }, outputs: { treeChange: "treeChange", treeDrop: "treeDrop" }, features: [i0.ɵɵProvidersFeature([TreeService, DropZoneService, TreeConstructionStatus]), i0.ɵɵNgOnChangesFeature], decls: 4, vars: 1, consts: [[1, "tree-event-host", 3, "dragoverNoChangeDetect", "dragleaveNoChangeDetect", "drop"], [4, "ngIf"], ["host", ""]], template: function LimbleTreeRootComponent_Template(rf, ctx) {
2176
- if (rf & 1) {
2177
- i0.ɵɵelementStart(0, "div", 0);
2178
- i0.ɵɵlistener("dragoverNoChangeDetect", function LimbleTreeRootComponent_Template_div_dragoverNoChangeDetect_0_listener($event) { return ctx.dragoverHandler($event); })("dragleaveNoChangeDetect", function LimbleTreeRootComponent_Template_div_dragleaveNoChangeDetect_0_listener($event) { return ctx.dragleaveHandler($event); })("drop", function LimbleTreeRootComponent_Template_div_drop_0_listener($event) { return ctx.dropHandler($event); });
2179
- i0.ɵɵtemplate(1, LimbleTreeRootComponent_limble_tree_placeholder_1_Template, 1, 0, "limble-tree-placeholder", 1);
2180
- i0.ɵɵtemplate(2, LimbleTreeRootComponent_ng_template_2_Template, 0, 0, "ng-template", null, 2, i0.ɵɵtemplateRefExtractor);
2181
- i0.ɵɵelementEnd();
2182
- }
2183
- if (rf & 2) {
2184
- i0.ɵɵadvance(1);
2185
- i0.ɵɵproperty("ngIf", ctx.placeholder === true);
2186
- }
2187
- }, dependencies: [i2.NgIf, LimbleTreePlaceholderComponent, DragoverNoChangeDetectDirective, DragleaveNoChangeDetectDirective] });
2188
- (function () {
2189
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreeRootComponent, [{
2190
- type: Component,
2191
- args: [{ selector: "limble-tree-root", providers: [TreeService, DropZoneService, TreeConstructionStatus], template: "<div\n (dragoverNoChangeDetect)=\"dragoverHandler($event)\"\n (dragleaveNoChangeDetect)=\"dragleaveHandler($event)\"\n (drop)=\"dropHandler($event)\"\n class=\"tree-event-host\"\n>\n <limble-tree-placeholder\n *ngIf=\"placeholder === true\"\n ></limble-tree-placeholder>\n <ng-template #host></ng-template>\n</div>\n" }]
2192
- }], function () { return [{ type: TreeService }, { type: DropZoneService }, { type: DragStateService }, { type: GlobalEventsService }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, { data: [{
2193
- type: Input
2194
- }], options: [{
2195
- type: Input
2196
- }], itemsPerPage: [{
2197
- type: Input
2198
- }], page: [{
2199
- type: Input
2200
- }], host: [{
2201
- type: ViewChild,
2202
- args: ["host", { read: ViewContainerRef }]
2203
- }], treeChange: [{
2204
- type: Output
2205
- }], treeDrop: [{
2206
- type: Output
2207
- }] });
2208
- })();
467
+ class TreeNodeBase {
468
+ constructor() {
469
+ this.destroyed = false;
470
+ this._branches = [];
471
+ this.events$ = new Subject();
472
+ this.subscriptions = [
473
+ this.graftsToSelf().subscribe((event) => {
474
+ this.registerChildRelationship(event.child(), event.index());
475
+ }),
476
+ this.prunesToSelf().subscribe((event) => {
477
+ this.deregisterChildRelationship(event.child());
478
+ })
479
+ ];
480
+ }
481
+ branches() {
482
+ return [...this._branches];
483
+ }
484
+ destroy() {
485
+ this.branches().forEach((branch) => {
486
+ branch.destroy();
487
+ });
488
+ this.subscriptions.forEach((sub) => {
489
+ sub.unsubscribe();
490
+ });
491
+ this.destroyed = true;
492
+ }
493
+ dispatch(event) {
494
+ this.events$.next(event);
495
+ }
496
+ events() {
497
+ return this.events$;
498
+ }
499
+ getBranch(index) {
500
+ return this._branches[index];
501
+ }
502
+ isDestroyed() {
503
+ return this.destroyed;
504
+ }
505
+ plot() {
506
+ return new Map(this.branches().map((branch, index) => [index, branch.plot()]));
507
+ }
508
+ traverse(callback) {
509
+ this.branches().forEach((branch) => {
510
+ branch.traverse(callback);
511
+ });
512
+ }
513
+ deregisterChildRelationship(child) {
514
+ const index = this.branches().findIndex((branch) => branch === child);
515
+ this._branches.splice(index, 1);
516
+ }
517
+ graftsToSelf() {
518
+ return this.events().pipe(filter((event) => event instanceof GraftEvent), filter((event) => event.parent().events() === this.events$));
519
+ }
520
+ prunesToSelf() {
521
+ return this.events().pipe(filter((event) => event instanceof PruneEvent), filter((event) => event.parent().events() === this.events$));
522
+ }
523
+ registerChildRelationship(child, index) {
524
+ const branches = this.branches();
525
+ if (index < 0 || index > branches.length) {
526
+ throw new TreeError(`Can't register child at index ${index}. Out of range.`);
527
+ }
528
+ this._branches.splice(index, 0, child);
529
+ }
530
+ }
531
+
532
+ class DestructionEvent {
533
+ constructor(source) {
534
+ this._source = source;
535
+ }
536
+ type() {
537
+ return "destruction";
538
+ }
539
+ source() {
540
+ return this._source;
541
+ }
542
+ }
2209
543
 
2210
- class LimbleTreeModule {
2211
- }
2212
- LimbleTreeModule.ɵfac = function LimbleTreeModule_Factory(t) { return new (t || LimbleTreeModule)(); };
2213
- LimbleTreeModule.ɵmod = /*@__PURE__*/ i0.ɵɵdefineNgModule({ type: LimbleTreeModule });
2214
- LimbleTreeModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({ providers: [ComponentCreatorService, DragStateService, GlobalEventsService], imports: [CommonModule] });
2215
- (function () {
2216
- (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LimbleTreeModule, [{
2217
- type: NgModule,
2218
- args: [{
2219
- declarations: [
2220
- LimbleTreeBranchComponent,
2221
- DropZoneComponent,
2222
- LimbleTreeNodeComponent,
2223
- LimbleTreeRootComponent,
2224
- LimbleTreePlaceholderComponent,
2225
- DragoverNoChangeDetectDirective,
2226
- DragleaveNoChangeDetectDirective
2227
- ],
2228
- imports: [CommonModule],
2229
- exports: [LimbleTreeRootComponent],
2230
- providers: [ComponentCreatorService, DragStateService, GlobalEventsService]
2231
- }]
2232
- }], null, null);
2233
- })();
2234
- (function () {
2235
- (typeof ngJitMode === "undefined" || ngJitMode) && i0.ɵɵsetNgModuleScope(LimbleTreeModule, { declarations: [LimbleTreeBranchComponent,
2236
- DropZoneComponent,
2237
- LimbleTreeNodeComponent,
2238
- LimbleTreeRootComponent,
2239
- LimbleTreePlaceholderComponent,
2240
- DragoverNoChangeDetectDirective,
2241
- DragleaveNoChangeDetectDirective], imports: [CommonModule], exports: [LimbleTreeRootComponent] });
2242
- })();
2243
- i0.ɵɵsetComponentScope(LimbleTreeNodeComponent, [i2.NgIf, LimbleTreeBranchComponent,
2244
- DropZoneComponent,
2245
- DragoverNoChangeDetectDirective], []);
544
+ class RootComponent {
545
+ constructor() {
546
+ this.branchesContainer = undefined;
547
+ this.dropzone = undefined;
548
+ this.afterViewInit = new EventEmitter();
549
+ this.dropped = new EventEmitter();
550
+ this.showInnerDropzone = false;
551
+ }
552
+ ngAfterViewInit() {
553
+ this.afterViewInit.emit();
554
+ assert(this.dropzone !== undefined);
555
+ this.dropzone.dropped.subscribe(this.dropped);
556
+ }
557
+ }
558
+ RootComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
559
+ RootComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RootComponent, isStandalone: true, selector: "root", outputs: { afterViewInit: "afterViewInit", dropped: "dropped" }, viewQueries: [{ propertyName: "branchesContainer", first: true, predicate: ["branchesContainer"], descendants: true, read: ViewContainerRef }, { propertyName: "dropzone", first: true, predicate: DropzoneComponent, descendants: true }], ngImport: i0, template: "<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n", styles: [".branches-container{min-width:64px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: DropzoneComponent, selector: "dropzone", inputs: ["placement"], outputs: ["dropped"] }] });
560
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RootComponent, decorators: [{
561
+ type: Component,
562
+ args: [{ standalone: true, selector: "root", imports: [CommonModule, DropzoneComponent], template: "<div class=\"branches-container\">\n <dropzone placement=\"inner\" [hidden]=\"!showInnerDropzone\"></dropzone>\n <div #branchesContainer></div>\n</div>\n", styles: [".branches-container{min-width:64px}\n"] }]
563
+ }], propDecorators: { branchesContainer: [{
564
+ type: ViewChild,
565
+ args: ["branchesContainer", { read: ViewContainerRef }]
566
+ }], dropzone: [{
567
+ type: ViewChild,
568
+ args: [DropzoneComponent]
569
+ }], afterViewInit: [{
570
+ type: Output
571
+ }], dropped: [{
572
+ type: Output
573
+ }] } });
574
+
575
+ /**
576
+ * A wrapper around the BranchComponent that helps instantiate it and handles its events.
577
+ */
578
+ class RootController {
579
+ constructor(treeRoot, viewContainerRef) {
580
+ this.treeRoot = treeRoot;
581
+ this.rootComponentRef = viewContainerRef.createComponent(RootComponent);
582
+ const viewInitSub = this.rootComponentRef.instance.afterViewInit.subscribe(() => {
583
+ const dropzone = this.rootComponentRef.instance.dropzone;
584
+ assert(dropzone !== undefined);
585
+ dropzoneRenderer.registerDropzone(dropzone, this.treeRoot);
586
+ });
587
+ const droppedSub = this.rootComponentRef.instance.dropped.subscribe(() => {
588
+ dropzoneRenderer.handleDrop(this.treeRoot, "inner");
589
+ });
590
+ this.instanceSubscriptions = [viewInitSub, droppedSub];
591
+ }
592
+ destroy() {
593
+ this.instanceSubscriptions.forEach((sub) => {
594
+ sub.unsubscribe();
595
+ });
596
+ }
597
+ detectChanges() {
598
+ this.rootComponentRef.changeDetectorRef.detectChanges();
599
+ }
600
+ getBranchesContainer() {
601
+ return this.rootComponentRef.instance.branchesContainer;
602
+ }
603
+ getComponentInstance() {
604
+ return this.rootComponentRef.instance;
605
+ }
606
+ getHostView() {
607
+ return this.rootComponentRef.hostView;
608
+ }
609
+ getNativeElement() {
610
+ return this.rootComponentRef.location.nativeElement;
611
+ }
612
+ }
613
+
614
+ class TreeRoot {
615
+ constructor(viewContainerRef) {
616
+ this.viewContainerRef = viewContainerRef;
617
+ this.treeNodeBase = new TreeNodeBase();
618
+ this.rootController = new RootController(this, viewContainerRef);
619
+ this.detectChanges();
620
+ }
621
+ branches() {
622
+ return this.treeNodeBase.branches();
623
+ }
624
+ destroy() {
625
+ if (this.isDestroyed()) {
626
+ throw new TreeError("Cannot destroy a destroyed tree root");
627
+ }
628
+ dropzoneRenderer.clearTreeFromRegistry(this);
629
+ this.treeNodeBase.destroy();
630
+ this.rootController.destroy();
631
+ this.viewContainerRef.clear();
632
+ config.delete(this);
633
+ this.dispatch(new DestructionEvent(this));
634
+ }
635
+ detectChanges() {
636
+ this.rootController.detectChanges();
637
+ }
638
+ dispatch(event) {
639
+ this.treeNodeBase.dispatch(event);
640
+ }
641
+ events() {
642
+ return this.treeNodeBase.events();
643
+ }
644
+ getBranch(index) {
645
+ return this.treeNodeBase.getBranch(index);
646
+ }
647
+ getBranchesContainer() {
648
+ if (this.isDestroyed()) {
649
+ throw new TreeError("Cannot get branches container from a destroyed tree root");
650
+ }
651
+ return this.rootController.getBranchesContainer();
652
+ }
653
+ getComponentInstance() {
654
+ if (this.isDestroyed()) {
655
+ throw new TreeError("Cannot get component instance from a destroyed tree root");
656
+ }
657
+ return this.rootController.getComponentInstance();
658
+ }
659
+ getHostView() {
660
+ if (this.isDestroyed()) {
661
+ throw new TreeError("Cannot get component host view from a destroyed tree root");
662
+ }
663
+ return this.rootController.getHostView();
664
+ }
665
+ getNativeElement() {
666
+ if (this.isDestroyed()) {
667
+ throw new TreeError("Cannot get native element from a destroyed tree root");
668
+ }
669
+ return this.rootController.getNativeElement();
670
+ }
671
+ grow(component, options) {
672
+ if (this.isDestroyed()) {
673
+ throw new TreeError("Cannot grow a branch on a destroyed tree root");
674
+ }
675
+ return new TreeBranch(this, Object.assign({ component }, options));
676
+ }
677
+ isDestroyed() {
678
+ return this.treeNodeBase.isDestroyed();
679
+ }
680
+ plot() {
681
+ return this.treeNodeBase.plot();
682
+ }
683
+ root() {
684
+ return this;
685
+ }
686
+ traverse(callback) {
687
+ callback(this);
688
+ this.treeNodeBase.traverse(callback);
689
+ }
690
+ }
691
+
692
+ class TreeService {
693
+ createEmptyTree(container, options = {}) {
694
+ container.clear();
695
+ const root = new TreeRoot(container);
696
+ config.setConfig(root, options);
697
+ return root;
698
+ }
699
+ }
700
+ TreeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
701
+ TreeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, providedIn: "root" });
702
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeService, decorators: [{
703
+ type: Injectable,
704
+ args: [{ providedIn: "root" }]
705
+ }] });
706
+
707
+ /**
708
+ * A wrapper around the BranchComponent that helps instantiate it and handles its events.
709
+ */
710
+ class BranchController {
711
+ constructor(treeBranch, parentBranchesContainer) {
712
+ this.treeBranch = treeBranch;
713
+ this.outputBindingSubscriptions = [];
714
+ this.branchComponentRef = createComponent(BranchComponent, {
715
+ environmentInjector: parentBranchesContainer.injector.get(EnvironmentInjector)
716
+ });
717
+ this.branchComponentRef.instance.contentToHost =
718
+ this.treeBranch.branchOptions.component;
719
+ this.instanceSubscriptions = this.getInstanceSubscriptions(this.branchComponentRef.instance);
720
+ }
721
+ destroy() {
722
+ this.instanceSubscriptions.forEach((sub) => {
723
+ sub.unsubscribe();
724
+ });
725
+ this.outputBindingSubscriptions.forEach((sub) => {
726
+ sub.unsubscribe();
727
+ });
728
+ }
729
+ detectChanges() {
730
+ this.branchComponentRef.changeDetectorRef.detectChanges();
731
+ }
732
+ getBranchesContainer() {
733
+ return this.branchComponentRef.instance.branchesContainer;
734
+ }
735
+ getComponentInstance() {
736
+ return this.branchComponentRef.instance;
737
+ }
738
+ getHostView() {
739
+ return this.branchComponentRef.hostView;
740
+ }
741
+ getNativeElement() {
742
+ return this.branchComponentRef.location.nativeElement;
743
+ }
744
+ getUserlandComponentRef() {
745
+ return this.branchComponentRef.instance.getHostedContent();
746
+ }
747
+ getContentCreatedSub(instance) {
748
+ return instance.contentCreated.subscribe((userlandComponentInstance) => {
749
+ var _a, _b;
750
+ const component = userlandComponentInstance;
751
+ Object.entries((_a = this.treeBranch.branchOptions.inputBindings) !== null && _a !== void 0 ? _a : {}).forEach(([key, value]) => {
752
+ component[key] = value;
753
+ });
754
+ Object.entries((_b = this.treeBranch.branchOptions.outputBindings) !== null && _b !== void 0 ? _b : {}).forEach(([key, value]) => {
755
+ this.outputBindingSubscriptions.push(component[key].subscribe(value));
756
+ });
757
+ component.treeBranch = this.treeBranch;
758
+ const dropzones = instance.dropzones;
759
+ assert(dropzones !== undefined);
760
+ dropzoneRenderer.registerDropzones(dropzones, this.treeBranch);
761
+ });
762
+ }
763
+ getInstanceSubscriptions(instance) {
764
+ const droppedSub = instance.dropped.subscribe((placement) => {
765
+ dropzoneRenderer.handleDrop(this.treeBranch, placement);
766
+ });
767
+ return [
768
+ this.getContentCreatedSub(instance),
769
+ this.getShowLowerZonesSub(instance),
770
+ this.getShowUpperZonesSub(instance),
771
+ droppedSub
772
+ ];
773
+ }
774
+ getShowLowerZonesSub(instance) {
775
+ return instance.showDropzones
776
+ .pipe(filter((direction) => direction === "lower"))
777
+ .subscribe(() => {
778
+ const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
779
+ if ((currentDropzoneDisplayed === null || currentDropzoneDisplayed === void 0 ? void 0 : currentDropzoneDisplayed.treeBranch) === this.treeBranch &&
780
+ currentDropzoneDisplayed.direction === "lower") {
781
+ return;
782
+ }
783
+ dropzoneRenderer.showLowerZones(this.treeBranch);
784
+ instance.triggerChangeDetection();
785
+ });
786
+ }
787
+ getShowUpperZonesSub(instance) {
788
+ return instance.showDropzones
789
+ .pipe(filter((direction) => direction === "upper"))
790
+ .subscribe(() => {
791
+ const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
792
+ if ((currentDropzoneDisplayed === null || currentDropzoneDisplayed === void 0 ? void 0 : currentDropzoneDisplayed.treeBranch) === this.treeBranch &&
793
+ currentDropzoneDisplayed.direction === "upper") {
794
+ return;
795
+ }
796
+ dropzoneRenderer.showUpperZones(this.treeBranch);
797
+ instance.triggerChangeDetection();
798
+ });
799
+ }
800
+ }
801
+
802
+ class TreeBranch {
803
+ constructor(parent, branchOptions) {
804
+ this.branchOptions = branchOptions;
805
+ this.detachedView = null;
806
+ this.treeNodeBase = new TreeNodeBase();
807
+ const parentBranchesContainer = parent.getBranchesContainer();
808
+ assert(parentBranchesContainer !== undefined);
809
+ this.branchController = new BranchController(this, parentBranchesContainer);
810
+ this.setIndentation(parent);
811
+ if (parent instanceof TreeBranch &&
812
+ parent.branchOptions.defaultCollapsed === true) {
813
+ treeCollapser.storePrecollapsedNode(parent, this);
814
+ this.detachedView = this.branchController.getHostView();
815
+ }
816
+ else {
817
+ parentBranchesContainer.insert(this.branchController.getHostView());
818
+ this.detectChanges();
819
+ this._parent = parent;
820
+ this.dispatch(new GraftEvent(this, {
821
+ parent: this._parent,
822
+ child: this,
823
+ index: this._parent.branches().length
824
+ }));
825
+ }
826
+ }
827
+ branches() {
828
+ return this.treeNodeBase.branches();
829
+ }
830
+ destroy() {
831
+ if (this.isDestroyed()) {
832
+ throw new TreeError("Cannot destroy a destroyed tree branch");
833
+ }
834
+ this.prune();
835
+ treeCollapser.expand(this);
836
+ dropzoneRenderer.clearTreeFromRegistry(this);
837
+ this.branchController.getHostView().destroy();
838
+ this.treeNodeBase.destroy();
839
+ this.branchController.destroy();
840
+ this.dispatch(new DestructionEvent(this));
841
+ }
842
+ detectChanges() {
843
+ this.branchController.detectChanges();
844
+ }
845
+ dispatch(event) {
846
+ var _a;
847
+ this.treeNodeBase.dispatch(event);
848
+ (_a = this._parent) === null || _a === void 0 ? void 0 : _a.dispatch(event);
849
+ }
850
+ events() {
851
+ return this.treeNodeBase.events();
852
+ }
853
+ getBranch(index) {
854
+ return this.treeNodeBase.getBranch(index);
855
+ }
856
+ getBranchesContainer() {
857
+ if (this.isDestroyed()) {
858
+ throw new TreeError("Cannot get branches container from a destroyed tree branch");
859
+ }
860
+ return this.branchController.getBranchesContainer();
861
+ }
862
+ getComponentInstance() {
863
+ if (this.isDestroyed()) {
864
+ throw new TreeError("Cannot get component instance from a destroyed tree branch");
865
+ }
866
+ return this.branchController.getComponentInstance();
867
+ }
868
+ getHostView() {
869
+ if (this.isDestroyed()) {
870
+ throw new TreeError("Cannot get component host view from a destroyed tree branch");
871
+ }
872
+ return this.branchController.getHostView();
873
+ }
874
+ getNativeElement() {
875
+ if (this.isDestroyed()) {
876
+ throw new TreeError("Cannot get native element from a destroyed tree branch");
877
+ }
878
+ return this.branchController.getNativeElement();
879
+ }
880
+ getUserlandComponentRef() {
881
+ if (this.isDestroyed()) {
882
+ throw new TreeError("Cannot get userland component from a destroyed tree branch");
883
+ }
884
+ return this.branchController.getUserlandComponentRef();
885
+ }
886
+ graftTo(newParent, index) {
887
+ this.checkGraftLocationValidity(newParent, index);
888
+ const ownIndex = this.index();
889
+ if (ownIndex !== undefined) {
890
+ this.prune();
891
+ }
892
+ this._parent = newParent;
893
+ const newIndex = index !== null && index !== void 0 ? index : newParent.branches().length;
894
+ this.reattachView(newIndex);
895
+ this.dispatch(new GraftEvent(this, {
896
+ parent: newParent,
897
+ child: this,
898
+ index: newIndex
899
+ }));
900
+ return newIndex;
901
+ }
902
+ grow(component, options) {
903
+ if (this.isDestroyed()) {
904
+ throw new TreeError("Cannot grow a branch on a destroyed tree branch");
905
+ }
906
+ return new TreeBranch(this, Object.assign({ component }, options));
907
+ }
908
+ index() {
909
+ if (!this._parent) {
910
+ return undefined;
911
+ }
912
+ const index = this._parent
913
+ .branches()
914
+ .findIndex((branch) => branch === this);
915
+ assert(index >= 0);
916
+ return index;
917
+ }
918
+ isDestroyed() {
919
+ return this.treeNodeBase.isDestroyed();
920
+ }
921
+ meta() {
922
+ var _a;
923
+ return (_a = this.branchOptions.meta) !== null && _a !== void 0 ? _a : {};
924
+ }
925
+ parent() {
926
+ return this._parent;
927
+ }
928
+ plot() {
929
+ return this.treeNodeBase.plot();
930
+ }
931
+ position() {
932
+ const index = this.index();
933
+ if (index === undefined) {
934
+ throw new TreeError("branch has no parent. Position cannot be determined.");
935
+ }
936
+ if (this._parent instanceof TreeBranch) {
937
+ const parentPosition = this._parent.position();
938
+ return [...parentPosition, index];
939
+ }
940
+ return [index];
941
+ }
942
+ prune() {
943
+ if (this.isDestroyed()) {
944
+ throw new TreeError("Cannot prune a destroyed tree branch");
945
+ }
946
+ const parent = this._parent;
947
+ const index = this.index();
948
+ if (index === undefined || parent === undefined)
949
+ return;
950
+ const container = parent.getBranchesContainer();
951
+ assert(container !== undefined);
952
+ this.detachedView = container.detach(index);
953
+ assert(this.detachedView !== null);
954
+ this.detachedView.detach();
955
+ this.dispatch(new PruneEvent(this, {
956
+ parent: parent,
957
+ child: this,
958
+ index: index
959
+ }));
960
+ this._parent = undefined;
961
+ return this;
962
+ }
963
+ root() {
964
+ const parent = this.parent();
965
+ if (parent instanceof TreeBranch) {
966
+ return parent.root();
967
+ }
968
+ assert(parent instanceof TreeRoot || parent === undefined);
969
+ return parent;
970
+ }
971
+ traverse(callback) {
972
+ callback(this);
973
+ this.treeNodeBase.traverse(callback);
974
+ }
975
+ checkGraftLocationValidity(newParent, index) {
976
+ if (this.isDestroyed()) {
977
+ throw new TreeError("Cannot graft a destroyed tree branch");
978
+ }
979
+ if (newParent.isDestroyed()) {
980
+ throw new TreeError("Cannot graft to a destroyed tree branch");
981
+ }
982
+ if (typeof index === "number" &&
983
+ this.indexIsOutOfRange(newParent, index)) {
984
+ throw new TreeError(`Cannot graft branch at index ${index} of the parent. Out of range.`);
985
+ }
986
+ this.traverse((node) => {
987
+ if (node === newParent) {
988
+ throw new TreeError("Cannot graft a branch to itself or any of its own descendants");
989
+ }
990
+ });
991
+ }
992
+ indexIsOutOfRange(parent, index) {
993
+ return index < 0 || index > parent.branches().length;
994
+ }
995
+ reattachView(index) {
996
+ assert(this._parent !== undefined);
997
+ assert(this.detachedView !== null);
998
+ const container = this._parent.getBranchesContainer();
999
+ assert(container !== undefined);
1000
+ this.detachedView.reattach();
1001
+ container.insert(this.detachedView, index);
1002
+ this.detachedView = null;
1003
+ }
1004
+ setIndentation(parent) {
1005
+ var _a;
1006
+ const root = parent.root();
1007
+ assert(root !== undefined);
1008
+ const options = config.getConfig(root);
1009
+ const branchesContainerEl = this.branchController
1010
+ .getNativeElement()
1011
+ .getElementsByClassName("branches-container")
1012
+ .item(0);
1013
+ assert(branchesContainerEl instanceof HTMLElement);
1014
+ branchesContainerEl.style.marginLeft = `${(_a = options === null || options === void 0 ? void 0 : options.indentation) !== null && _a !== void 0 ? _a : 16}px`;
1015
+ }
1016
+ }
1017
+
1018
+ class DropzoneRenderer {
1019
+ constructor() {
1020
+ this.registry = new Map();
1021
+ this.currentDisplay = null;
1022
+ dragAndDrop.dragAborted$.subscribe(() => {
1023
+ this.clearCurrentDisplay();
1024
+ });
1025
+ dragState
1026
+ .events()
1027
+ .pipe(filter((event) => event === DragStates.Starting))
1028
+ .subscribe(() => {
1029
+ var _a, _b;
1030
+ const branch = dragState.getDragData();
1031
+ assert(branch !== undefined);
1032
+ let cursor = (_a = branch.parent()) === null || _a === void 0 ? void 0 : _a.getBranch(((_b = branch.index()) !== null && _b !== void 0 ? _b : 0) - 1);
1033
+ let final = branch.parent();
1034
+ while (cursor !== undefined) {
1035
+ final = cursor;
1036
+ cursor = cursor.branches().at(-1);
1037
+ }
1038
+ branch
1039
+ .events()
1040
+ .pipe(filter((event) => event instanceof PruneEvent), first())
1041
+ .subscribe(() => {
1042
+ assert(final instanceof TreeBranch || final instanceof TreeRoot);
1043
+ this.showLowerZones(final);
1044
+ });
1045
+ });
1046
+ }
1047
+ clearCurrentDisplay() {
1048
+ if (this.currentDisplay === null)
1049
+ return;
1050
+ for (const branch of this.registry.values()) {
1051
+ const instance = branch.getComponentInstance();
1052
+ instance.showInnerDropzone = false;
1053
+ if (instance instanceof BranchComponent) {
1054
+ instance.showLateralDropzone = false;
1055
+ }
1056
+ }
1057
+ this.currentDisplay = null;
1058
+ }
1059
+ clearTreeFromRegistry(tree) {
1060
+ const nodes = [];
1061
+ tree.traverse((node) => nodes.push(node));
1062
+ for (const [dropzoneComponent, treeNode] of this.registry) {
1063
+ if (nodes.includes(treeNode)) {
1064
+ this.registry.delete(dropzoneComponent);
1065
+ }
1066
+ }
1067
+ }
1068
+ getCurrentDisplay() {
1069
+ if (this.currentDisplay === null)
1070
+ return null;
1071
+ return Object.assign({}, this.currentDisplay);
1072
+ }
1073
+ getDropzoneLocation(dropzone) {
1074
+ const branch = this.registry.get(dropzone);
1075
+ const placement = dropzone.placement;
1076
+ if (branch === undefined) {
1077
+ throw new Error("dropzone not found in registry");
1078
+ }
1079
+ if (placement === undefined) {
1080
+ throw new Error("dropzone has an undefined placement");
1081
+ }
1082
+ return [branch, placement];
1083
+ }
1084
+ handleDrop(treeNode, placement) {
1085
+ if (placement === "inner") {
1086
+ dragAndDrop.drop(treeNode, 0);
1087
+ }
1088
+ else if (treeNode instanceof TreeBranch && placement === "lateral") {
1089
+ const currentParent = treeNode.parent();
1090
+ const index = treeNode.index();
1091
+ if (currentParent === undefined || index === undefined) {
1092
+ throw new Error("branch must have a parent");
1093
+ }
1094
+ dragAndDrop.drop(currentParent, index + 1);
1095
+ }
1096
+ this.clearCurrentDisplay();
1097
+ }
1098
+ registerDropzone(dropzone, treeNode) {
1099
+ this.registry.set(dropzone, treeNode);
1100
+ }
1101
+ registerDropzones(dropzones, treeBranch) {
1102
+ for (const dropzone of dropzones) {
1103
+ this.registry.set(dropzone, treeBranch);
1104
+ }
1105
+ }
1106
+ showLowerZones(treeNode) {
1107
+ this.clearCurrentDisplay();
1108
+ this.showInnerZone(treeNode);
1109
+ if (treeNode.branches().length === 0) {
1110
+ this.loopThroughLowerZones(treeNode);
1111
+ }
1112
+ this.currentDisplay = { treeBranch: treeNode, direction: "lower" };
1113
+ }
1114
+ showUpperZones(treeBranch) {
1115
+ this.clearCurrentDisplay();
1116
+ this.loopThroughUpperZones(treeBranch);
1117
+ this.currentDisplay = { treeBranch, direction: "upper" };
1118
+ }
1119
+ loopThroughLowerZones(treeNode) {
1120
+ let cursor = treeNode;
1121
+ while (cursor instanceof TreeBranch) {
1122
+ this.showLateralZone(cursor);
1123
+ const parent = cursor.parent();
1124
+ const index = cursor.index();
1125
+ assert(parent !== undefined && index !== undefined);
1126
+ if (parent.branches().length > index + 1) {
1127
+ return;
1128
+ }
1129
+ cursor = cursor.parent();
1130
+ }
1131
+ }
1132
+ loopThroughUpperZones(treeBranch) {
1133
+ var _a, _b;
1134
+ let cursor = (_a = treeBranch
1135
+ .parent()) === null || _a === void 0 ? void 0 : _a.getBranch(((_b = treeBranch.index()) !== null && _b !== void 0 ? _b : 0) - 1);
1136
+ let final = treeBranch.parent();
1137
+ while (cursor !== undefined) {
1138
+ this.showLateralZone(cursor);
1139
+ final = cursor;
1140
+ cursor = cursor.branches().at(-1);
1141
+ }
1142
+ if (final !== undefined &&
1143
+ (final instanceof TreeRoot || final instanceof TreeBranch)) {
1144
+ this.showInnerZone(final);
1145
+ }
1146
+ }
1147
+ nestingAllowed(treeNode) {
1148
+ var _a, _b, _c;
1149
+ if (treeNode instanceof TreeRoot) {
1150
+ return true;
1151
+ }
1152
+ if (treeNode instanceof TreeBranch) {
1153
+ const allowNesting = (_c = (_b = (_a = config.getConfig(treeNode.root())) === null || _a === void 0 ? void 0 : _a.dragAndDrop) === null || _b === void 0 ? void 0 : _b.allowNesting) !== null && _c !== void 0 ? _c : (() => true);
1154
+ return allowNesting(treeNode);
1155
+ }
1156
+ throw new Error("unsupported treeNode type");
1157
+ }
1158
+ dropAllowed(parent, index) {
1159
+ var _a, _b, _c, _d, _e, _f;
1160
+ const sourceNode = dragState.getDragData();
1161
+ assert(sourceNode instanceof TreeBranch);
1162
+ if (parent instanceof TreeRoot) {
1163
+ const allowDrop = (_c = (_b = (_a = config.getConfig(parent)) === null || _a === void 0 ? void 0 : _a.dragAndDrop) === null || _b === void 0 ? void 0 : _b.allowDrop) !== null && _c !== void 0 ? _c : (() => true);
1164
+ return allowDrop(sourceNode, parent, index);
1165
+ }
1166
+ if (parent instanceof TreeBranch) {
1167
+ const allowDrop = (_f = (_e = (_d = config.getConfig(parent.root())) === null || _d === void 0 ? void 0 : _d.dragAndDrop) === null || _e === void 0 ? void 0 : _e.allowDrop) !== null && _f !== void 0 ? _f : (() => true);
1168
+ return allowDrop(sourceNode, parent, index);
1169
+ }
1170
+ throw new Error("unsupported treeNode type");
1171
+ }
1172
+ showInnerZone(treeNode) {
1173
+ if (!this.nestingAllowed(treeNode) || !this.dropAllowed(treeNode, 0))
1174
+ return;
1175
+ treeNode.getComponentInstance().showInnerDropzone = true;
1176
+ }
1177
+ showLateralZone(treeBranch) {
1178
+ const index = treeBranch.index();
1179
+ assert(index !== undefined);
1180
+ if (!this.dropAllowed(treeBranch.parent(), index + 1))
1181
+ return;
1182
+ treeBranch.getComponentInstance().showLateralDropzone = true;
1183
+ }
1184
+ }
1185
+ const dropzoneRenderer = new DropzoneRenderer();
1186
+
1187
+ class TreeDragAndDropService {
1188
+ clearDropzones() {
1189
+ dropzoneRenderer.clearCurrentDisplay();
1190
+ }
1191
+ dragStart(treeBranch, event) {
1192
+ dragAndDrop.dragStart(treeBranch, event);
1193
+ }
1194
+ getCurrentlyDisplayedDropzoneFamily() {
1195
+ return dropzoneRenderer.getCurrentDisplay();
1196
+ }
1197
+ showRootDropzone(root) {
1198
+ dropzoneRenderer.showLowerZones(root);
1199
+ }
1200
+ state() {
1201
+ return dragState.events();
1202
+ }
1203
+ }
1204
+ TreeDragAndDropService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1205
+ TreeDragAndDropService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService });
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropService, decorators: [{
1207
+ type: Injectable
1208
+ }] });
1209
+
1210
+ class DraggableDirective {
1211
+ constructor(dragAndDropService, renderer, hostElement) {
1212
+ this.dragAndDropService = dragAndDropService;
1213
+ renderer.setAttribute(hostElement.nativeElement, "draggable", "true");
1214
+ renderer.setStyle(hostElement.nativeElement, "cursor", "grab");
1215
+ }
1216
+ onDragstart(event) {
1217
+ if (this.limbleTreeDraggable === undefined)
1218
+ return;
1219
+ this.dragAndDropService.dragStart(this.limbleTreeDraggable, event);
1220
+ }
1221
+ }
1222
+ DraggableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, deps: [{ token: TreeDragAndDropService }, { token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1223
+ DraggableDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DraggableDirective, isStandalone: true, selector: "[limbleTreeDraggable]", inputs: { limbleTreeDraggable: "limbleTreeDraggable" }, host: { listeners: { "dragstart": "onDragstart($event)" } }, ngImport: i0 });
1224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, decorators: [{
1225
+ type: Directive,
1226
+ args: [{
1227
+ selector: "[limbleTreeDraggable]",
1228
+ standalone: true
1229
+ }]
1230
+ }], ctorParameters: function () { return [{ type: TreeDragAndDropService }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { limbleTreeDraggable: [{
1231
+ type: Input
1232
+ }], onDragstart: [{
1233
+ type: HostListener,
1234
+ args: ["dragstart", ["$event"]]
1235
+ }] } });
1236
+
1237
+ class TreeDragAndDropModule {
1238
+ }
1239
+ TreeDragAndDropModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1240
+ TreeDragAndDropModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, imports: [DraggableDirective, DragoverNoChangeDetectDirective], exports: [DraggableDirective, DragoverNoChangeDetectDirective] });
1241
+ TreeDragAndDropModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, providers: [TreeDragAndDropService] });
1242
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, decorators: [{
1243
+ type: NgModule,
1244
+ args: [{
1245
+ imports: [DraggableDirective, DragoverNoChangeDetectDirective],
1246
+ providers: [TreeDragAndDropService],
1247
+ exports: [DraggableDirective, DragoverNoChangeDetectDirective]
1248
+ }]
1249
+ }] });
1250
+
1251
+ /**
1252
+ * A shim to help with the transition from v0 to v1.
1253
+ * @deprecated
1254
+ */
1255
+ class LegacyTree {
1256
+ /** Creates a v1 tree structure from a v0 data array and v0 tree options. */
1257
+ createTreeFromLegacyArray(container, data, treeOptions = {}) {
1258
+ const root = new TreeRoot(container);
1259
+ config.setConfig(root, this.upgradeOptions(treeOptions));
1260
+ for (const node of data) {
1261
+ this.renderTreeNode(root, node, treeOptions);
1262
+ }
1263
+ return root;
1264
+ }
1265
+ upgradeOptions(legacyOptions) {
1266
+ return {
1267
+ indentation: legacyOptions.indent,
1268
+ dragAndDrop: {
1269
+ allowNesting: (branch) => {
1270
+ if (legacyOptions.listMode === true) {
1271
+ return false;
1272
+ }
1273
+ if (legacyOptions.allowNesting === undefined) {
1274
+ return true;
1275
+ }
1276
+ if (typeof legacyOptions.allowNesting === "boolean") {
1277
+ return legacyOptions.allowNesting;
1278
+ }
1279
+ return legacyOptions.allowNesting(branch);
1280
+ },
1281
+ allowDragging: (branch) => {
1282
+ if (legacyOptions.allowDragging === undefined) {
1283
+ return true;
1284
+ }
1285
+ if (typeof legacyOptions.allowDragging === "boolean") {
1286
+ return legacyOptions.allowDragging;
1287
+ }
1288
+ return legacyOptions.allowDragging(branch);
1289
+ },
1290
+ allowDrop: (source, parent, index) => {
1291
+ if (legacyOptions.allowDrop === undefined) {
1292
+ return true;
1293
+ }
1294
+ return legacyOptions.allowDrop(source, parent, index);
1295
+ }
1296
+ }
1297
+ };
1298
+ }
1299
+ renderTreeNode(parent, node, options) {
1300
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1301
+ const component = (_b = (_a = node.component) === null || _a === void 0 ? void 0 : _a.class) !== null && _b !== void 0 ? _b : (_c = options.defaultComponent) === null || _c === void 0 ? void 0 : _c.class;
1302
+ if (component === undefined) {
1303
+ throw new TreeError("A component must be provided");
1304
+ }
1305
+ const bindings = ((_g = (_e = (_d = node.component) === null || _d === void 0 ? void 0 : _d.bindings) !== null && _e !== void 0 ? _e : (_f = options.defaultComponent) === null || _f === void 0 ? void 0 : _f.bindings) !== null && _g !== void 0 ? _g : {});
1306
+ const nodeData = node;
1307
+ const branch = parent.grow(component, {
1308
+ inputBindings: bindings,
1309
+ meta: { nodeData }
1310
+ });
1311
+ for (const childNode of (_h = node.nodes) !== null && _h !== void 0 ? _h : []) {
1312
+ this.renderTreeNode(branch, childNode, options);
1313
+ }
1314
+ if (node.collapsed === true) {
1315
+ treeCollapser.collapse(branch);
1316
+ }
1317
+ }
1318
+ }
1319
+
1320
+ /** @deprecated */
1321
+ class LimbleTreeRootComponent {
1322
+ constructor() {
1323
+ this.itemsPerPage = Infinity;
1324
+ this.page = 1;
1325
+ this.treeChange = new EventEmitter();
1326
+ this.treeDrop = new EventEmitter();
1327
+ this.legacyTree = new LegacyTree();
1328
+ }
1329
+ ngAfterViewInit() {
1330
+ this.update();
1331
+ }
1332
+ ngOnChanges() {
1333
+ if (this.host !== undefined && this.data !== undefined) {
1334
+ this.update();
1335
+ }
1336
+ }
1337
+ ngOnDestroy() {
1338
+ var _a, _b;
1339
+ (_a = this.dropSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
1340
+ (_b = this.root) === null || _b === void 0 ? void 0 : _b.destroy();
1341
+ }
1342
+ getRoot() {
1343
+ return this.root;
1344
+ }
1345
+ update() {
1346
+ var _a, _b;
1347
+ if (this.data === undefined) {
1348
+ throw new TreeError("LimbleTreeRootComponent's `data` input is required");
1349
+ }
1350
+ if (this.host === undefined) {
1351
+ throw new TreeError("LimbleTreeRootComponent's `host` property is not defined");
1352
+ }
1353
+ (_a = this.root) === null || _a === void 0 ? void 0 : _a.destroy();
1354
+ (_b = this.dropSubscription) === null || _b === void 0 ? void 0 : _b.unsubscribe();
1355
+ const dataSlice = this.paginatedData();
1356
+ this.root = this.legacyTree.createTreeFromLegacyArray(this.host, dataSlice, this.options);
1357
+ this.dropSubscription = this.root
1358
+ .events()
1359
+ .pipe(filter((event) => event instanceof DragEndEvent))
1360
+ .subscribe(this.treeDrop);
1361
+ this.treeChange.emit(this.root);
1362
+ }
1363
+ paginatedData() {
1364
+ var _a;
1365
+ assert(this.data !== undefined);
1366
+ if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.listMode) !== true) {
1367
+ return this.data;
1368
+ }
1369
+ return this.data.slice((this.page - 1) * this.itemsPerPage, this.page * this.itemsPerPage);
1370
+ }
1371
+ }
1372
+ LimbleTreeRootComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeRootComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1373
+ LimbleTreeRootComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: LimbleTreeRootComponent, isStandalone: true, selector: "limble-tree-root", inputs: { data: "data", options: "options", itemsPerPage: "itemsPerPage", page: "page" }, outputs: { treeChange: "treeChange", treeDrop: "treeDrop" }, viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div #host></div>\n" });
1374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeRootComponent, decorators: [{
1375
+ type: Component,
1376
+ args: [{ selector: "limble-tree-root", standalone: true, template: "<div #host></div>\n" }]
1377
+ }], ctorParameters: function () { return []; }, propDecorators: { data: [{
1378
+ type: Input
1379
+ }], options: [{
1380
+ type: Input
1381
+ }], itemsPerPage: [{
1382
+ type: Input
1383
+ }], page: [{
1384
+ type: Input
1385
+ }], host: [{
1386
+ type: ViewChild,
1387
+ args: ["host", { read: ViewContainerRef }]
1388
+ }], treeChange: [{
1389
+ type: Output
1390
+ }], treeDrop: [{
1391
+ type: Output
1392
+ }] } });
1393
+
1394
+ /** @deprecated */
1395
+ class LimbleTreeLegacyModule {
1396
+ }
1397
+ LimbleTreeLegacyModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1398
+ LimbleTreeLegacyModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, imports: [LimbleTreeRootComponent], exports: [LimbleTreeRootComponent] });
1399
+ LimbleTreeLegacyModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, providers: [LegacyTree], imports: [LimbleTreeRootComponent] });
1400
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeLegacyModule, decorators: [{
1401
+ type: NgModule,
1402
+ args: [{
1403
+ declarations: [],
1404
+ imports: [LimbleTreeRootComponent],
1405
+ providers: [LegacyTree],
1406
+ exports: [LimbleTreeRootComponent]
1407
+ }]
1408
+ }] });
1409
+
1410
+ class LimbleTreeModule {
1411
+ }
1412
+ LimbleTreeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1413
+ LimbleTreeModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule], exports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule] });
1414
+ LimbleTreeModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, providers: [TreeService], imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule, LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule] });
1415
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, decorators: [{
1416
+ type: NgModule,
1417
+ args: [{
1418
+ declarations: [],
1419
+ imports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule],
1420
+ providers: [TreeService],
1421
+ exports: [LimbleTreeLegacyModule, TreeCollapseModule, TreeDragAndDropModule]
1422
+ }]
1423
+ }] });
2246
1424
 
2247
- /*
2248
- * Public API Surface of limble-tree
1425
+ /*
1426
+ * Public API Surface of limble-tree
2249
1427
  */
2250
1428
 
2251
- /**
2252
- * Generated bundle index. Do not edit.
1429
+ /**
1430
+ * Generated bundle index. Do not edit.
2253
1431
  */
2254
1432
 
2255
- export { LimbleTreeModule, LimbleTreeRootComponent };
1433
+ export { DestructionEvent, DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService, config };
2256
1434
  //# sourceMappingURL=limble-limble-tree.mjs.map