@limble/limble-tree 1.0.0-alpha.2 → 1.0.0-beta.1

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 (72) hide show
  1. package/README.md +4 -0
  2. package/esm2020/lib/components/branch/branch.component.mjs +1 -1
  3. package/esm2020/lib/components/dropzone/dropzone.component.mjs +2 -2
  4. package/esm2020/lib/core/configuration/configuration.mjs +1 -1
  5. package/esm2020/lib/core/configuration/tree-options.interface.mjs +1 -1
  6. package/esm2020/lib/core/index.mjs +1 -2
  7. package/esm2020/lib/core/tree-branch/tree-branch.mjs +181 -5
  8. package/esm2020/lib/core/tree-root/tree-root.mjs +97 -2
  9. package/esm2020/lib/core/tree-service/tree.service.mjs +7 -1
  10. package/esm2020/lib/events/drag/drag-end-event.mjs +9 -7
  11. package/esm2020/lib/events/drag/drag-start-event.mjs +2 -4
  12. package/esm2020/lib/events/drag/drop-event.mjs +2 -4
  13. package/esm2020/lib/events/general/destruction-event.mjs +2 -4
  14. package/esm2020/lib/events/relational/graft-event.mjs +2 -4
  15. package/esm2020/lib/events/relational/prune-event.mjs +2 -4
  16. package/esm2020/lib/events/relational/relational-tree-event.interface.mjs +1 -1
  17. package/esm2020/lib/extras/collapse/collapse.module.mjs +2 -1
  18. package/esm2020/lib/extras/collapse/collapse.service.mjs +26 -1
  19. package/esm2020/lib/extras/drag-and-drop/drag-and-drop.module.mjs +5 -1
  20. package/esm2020/lib/extras/drag-and-drop/drag-and-drop.service.mjs +21 -5
  21. package/esm2020/lib/extras/drag-and-drop/draggable.directive.mjs +7 -7
  22. package/esm2020/lib/extras/drag-and-drop/dragover-no-change-detect.mjs +10 -11
  23. package/esm2020/lib/legacy/legacy-component-obj.interface.mjs +1 -1
  24. package/esm2020/lib/legacy/legacy-tree-data.interface.mjs +1 -1
  25. package/esm2020/lib/legacy/legacy-tree-options.interface.mjs +1 -1
  26. package/esm2020/lib/legacy/legacy-tree.mjs +3 -2
  27. package/esm2020/lib/legacy/limble-tree-root/limble-tree-root.component.mjs +1 -1
  28. package/esm2020/lib/limble-tree.module.mjs +6 -2
  29. package/esm2020/lib/structure/component-container.interface.mjs +1 -1
  30. package/esm2020/lib/structure/index.mjs +1 -2
  31. package/esm2020/lib/structure/tree-branch-node.interface.mjs +1 -1
  32. package/esm2020/lib/structure/tree-event.interface.mjs +1 -1
  33. package/esm2020/lib/structure/tree-node.interface.mjs +1 -1
  34. package/esm2020/lib/structure/tree-relationship.interface.mjs +1 -1
  35. package/fesm2015/limble-limble-tree.mjs +511 -190
  36. package/fesm2015/limble-limble-tree.mjs.map +1 -1
  37. package/fesm2020/limble-limble-tree.mjs +510 -189
  38. package/fesm2020/limble-limble-tree.mjs.map +1 -1
  39. package/lib/core/configuration/configuration.d.ts +2 -2
  40. package/lib/core/configuration/tree-options.interface.d.ts +38 -16
  41. package/lib/core/index.d.ts +0 -1
  42. package/lib/core/tree-branch/tree-branch.d.ts +183 -8
  43. package/lib/core/tree-root/tree-root.d.ts +100 -7
  44. package/lib/core/tree-service/tree.service.d.ts +8 -2
  45. package/lib/events/drag/drag-end-event.d.ts +11 -8
  46. package/lib/events/drag/drag-start-event.d.ts +6 -5
  47. package/lib/events/drag/drop-event.d.ts +6 -6
  48. package/lib/events/general/destruction-event.d.ts +5 -5
  49. package/lib/events/relational/graft-event.d.ts +5 -6
  50. package/lib/events/relational/prune-event.d.ts +5 -6
  51. package/lib/events/relational/relational-tree-event.interface.d.ts +5 -1
  52. package/lib/extras/collapse/collapse.module.d.ts +1 -0
  53. package/lib/extras/collapse/collapse.service.d.ts +25 -0
  54. package/lib/extras/drag-and-drop/drag-and-drop.module.d.ts +4 -0
  55. package/lib/extras/drag-and-drop/drag-and-drop.service.d.ts +22 -3
  56. package/lib/extras/drag-and-drop/draggable.directive.d.ts +3 -4
  57. package/lib/extras/drag-and-drop/dragover-no-change-detect.d.ts +7 -3
  58. package/lib/legacy/legacy-component-obj.interface.d.ts +1 -1
  59. package/lib/legacy/legacy-tree-data.interface.d.ts +1 -1
  60. package/lib/legacy/legacy-tree-options.interface.d.ts +2 -2
  61. package/lib/legacy/legacy-tree.d.ts +4 -4
  62. package/lib/legacy/limble-tree-root/limble-tree-root.component.d.ts +4 -4
  63. package/lib/limble-tree.module.d.ts +4 -0
  64. package/lib/structure/component-container.interface.d.ts +1 -1
  65. package/lib/structure/index.d.ts +0 -1
  66. package/lib/structure/tree-branch-node.interface.d.ts +2 -2
  67. package/lib/structure/tree-event.interface.d.ts +3 -3
  68. package/lib/structure/tree-node.interface.d.ts +11 -8
  69. package/lib/structure/tree-relationship.interface.d.ts +2 -2
  70. package/package.json +1 -1
  71. package/esm2020/lib/structure/event-conduit.interface.mjs +0 -2
  72. package/lib/structure/event-conduit.interface.d.ts +0 -6
@@ -1,9 +1,8 @@
1
1
  import * as i0 from '@angular/core';
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';
2
+ import { Injectable, NgModule, EventEmitter, Directive, Output, Component, Input, NgZone, ViewContainerRef, ViewChild, ViewChildren, createComponent, EnvironmentInjector, HostListener } from '@angular/core';
3
+ import { BehaviorSubject, fromEvent, merge, map, Subject, filter, first } from 'rxjs';
4
4
  import * as i1 from '@angular/common';
5
5
  import { CommonModule } from '@angular/common';
6
- import { throttleTime } from 'rxjs/operators';
7
6
 
8
7
  class TreeCollapser {
9
8
  constructor() {
@@ -38,13 +37,38 @@ class TreeCollapser {
38
37
  }
39
38
  const treeCollapser = new TreeCollapser();
40
39
 
40
+ /** A service that collapses and expands tree branches */
41
41
  class TreeCollapseService {
42
+ /**
43
+ * Causes a TreeBranch to collapse, temporarily pruning all of its children
44
+ * from the tree.
45
+ *
46
+ * @param treeBranch - The branch to collapse.
47
+ */
42
48
  collapse(treeBranch) {
43
49
  treeCollapser.collapse(treeBranch);
44
50
  }
51
+ /**
52
+ * Causes a TreeBranch to expand, restoring all of its children which were
53
+ * previously pruned by a call to `collapse()`.
54
+ *
55
+ * @param treeBranch - The branch to expand.
56
+ */
45
57
  expand(treeBranch) {
46
58
  treeCollapser.expand(treeBranch);
47
59
  }
60
+ /**
61
+ * Determines whether a TreeBranch currently has any children which are
62
+ * pruned from the tree due to a call to the `collapse()` method.
63
+ *
64
+ * @remarks
65
+ * Child branches which are pruned manually from the tree, rather than
66
+ * through the `collapse()` method, will not be considered.
67
+ *
68
+ * @param treeBranch - The branch to check.
69
+ *
70
+ * @returns `true` if the branch is currently collapsed; `false` if it is not.
71
+ */
48
72
  isCollapsed(treeBranch) {
49
73
  return treeCollapser.isCollapsed(treeBranch);
50
74
  }
@@ -55,6 +79,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
55
79
  type: Injectable
56
80
  }] });
57
81
 
82
+ /** A module containing the entities which provide collapse functionality */
58
83
  class TreeCollapseModule {
59
84
  }
60
85
  TreeCollapseModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeCollapseModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -67,66 +92,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
67
92
  }]
68
93
  }] });
69
94
 
70
- class Configuration {
71
- constructor() {
72
- this.configStorage = new Map();
73
- this.configStorage = new Map();
74
- }
75
- setConfig(root, options) {
76
- this.configStorage.set(root, options);
77
- }
78
- getConfig(root) {
79
- return this.configStorage.get(root);
80
- }
81
- delete(root) {
82
- this.configStorage.delete(root);
83
- }
84
- }
85
- const config = new Configuration();
86
-
87
- class TreeError extends Error {
88
- }
89
-
90
- class DragEndEvent {
91
- constructor(source, endpoints) {
92
- this._source = source;
93
- this._oldParent = endpoints.oldParent;
94
- this._oldIndex = endpoints.oldIndex;
95
- this._newParent = endpoints.newParent;
96
- this._newIndex = endpoints.newIndex;
97
- }
98
- type() {
99
- return "drag end";
100
- }
101
- source() {
102
- return this._source;
103
- }
104
- newIndex() {
105
- return this._newIndex;
106
- }
107
- newParent() {
108
- return this._newParent;
109
- }
110
- oldIndex() {
111
- return this._oldIndex;
112
- }
113
- oldParent() {
114
- return this._oldParent;
115
- }
116
- }
117
-
118
- class DragStartEvent {
119
- constructor(source) {
120
- this._source = source;
121
- }
122
- type() {
123
- return "drag start";
124
- }
125
- source() {
126
- return this._source;
127
- }
128
- }
129
-
130
95
  function assert(condition) {
131
96
  if (condition) {
132
97
  return;
@@ -179,115 +144,20 @@ class DragState {
179
144
  }
180
145
  const dragState = new DragState();
181
146
 
182
- class DropEvent {
183
- constructor(source, parent, index) {
184
- this._source = source;
185
- this._parent = parent;
186
- this._index = index;
187
- }
188
- type() {
189
- return "drag end";
190
- }
191
- source() {
192
- return this._source;
193
- }
194
- index() {
195
- return this._index;
196
- }
197
- parent() {
198
- return this._parent;
199
- }
200
- }
201
-
202
- class DragAndDrop {
203
- constructor() {
204
- this.dragAborted$ = new Subject();
205
- }
206
- dragStart(treeBranch, event) {
207
- if (!this.draggingAllowed(treeBranch)) {
208
- event.preventDefault();
209
- return;
210
- }
211
- treeBranch.dispatch(new DragStartEvent(treeBranch));
212
- this.setDragEffects(treeBranch, event);
213
- this.watchForDragend(treeBranch, event);
214
- // We have to do a setTimeout because DOM changes are not allowed during a
215
- // dragstart event.
216
- setTimeout(() => {
217
- dragState.starting(treeBranch);
218
- treeBranch.prune();
219
- dragState.dragging();
220
- });
221
- }
222
- drop(parent, index) {
223
- const treeBranch = dragState.getDragData();
224
- if (treeBranch === undefined) {
225
- throw new TreeError("Cannot get dragged branch");
226
- }
227
- this.graftDraggedBranch(treeBranch, parent, index);
228
- treeBranch.dispatch(new DropEvent(treeBranch, parent, index));
229
- }
230
- getDragImageOffsets(event, element) {
231
- const bounds = element.getBoundingClientRect();
232
- const xOffset = event.clientX - bounds.left;
233
- const yOffset = event.clientY - bounds.top;
234
- return [xOffset, yOffset];
235
- }
236
- setDragEffects(treeBranch, event) {
237
- const dataTransfer = event.dataTransfer;
238
- assert(dataTransfer instanceof DataTransfer);
239
- const nativeElement = treeBranch.getNativeElement();
240
- const [xOffset, yOffset] = this.getDragImageOffsets(event, nativeElement);
241
- dataTransfer.setDragImage(nativeElement, xOffset, yOffset);
242
- }
243
- watchForDragend(treeBranch, event) {
244
- const oldParent = treeBranch.parent();
245
- const oldIndex = treeBranch.index();
246
- assert(oldParent !== undefined && oldIndex !== undefined);
247
- event.target?.addEventListener("dragend", (dragend) => {
248
- if (dragState.state() !== DragStates.Dropped) {
249
- //The drag ended but a drop never occurred, so put the dragged branch back where it started.
250
- this.dragAborted$.next(dragend);
251
- this.graftDraggedBranch(treeBranch, oldParent, oldIndex);
252
- }
253
- dragState.restart();
254
- const newParent = treeBranch.parent();
255
- assert(newParent !== undefined);
256
- const newIndex = treeBranch.index();
257
- assert(newIndex !== undefined);
258
- treeBranch.dispatch(new DragEndEvent(treeBranch, {
259
- oldParent,
260
- oldIndex,
261
- newParent,
262
- newIndex
263
- }));
264
- }, { once: true });
265
- }
266
- draggingAllowed(treeBranch) {
267
- const allowDragging = config.getConfig(treeBranch.root())?.dragAndDrop?.allowDragging ??
268
- (() => true);
269
- return allowDragging(treeBranch);
270
- }
271
- graftDraggedBranch(treeBranch, parent, index) {
272
- treeBranch.graftTo(parent, index);
273
- treeBranch.getNativeElement().style.display = "block";
274
- dragState.dropped();
275
- }
276
- }
277
- const dragAndDrop = new DragAndDrop();
278
-
147
+ /**
148
+ * Works just like Angular's built-in `(dragover)` event binding, but is much
149
+ * more performant. It throttles the event to a configurable rate (default once
150
+ * every 25ms) and runs outside of Angular's change detection.
151
+ */
279
152
  class DragoverNoChangeDetectDirective {
280
153
  constructor(ngZone, el) {
281
154
  this.ngZone = ngZone;
282
155
  this.el = el;
283
156
  this.dragoverNoChangeDetect = new EventEmitter();
284
- this.dragoverEventThrottle = 25;
285
157
  }
286
158
  ngOnInit() {
287
159
  this.ngZone.runOutsideAngular(() => {
288
- this.eventSubscription = fromEvent(this.el.nativeElement, "dragover")
289
- .pipe(throttleTime(this.dragoverEventThrottle))
290
- .subscribe(($event) => {
160
+ this.eventSubscription = fromEvent(this.el.nativeElement, "dragover").subscribe(($event) => {
291
161
  this.dragoverNoChangeDetect.emit($event);
292
162
  });
293
163
  });
@@ -299,16 +169,14 @@ class DragoverNoChangeDetectDirective {
299
169
  }
300
170
  }
301
171
  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 });
302
- 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 });
172
+ DragoverNoChangeDetectDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: DragoverNoChangeDetectDirective, isStandalone: true, selector: "[dragoverNoChangeDetect]", outputs: { dragoverNoChangeDetect: "dragoverNoChangeDetect" }, ngImport: i0 });
303
173
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DragoverNoChangeDetectDirective, decorators: [{
304
174
  type: Directive,
305
175
  args: [{
306
176
  standalone: true,
307
177
  selector: "[dragoverNoChangeDetect]"
308
178
  }]
309
- }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { dragoverEventThrottle: [{
310
- type: Input
311
- }], dragoverNoChangeDetect: [{
179
+ }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ElementRef }]; }, propDecorators: { dragoverNoChangeDetect: [{
312
180
  type: Output
313
181
  }] } });
314
182
 
@@ -332,10 +200,10 @@ class DropzoneComponent {
332
200
  }
333
201
  }
334
202
  DropzoneComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
335
- 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"] }] });
203
+ 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:36px;margin:8px 0;transition:height .3s ease-out;animation:animation .3s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:72px}@keyframes animation{0%{height:0px;opacity:0}to{height:36px;opacity:1}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: DragoverNoChangeDetectDirective, selector: "[dragoverNoChangeDetect]", outputs: ["dragoverNoChangeDetect"] }] });
336
204
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DropzoneComponent, decorators: [{
337
205
  type: Component,
338
- 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"] }]
206
+ 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:36px;margin:8px 0;transition:height .3s ease-out;animation:animation .3s ease-out}.dropzone.active{border-color:#289e49;border-width:2px;background-color:#d0e8d6;height:72px}@keyframes animation{0%{height:0px;opacity:0}to{height:36px;opacity:1}}\n"] }]
339
207
  }], propDecorators: { placement: [{
340
208
  type: Input
341
209
  }], dropped: [{
@@ -391,7 +259,7 @@ class BranchComponent {
391
259
  }
392
260
  }
393
261
  BranchComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, deps: [{ token: i0.ApplicationRef }], target: i0.ɵɵFactoryTarget.Component });
394
- 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"] }] });
262
+ 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]", outputs: ["dragoverNoChangeDetect"] }] });
395
263
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BranchComponent, decorators: [{
396
264
  type: Component,
397
265
  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"] }]
@@ -414,6 +282,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
414
282
  type: Output
415
283
  }] } });
416
284
 
285
+ class Configuration {
286
+ constructor() {
287
+ this.configStorage = new Map();
288
+ this.configStorage = new Map();
289
+ }
290
+ setConfig(root, options) {
291
+ this.configStorage.set(root, options);
292
+ }
293
+ getConfig(root) {
294
+ return this.configStorage.get(root);
295
+ }
296
+ delete(root) {
297
+ this.configStorage.delete(root);
298
+ }
299
+ }
300
+ const config = new Configuration();
301
+
302
+ class TreeError extends Error {
303
+ }
304
+
305
+ /** Emitted when a drag-and-drop operation has completed */
306
+ class DragEndEvent {
307
+ constructor(source, endpoints) {
308
+ this._source = source;
309
+ this._oldParent = endpoints.oldParent;
310
+ this._oldIndex = endpoints.oldIndex;
311
+ this._newParent = endpoints.newParent;
312
+ this._newIndex = endpoints.newIndex;
313
+ }
314
+ /** @returns The new index of the dropped branch */
315
+ newIndex() {
316
+ return this._newIndex;
317
+ }
318
+ /** @returns The new parent of the dropped branch */
319
+ newParent() {
320
+ return this._newParent;
321
+ }
322
+ /** @returns The index of the dropped branch before it was dragged */
323
+ oldIndex() {
324
+ return this._oldIndex;
325
+ }
326
+ /** @returns The parent of the dropped branch before it was dragged */
327
+ oldParent() {
328
+ return this._oldParent;
329
+ }
330
+ source() {
331
+ return this._source;
332
+ }
333
+ }
334
+
335
+ /** Emitted when a TreeBranch begins being dragged */
336
+ class DragStartEvent {
337
+ constructor(source) {
338
+ this._source = source;
339
+ }
340
+ source() {
341
+ return this._source;
342
+ }
343
+ }
344
+
345
+ /** Emitted when a TreeBranch is dropped into a valid Dropzone */
346
+ class DropEvent {
347
+ constructor(source, parent, index) {
348
+ this._source = source;
349
+ this._parent = parent;
350
+ this._index = index;
351
+ }
352
+ source() {
353
+ return this._source;
354
+ }
355
+ index() {
356
+ return this._index;
357
+ }
358
+ parent() {
359
+ return this._parent;
360
+ }
361
+ }
362
+
363
+ class DragAndDrop {
364
+ constructor() {
365
+ this.dragAborted$ = new Subject();
366
+ }
367
+ dragStart(treeBranch, event) {
368
+ if (!this.draggingAllowed(treeBranch)) {
369
+ event.preventDefault();
370
+ return;
371
+ }
372
+ treeBranch.dispatch(new DragStartEvent(treeBranch));
373
+ this.setDragEffects(treeBranch, event);
374
+ this.watchForDragend(treeBranch, event);
375
+ // We have to do a setTimeout because DOM changes are not allowed during a
376
+ // dragstart event.
377
+ setTimeout(() => {
378
+ dragState.starting(treeBranch);
379
+ treeBranch.prune();
380
+ dragState.dragging();
381
+ });
382
+ }
383
+ drop(parent, index) {
384
+ const treeBranch = dragState.getDragData();
385
+ if (treeBranch === undefined) {
386
+ throw new TreeError("Cannot get dragged branch");
387
+ }
388
+ this.graftDraggedBranch(treeBranch, parent, index);
389
+ treeBranch.dispatch(new DropEvent(treeBranch, parent, index));
390
+ }
391
+ getDragImageOffsets(event, element) {
392
+ const bounds = element.getBoundingClientRect();
393
+ const xOffset = event.clientX - bounds.left;
394
+ const yOffset = event.clientY - bounds.top;
395
+ return [xOffset, yOffset];
396
+ }
397
+ setDragEffects(treeBranch, event) {
398
+ const dataTransfer = event.dataTransfer;
399
+ assert(dataTransfer instanceof DataTransfer);
400
+ const nativeElement = treeBranch.getNativeElement();
401
+ const [xOffset, yOffset] = this.getDragImageOffsets(event, nativeElement);
402
+ dataTransfer.setDragImage(nativeElement, xOffset, yOffset);
403
+ }
404
+ watchForDragend(treeBranch, event) {
405
+ const oldParent = treeBranch.parent();
406
+ const oldIndex = treeBranch.index();
407
+ assert(oldParent !== undefined && oldIndex !== undefined);
408
+ event.target?.addEventListener("dragend", (dragend) => {
409
+ if (dragState.state() !== DragStates.Dropped) {
410
+ //The drag ended but a drop never occurred, so put the dragged branch back where it started.
411
+ this.dragAborted$.next(dragend);
412
+ this.graftDraggedBranch(treeBranch, oldParent, oldIndex);
413
+ }
414
+ dragState.restart();
415
+ const newParent = treeBranch.parent();
416
+ assert(newParent !== undefined);
417
+ const newIndex = treeBranch.index();
418
+ assert(newIndex !== undefined);
419
+ treeBranch.dispatch(new DragEndEvent(treeBranch, {
420
+ oldParent,
421
+ oldIndex,
422
+ newParent,
423
+ newIndex
424
+ }));
425
+ }, { once: true });
426
+ }
427
+ draggingAllowed(treeBranch) {
428
+ const allowDragging = config.getConfig(treeBranch.root())?.dragAndDrop?.allowDragging ??
429
+ (() => true);
430
+ return allowDragging(treeBranch);
431
+ }
432
+ graftDraggedBranch(treeBranch, parent, index) {
433
+ treeBranch.graftTo(parent, index);
434
+ treeBranch.getNativeElement().style.display = "block";
435
+ dragState.dropped();
436
+ }
437
+ }
438
+ const dragAndDrop = new DragAndDrop();
439
+
440
+ /** Emits when a branch is grafted to another tree node */
417
441
  class GraftEvent {
418
442
  constructor(source, relationship) {
419
443
  this._source = source;
@@ -424,9 +448,6 @@ class GraftEvent {
424
448
  child() {
425
449
  return this._child;
426
450
  }
427
- type() {
428
- return "graft";
429
- }
430
451
  index() {
431
452
  return this._index;
432
453
  }
@@ -438,6 +459,7 @@ class GraftEvent {
438
459
  }
439
460
  }
440
461
 
462
+ /** Emitted when a branch is pruned from its parent branch */
441
463
  class PruneEvent {
442
464
  constructor(source, relationship) {
443
465
  this._source = source;
@@ -448,9 +470,6 @@ class PruneEvent {
448
470
  child() {
449
471
  return this._child;
450
472
  }
451
- type() {
452
- return "prune";
453
- }
454
473
  index() {
455
474
  return this._index;
456
475
  }
@@ -527,13 +546,11 @@ class TreeNodeBase {
527
546
  }
528
547
  }
529
548
 
549
+ /** Emitted when a node is destroyed */
530
550
  class DestructionEvent {
531
551
  constructor(source) {
532
552
  this._source = source;
533
553
  }
534
- type() {
535
- return "destruction";
536
- }
537
554
  source() {
538
555
  return this._source;
539
556
  }
@@ -609,6 +626,11 @@ class RootController {
609
626
  }
610
627
  }
611
628
 
629
+ /**
630
+ * Represents the base of the tree. It renders a very simple container for child
631
+ * branches. It has methods for creating and accessing those branches. It emits
632
+ * events when things happen in the tree.
633
+ */
612
634
  class TreeRoot {
613
635
  constructor(viewContainerRef) {
614
636
  this.viewContainerRef = viewContainerRef;
@@ -616,9 +638,19 @@ class TreeRoot {
616
638
  this.rootController = new RootController(this, viewContainerRef);
617
639
  this.detectChanges();
618
640
  }
641
+ /** @returns All child branches as an array of TreeBranch instances */
619
642
  branches() {
620
643
  return this.treeNodeBase.branches();
621
644
  }
645
+ /**
646
+ * Recursively destroys all branches of the tree, as well as itself.
647
+ *
648
+ * @remarks
649
+ * This releases all resources held or consumed by the tree.
650
+ *
651
+ * It is important to call this method when a tree is discarded, otherwise
652
+ * the tree will remain in memory and continue to consume resources.
653
+ */
622
654
  destroy() {
623
655
  if (this.isDestroyed()) {
624
656
  throw new TreeError("Cannot destroy a destroyed tree root");
@@ -630,64 +662,150 @@ class TreeRoot {
630
662
  config.delete(this);
631
663
  this.dispatch(new DestructionEvent(this));
632
664
  }
665
+ /** Run Angular change detection on the root of the tree */
633
666
  detectChanges() {
634
667
  this.rootController.detectChanges();
635
668
  }
669
+ /**
670
+ * Emits the specified TreeEvent.
671
+ *
672
+ * @remarks
673
+ * Caution: It is not recommended to manually emit TreeEvents that are already
674
+ * provided by the library. For example, it is not recommended to emit a
675
+ * `GraftEvent`, `DestructionEvent`, etc. These events may be used by the tree,
676
+ * and emitting them manually may cause unexpected behavior. Instead, we
677
+ * recommend implementing the TreeEvent interface with your own custom events
678
+ * and dispatching those.
679
+ *
680
+ * @param event - The TreeEvent that will be emitted.
681
+ */
636
682
  dispatch(event) {
637
683
  this.treeNodeBase.dispatch(event);
638
684
  }
685
+ /**
686
+ * @returns
687
+ * An observable that emits TreeEvents whenever an event is dispatched
688
+ * in the root or any of its descendant branches.
689
+ */
639
690
  events() {
640
691
  return this.treeNodeBase.events();
641
692
  }
693
+ /**
694
+ * @returns
695
+ * The child branch at the specified index, or undefined if there is
696
+ * no child branch at the specified index.
697
+ */
642
698
  getBranch(index) {
643
699
  return this.treeNodeBase.getBranch(index);
644
700
  }
701
+ /** @returns The ViewContainerRef in which child branches are rendered */
645
702
  getBranchesContainer() {
646
703
  if (this.isDestroyed()) {
647
704
  throw new TreeError("Cannot get branches container from a destroyed tree root");
648
705
  }
649
706
  return this.rootController.getBranchesContainer();
650
707
  }
708
+ /**
709
+ * Retrieves the RootComponent.
710
+ *
711
+ * @remarks
712
+ * The RootComponent holds the BranchesContainer, as well as a single Dropzone
713
+ * for drag-and-drop operations.
714
+ *
715
+ * @returns The instance of RootComponent that is rendered by this class.
716
+ */
651
717
  getComponentInstance() {
652
718
  if (this.isDestroyed()) {
653
719
  throw new TreeError("Cannot get component instance from a destroyed tree root");
654
720
  }
655
721
  return this.rootController.getComponentInstance();
656
722
  }
723
+ /** @returns The Host View in which the RootComponent is rendered */
657
724
  getHostView() {
658
725
  if (this.isDestroyed()) {
659
726
  throw new TreeError("Cannot get component host view from a destroyed tree root");
660
727
  }
661
728
  return this.rootController.getHostView();
662
729
  }
730
+ /** @returns The RootComponent as a native HTML Element */
663
731
  getNativeElement() {
664
732
  if (this.isDestroyed()) {
665
733
  throw new TreeError("Cannot get native element from a destroyed tree root");
666
734
  }
667
735
  return this.rootController.getNativeElement();
668
736
  }
737
+ /**
738
+ * Appends a new child branch to this branch. The child branch will render
739
+ * the specified component according to the (optional) configuration parameter.
740
+ *
741
+ * @param component - The component to render in the new child branch.
742
+ * @param options - Configuration options for the new child branch.
743
+ *
744
+ * @returns
745
+ * The newly-created child branch.
746
+ */
669
747
  grow(component, options) {
670
748
  if (this.isDestroyed()) {
671
749
  throw new TreeError("Cannot grow a branch on a destroyed tree root");
672
750
  }
673
751
  return new TreeBranch(this, { component, ...options });
674
752
  }
753
+ /** @returns `true` if the tree is destroyed, `false` otherwise */
675
754
  isDestroyed() {
676
755
  return this.treeNodeBase.isDestroyed();
677
756
  }
757
+ /**
758
+ * Provides a model describing the shape of the tree.
759
+ *
760
+ * @returns A multi-dimensional Map which describes the shape of the tree.
761
+ *
762
+ * @example
763
+ * For example, an empty tree will return an empty Map. A tree with a single
764
+ * branch will return a Map with a single entry, where the key is the index
765
+ * of the branch (zero) and the value is an empty Map. A Tree like this:
766
+ *
767
+ * ```
768
+ * ---Branch-------Branch
769
+ * /
770
+ * Root-------Branch
771
+ * \
772
+ * ---Branch
773
+ * ```
774
+ * Will return a Map of matching shape:
775
+ * ```
776
+ * Map {
777
+ * 0: Map { 0: Map {}},
778
+ * 1: Map {},
779
+ * 2: Map {}
780
+ * }
781
+ * ```
782
+ */
678
783
  plot() {
679
784
  return this.treeNodeBase.plot();
680
785
  }
786
+ /** @returns Itself */
681
787
  root() {
682
788
  return this;
683
789
  }
790
+ /**
791
+ * Traverses the tree in depth-first pre-order, executing the provided
792
+ * callback function on each node. Traversal includes the Root.
793
+ *
794
+ * @param callback - A function to execute on each node.
795
+ */
684
796
  traverse(callback) {
685
797
  callback(this);
686
798
  this.treeNodeBase.traverse(callback);
687
799
  }
688
800
  }
689
801
 
802
+ /** Responsible for the creation of new trees. */
690
803
  class TreeService {
804
+ /**
805
+ * Creates a new, empty tree structure inside the provided container.
806
+ *
807
+ * @returns A `TreeRoot` representing the base of the new tree.
808
+ */
691
809
  createEmptyTree(container, options = {}) {
692
810
  container.clear();
693
811
  const root = new TreeRoot(container);
@@ -796,6 +914,15 @@ class BranchController {
796
914
  }
797
915
  }
798
916
 
917
+ /** Represents a standard node in a tree. Renders a BranchComponent.
918
+ *
919
+ * @remarks
920
+ * This class renders a branch component, which does the following:
921
+ * 1. Renders a component provided by the user
922
+ * 2. Provides a container in which child branches may be rendered
923
+ * 3. Contains two Dropzones: one for dropping branches below this branch (as a
924
+ * sibling), and one for dropping branches as a first child of this branch.
925
+ */
799
926
  class TreeBranch {
800
927
  constructor(parent, branchOptions) {
801
928
  this.branchOptions = branchOptions;
@@ -821,9 +948,18 @@ class TreeBranch {
821
948
  }));
822
949
  }
823
950
  }
951
+ /** @returns All child branches as an array of TreeBranch instances, in order. */
824
952
  branches() {
825
953
  return this.treeNodeBase.branches();
826
954
  }
955
+ /**
956
+ * Recursively destroys all descendant branches, as well as itself. This
957
+ * releases all resources held or consumed by this branch and its descendants.
958
+ *
959
+ * @remarks
960
+ * It is important to call this method when a branch is discarded, otherwise
961
+ * the branch will remain in memory and continue to consume resources.
962
+ */
827
963
  destroy() {
828
964
  if (this.isDestroyed()) {
829
965
  throw new TreeError("Cannot destroy a destroyed tree branch");
@@ -836,49 +972,101 @@ class TreeBranch {
836
972
  this.branchController.destroy();
837
973
  this.dispatch(new DestructionEvent(this));
838
974
  }
975
+ /** Run Angular change detection on this branch */
839
976
  detectChanges() {
840
977
  this.branchController.detectChanges();
841
978
  }
979
+ /**
980
+ * Emits the specified TreeEvent.
981
+ *
982
+ * @remarks
983
+ * Caution: It is not recommended to manually emit TreeEvents that are already
984
+ * provided by the library. For example, it is not recommended to emit a
985
+ * `GraftEvent`, `DestructionEvent`, etc. These events may be used by the tree,
986
+ * and emitting them manually may cause unexpected behavior. Instead, we
987
+ * recommend implementing the TreeEvent interface with your own custom events
988
+ * and dispatching those.
989
+ *
990
+ * @param event - The TreeEvent that will be emitted.
991
+ */
842
992
  dispatch(event) {
843
993
  this.treeNodeBase.dispatch(event);
844
994
  this._parent?.dispatch(event);
845
995
  }
996
+ /**
997
+ * @returns
998
+ * An observable that emits TreeEvents whenever an event is dispatched
999
+ * in this branch or any of its descendant branches.
1000
+ */
846
1001
  events() {
847
1002
  return this.treeNodeBase.events();
848
1003
  }
1004
+ /**
1005
+ * @param index - The index of the child branch to retrieve.
1006
+ *
1007
+ * @returns
1008
+ * The child branch at the specified index, or undefined if there is
1009
+ * no child branch at the specified index.
1010
+ */
849
1011
  getBranch(index) {
850
1012
  return this.treeNodeBase.getBranch(index);
851
1013
  }
1014
+ /** @returns The ViewContainerRef in which child branches are rendered */
852
1015
  getBranchesContainer() {
853
1016
  if (this.isDestroyed()) {
854
1017
  throw new TreeError("Cannot get branches container from a destroyed tree branch");
855
1018
  }
856
1019
  return this.branchController.getBranchesContainer();
857
1020
  }
1021
+ /** @returns The instance of BranchComponent that is rendered by this class. */
858
1022
  getComponentInstance() {
859
1023
  if (this.isDestroyed()) {
860
1024
  throw new TreeError("Cannot get component instance from a destroyed tree branch");
861
1025
  }
862
1026
  return this.branchController.getComponentInstance();
863
1027
  }
1028
+ /** @returns The Host View in which the BranchComponent is rendered */
864
1029
  getHostView() {
865
1030
  if (this.isDestroyed()) {
866
1031
  throw new TreeError("Cannot get component host view from a destroyed tree branch");
867
1032
  }
868
1033
  return this.branchController.getHostView();
869
1034
  }
1035
+ /** @returns The BranchComponent as a native HTML Element */
870
1036
  getNativeElement() {
871
1037
  if (this.isDestroyed()) {
872
1038
  throw new TreeError("Cannot get native element from a destroyed tree branch");
873
1039
  }
874
1040
  return this.branchController.getNativeElement();
875
1041
  }
1042
+ /**
1043
+ * @returns
1044
+ * A ComponentRef containing the instance of the user-provided
1045
+ * component which is rendered by this branch.
1046
+ */
876
1047
  getUserlandComponentRef() {
877
1048
  if (this.isDestroyed()) {
878
1049
  throw new TreeError("Cannot get userland component from a destroyed tree branch");
879
1050
  }
880
1051
  return this.branchController.getUserlandComponentRef();
881
1052
  }
1053
+ /**
1054
+ * Attaches a branch to a new parent node.
1055
+ *
1056
+ * @remarks
1057
+ * If not already pruned, this method prunes (removes) this branch from its
1058
+ * current position in the tree; then grafts (reattaches) it as a child of the
1059
+ * specified parent branch at the specified index. If no index is specified,
1060
+ * the branch is appended as the last child of the parent. This causes this
1061
+ * branch's associated BranchComponent to be re-rendered in the DOM at the
1062
+ * new location.
1063
+ *
1064
+ * @param newParent - The new parent branch unto which this branch will be grafted.
1065
+ * @param index - The index at which this branch will be grafted. If not specified,
1066
+ * this branch will be appended as the last child of the new parent.
1067
+ *
1068
+ * @returns The index at which this branch was grafted.
1069
+ */
882
1070
  graftTo(newParent, index) {
883
1071
  this.checkGraftLocationValidity(newParent, index);
884
1072
  const ownIndex = this.index();
@@ -895,12 +1083,35 @@ class TreeBranch {
895
1083
  }));
896
1084
  return newIndex;
897
1085
  }
1086
+ /**
1087
+ * Appends a new child branch to this branch. The child branch will render
1088
+ * the specified component according to the (optional) configuration parameter.
1089
+ *
1090
+ * @param component - The component to render in the new child branch.
1091
+ * @param options - Configuration options for the new child branch.
1092
+ *
1093
+ * @returns
1094
+ * The newly-created child branch.
1095
+ */
898
1096
  grow(component, options) {
899
1097
  if (this.isDestroyed()) {
900
1098
  throw new TreeError("Cannot grow a branch on a destroyed tree branch");
901
1099
  }
902
1100
  return new TreeBranch(this, { component, ...options });
903
1101
  }
1102
+ /**
1103
+ * Determines this branch's index in relation to its sibling branches.
1104
+ *
1105
+ * @remarks
1106
+ * For example, if it is the first child of its parent, this method will return
1107
+ * 0. If it is the second child of its parent, this method will return 1.
1108
+ *
1109
+ * If this branch has no parent, (eg, if this branch has been pruned) this
1110
+ * method will return undefined.
1111
+ *
1112
+ * @returns
1113
+ * The index of this branch in relation to its sibling branches, or undefined.
1114
+ */
904
1115
  index() {
905
1116
  if (!this._parent) {
906
1117
  return undefined;
@@ -911,18 +1122,76 @@ class TreeBranch {
911
1122
  assert(index >= 0);
912
1123
  return index;
913
1124
  }
1125
+ /** @returns `true` if the branch is destroyed, `false` otherwise */
914
1126
  isDestroyed() {
915
1127
  return this.treeNodeBase.isDestroyed();
916
1128
  }
1129
+ /**
1130
+ * @returns
1131
+ * The data that was passed into the `branchOptions`' `meta` property
1132
+ * at construction.
1133
+ */
917
1134
  meta() {
918
1135
  return this.branchOptions.meta ?? {};
919
1136
  }
1137
+ /**
1138
+ * @returns
1139
+ * This branch's parent node (which may be a TreeBranch or TreeRoot).
1140
+ * If this branch has no parent, (eg, if this branch has been pruned) this
1141
+ * method will return undefined.
1142
+ */
920
1143
  parent() {
921
1144
  return this._parent;
922
1145
  }
1146
+ /**
1147
+ * Provides a model describing this branch's descendants.
1148
+ *
1149
+ * @returns
1150
+ * A multi-dimensional Map which describes the shape of this branch's
1151
+ * descendants.
1152
+ *
1153
+ * @example
1154
+ * A branch with no children will return an empty Map. A branch with
1155
+ * a single child will return a Map with a single entry, where the key is the index
1156
+ * of the branch (zero) and the value is an empty Map. A Tree like this:
1157
+ *
1158
+ * ```
1159
+ * ---Branch-------Branch
1160
+ * /
1161
+ * Branch-------Branch
1162
+ * \
1163
+ * ---Branch
1164
+ * ```
1165
+ * Will return a Map of matching shape:
1166
+ * ```
1167
+ * Map {
1168
+ * 0: Map { 0: Map {}},
1169
+ * 1: Map {},
1170
+ * 2: Map {}
1171
+ * }
1172
+ * ```
1173
+ */
923
1174
  plot() {
924
1175
  return this.treeNodeBase.plot();
925
1176
  }
1177
+ /**
1178
+ * Calculates the branch's position in the tree relative to the Root.
1179
+ *
1180
+ * @remarks
1181
+ * The position is described as an array of numbers, where each number
1182
+ * represents the index of the branch at that level of the tree.
1183
+ *
1184
+ * For example, if this branch is the first child of the Root, this method
1185
+ * will return [0]. If this branch is the second child of the first child
1186
+ * of the Root, this method will return [0, 1].
1187
+ *
1188
+ * If the branch is not related to a TreeRoot, (such as when it has been
1189
+ * pruned,) this method will throw an error.
1190
+ *
1191
+ * @returns
1192
+ * An array of numbers which describe the branch's position in the tree
1193
+ * relative to the Root.
1194
+ */
926
1195
  position() {
927
1196
  const index = this.index();
928
1197
  if (index === undefined) {
@@ -934,6 +1203,19 @@ class TreeBranch {
934
1203
  }
935
1204
  return [index];
936
1205
  }
1206
+ /**
1207
+ * Removes a branch from its tree without destroying it.
1208
+ *
1209
+ * @remarks
1210
+ * Removes this branch from its parent and detaches its associated
1211
+ * BranchComponent from the DOM. This puts the branch in a "pruned" state,
1212
+ * which may affect the behavior of other methods.
1213
+ *
1214
+ * A pruned branch can be reattached to any other node using the `graftTo` method.
1215
+ *
1216
+ * @returns
1217
+ * Itself, or undefined if it is already in a pruned state.
1218
+ */
937
1219
  prune() {
938
1220
  if (this.isDestroyed()) {
939
1221
  throw new TreeError("Cannot prune a destroyed tree branch");
@@ -955,6 +1237,14 @@ class TreeBranch {
955
1237
  this._parent = undefined;
956
1238
  return this;
957
1239
  }
1240
+ /**
1241
+ * Get the root of the tree to which this Branch is attached.
1242
+ *
1243
+ * @returns
1244
+ * The TreeRoot of the tree this branch is in. If this branch is
1245
+ * does not have a root (such as when it has been pruned) this method will
1246
+ * return undefined.
1247
+ */
958
1248
  root() {
959
1249
  const parent = this.parent();
960
1250
  if (parent instanceof TreeBranch) {
@@ -963,6 +1253,12 @@ class TreeBranch {
963
1253
  assert(parent instanceof TreeRoot || parent === undefined);
964
1254
  return parent;
965
1255
  }
1256
+ /**
1257
+ * Traverses this branch's descendants in depth-first pre-order, executing
1258
+ * the provided callback function on each node. Traversal includes this branch.
1259
+ *
1260
+ * @param callback - A function to execute on each node.
1261
+ */
966
1262
  traverse(callback) {
967
1263
  callback(this);
968
1264
  this.treeNodeBase.traverse(callback);
@@ -1179,18 +1475,35 @@ class DropzoneRenderer {
1179
1475
  const dropzoneRenderer = new DropzoneRenderer();
1180
1476
 
1181
1477
  class TreeDragAndDropService {
1478
+ /** Hides all Dropzones */
1182
1479
  clearDropzones() {
1183
1480
  dropzoneRenderer.clearCurrentDisplay();
1184
1481
  }
1185
- dragStart(treeBranch, event) {
1186
- dragAndDrop.dragStart(treeBranch, event);
1187
- }
1482
+ /**
1483
+ * @returns An object that indicates which dropzones are currently being displayed.
1484
+ * If no dropzones are being displayed, then null is returned.
1485
+ */
1188
1486
  getCurrentlyDisplayedDropzoneFamily() {
1189
1487
  return dropzoneRenderer.getCurrentDisplay();
1190
1488
  }
1489
+ /**
1490
+ * Causes the dropzone of the TreeRoot to be displayed.
1491
+ *
1492
+ * @remarks
1493
+ * This is a useful function when you want to show the dropzone of a TreeRoot
1494
+ * that has no child branches.
1495
+ *
1496
+ * @param root - The TreeRoot whose dropzone you want to show.
1497
+ */
1191
1498
  showRootDropzone(root) {
1192
1499
  dropzoneRenderer.showLowerZones(root);
1193
1500
  }
1501
+ /**
1502
+ * @returns An observable that emits a number whenever the drag state changes.
1503
+ *
1504
+ * @remarks
1505
+ * See the `DragStates` enum for a list of possible states.
1506
+ */
1194
1507
  state() {
1195
1508
  return dragState.events();
1196
1509
  }
@@ -1201,19 +1514,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
1201
1514
  type: Injectable
1202
1515
  }] });
1203
1516
 
1517
+ /** Makes an TreeBranch draggable when the host element is dragged */
1204
1518
  class DraggableDirective {
1205
- constructor(dragAndDropService, renderer, hostElement) {
1206
- this.dragAndDropService = dragAndDropService;
1519
+ constructor(renderer, hostElement) {
1207
1520
  renderer.setAttribute(hostElement.nativeElement, "draggable", "true");
1208
1521
  renderer.setStyle(hostElement.nativeElement, "cursor", "grab");
1209
1522
  }
1210
1523
  onDragstart(event) {
1211
1524
  if (this.limbleTreeDraggable === undefined)
1212
1525
  return;
1213
- this.dragAndDropService.dragStart(this.limbleTreeDraggable, event);
1526
+ dragAndDrop.dragStart(this.limbleTreeDraggable, event);
1214
1527
  }
1215
1528
  }
1216
- 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 });
1529
+ DraggableDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1217
1530
  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 });
1218
1531
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: DraggableDirective, decorators: [{
1219
1532
  type: Directive,
@@ -1221,13 +1534,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
1221
1534
  selector: "[limbleTreeDraggable]",
1222
1535
  standalone: true
1223
1536
  }]
1224
- }], ctorParameters: function () { return [{ type: TreeDragAndDropService }, { type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { limbleTreeDraggable: [{
1537
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }]; }, propDecorators: { limbleTreeDraggable: [{
1225
1538
  type: Input
1226
1539
  }], onDragstart: [{
1227
1540
  type: HostListener,
1228
1541
  args: ["dragstart", ["$event"]]
1229
1542
  }] } });
1230
1543
 
1544
+ /**
1545
+ * An Angular module containing all of the entities which provide Drag-And-Drop
1546
+ * functionality.
1547
+ */
1231
1548
  class TreeDragAndDropModule {
1232
1549
  }
1233
1550
  TreeDragAndDropModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TreeDragAndDropModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -1399,6 +1716,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
1399
1716
  }]
1400
1717
  }] });
1401
1718
 
1719
+ /**
1720
+ * Import this Angular module into your application to gain access to the
1721
+ * components, directives, and services provided by Limble Tree.
1722
+ */
1402
1723
  class LimbleTreeModule {
1403
1724
  }
1404
1725
  LimbleTreeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: LimbleTreeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -1422,5 +1743,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
1422
1743
  * Generated bundle index. Do not edit.
1423
1744
  */
1424
1745
 
1425
- export { DestructionEvent, DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService, config };
1746
+ export { DestructionEvent, DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService };
1426
1747
  //# sourceMappingURL=limble-limble-tree.mjs.map