@limble/limble-tree 1.0.0-alpha.1 → 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.
- package/README.md +446 -17
- package/esm2020/lib/components/branch/branch.component.mjs +6 -14
- package/esm2020/lib/components/root/root.component.mjs +3 -4
- package/esm2020/lib/core/branch-options.interface.mjs +1 -1
- package/esm2020/lib/core/configuration/tree-options.interface.mjs +1 -1
- package/esm2020/lib/core/relationship.interface.mjs +1 -1
- package/esm2020/lib/core/tree-branch/branch-controller.mjs +99 -0
- package/esm2020/lib/core/tree-branch/tree-branch.mjs +81 -103
- package/esm2020/lib/core/tree-node-base.mjs +10 -9
- package/esm2020/lib/core/tree-root/root-controller.mjs +42 -0
- package/esm2020/lib/core/tree-root/tree-root.mjs +43 -27
- package/esm2020/lib/events/drag/drag-end-event.mjs +1 -1
- package/esm2020/lib/events/drag/drop-event.mjs +1 -1
- package/esm2020/lib/events/general/destruction-event.mjs +12 -0
- package/esm2020/lib/events/general/index.mjs +2 -0
- package/esm2020/lib/events/index.mjs +2 -1
- package/esm2020/lib/extras/collapse/collapse.mjs +2 -2
- package/esm2020/lib/extras/drag-and-drop/drag-and-drop.mjs +6 -10
- package/esm2020/lib/extras/drag-and-drop/draggable.directive.mjs +1 -1
- package/esm2020/lib/extras/drag-and-drop/dropzone-renderer.mjs +9 -7
- package/esm2020/lib/legacy/legacy-tree.mjs +28 -29
- package/esm2020/lib/structure/branchable.interface.mjs +1 -1
- package/esm2020/lib/structure/component-container.interface.mjs +2 -0
- package/esm2020/lib/structure/index.mjs +2 -4
- package/esm2020/lib/structure/tree-branch-node.interface.mjs +1 -1
- package/esm2020/lib/structure/tree-node.interface.mjs +1 -1
- package/fesm2015/limble-limble-tree.mjs +317 -193
- package/fesm2015/limble-limble-tree.mjs.map +1 -1
- package/fesm2020/limble-limble-tree.mjs +315 -189
- package/fesm2020/limble-limble-tree.mjs.map +1 -1
- package/lib/core/branch-options.interface.d.ts +1 -1
- package/lib/core/configuration/tree-options.interface.d.ts +23 -26
- package/lib/core/relationship.interface.d.ts +2 -3
- package/lib/core/tree-branch/branch-controller.d.ts +25 -0
- package/lib/core/tree-branch/tree-branch.d.ts +18 -18
- package/lib/core/tree-node-base.d.ts +4 -5
- package/lib/core/tree-root/root-controller.d.ts +19 -0
- package/lib/core/tree-root/tree-root.d.ts +11 -9
- package/lib/events/drag/drag-end-event.d.ts +5 -6
- package/lib/events/drag/drop-event.d.ts +3 -6
- package/lib/events/general/destruction-event.d.ts +8 -0
- package/lib/events/general/index.d.ts +1 -0
- package/lib/events/index.d.ts +1 -0
- package/lib/extras/drag-and-drop/drag-and-drop.d.ts +2 -3
- package/lib/extras/drag-and-drop/draggable.directive.d.ts +1 -1
- package/lib/structure/branchable.interface.d.ts +0 -1
- package/lib/structure/component-container.interface.d.ts +8 -0
- package/lib/structure/index.d.ts +1 -3
- package/lib/structure/tree-branch-node.interface.d.ts +2 -2
- package/lib/structure/tree-node.interface.d.ts +3 -1
- package/package.json +1 -1
- package/esm2020/lib/structure/container-tree-node.interface.mjs +0 -2
- package/esm2020/lib/structure/content-container.interface.mjs +0 -2
- package/esm2020/lib/structure/tree-root.node.interface.mjs +0 -2
- package/lib/structure/container-tree-node.interface.d.ts +0 -3
- package/lib/structure/content-container.interface.d.ts +0 -3
- package/lib/structure/tree-root.node.interface.d.ts +0 -2
|
@@ -27,7 +27,7 @@ class TreeCollapser {
|
|
|
27
27
|
branch.graftTo(treeBranch);
|
|
28
28
|
});
|
|
29
29
|
this.tempStorage.delete(treeBranch);
|
|
30
|
-
treeBranch.
|
|
30
|
+
treeBranch.detectChanges();
|
|
31
31
|
}
|
|
32
32
|
isCollapsed(treeBranch) {
|
|
33
33
|
return this.tempStorage.has(treeBranch);
|
|
@@ -235,19 +235,15 @@ class DragAndDrop {
|
|
|
235
235
|
}
|
|
236
236
|
setDragEffects(treeBranch, event) {
|
|
237
237
|
const dataTransfer = event.dataTransfer;
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
const nativeElement = treeBranch.getContents().location.nativeElement;
|
|
238
|
+
assert(dataTransfer instanceof DataTransfer);
|
|
239
|
+
const nativeElement = treeBranch.getNativeElement();
|
|
242
240
|
const [xOffset, yOffset] = this.getDragImageOffsets(event, nativeElement);
|
|
243
241
|
dataTransfer.setDragImage(nativeElement, xOffset, yOffset);
|
|
244
242
|
}
|
|
245
243
|
watchForDragend(treeBranch, event) {
|
|
246
244
|
const oldParent = treeBranch.parent();
|
|
247
245
|
const oldIndex = treeBranch.index();
|
|
248
|
-
|
|
249
|
-
throw new Error("branch must have a parent");
|
|
250
|
-
}
|
|
246
|
+
assert(oldParent !== undefined && oldIndex !== undefined);
|
|
251
247
|
event.target?.addEventListener("dragend", (dragend) => {
|
|
252
248
|
if (dragState.state() !== DragStates.Dropped) {
|
|
253
249
|
//The drag ended but a drop never occurred, so put the dragged branch back where it started.
|
|
@@ -268,13 +264,13 @@ class DragAndDrop {
|
|
|
268
264
|
}, { once: true });
|
|
269
265
|
}
|
|
270
266
|
draggingAllowed(treeBranch) {
|
|
271
|
-
const allowDragging = config.getConfig(treeBranch.root())?.allowDragging ??
|
|
267
|
+
const allowDragging = config.getConfig(treeBranch.root())?.dragAndDrop?.allowDragging ??
|
|
272
268
|
(() => true);
|
|
273
269
|
return allowDragging(treeBranch);
|
|
274
270
|
}
|
|
275
271
|
graftDraggedBranch(treeBranch, parent, index) {
|
|
276
272
|
treeBranch.graftTo(parent, index);
|
|
277
|
-
treeBranch.
|
|
273
|
+
treeBranch.getNativeElement().style.display = "block";
|
|
278
274
|
dragState.dropped();
|
|
279
275
|
}
|
|
280
276
|
}
|
|
@@ -359,22 +355,14 @@ class BranchComponent {
|
|
|
359
355
|
this.showLateralDropzone = false;
|
|
360
356
|
}
|
|
361
357
|
ngAfterViewInit() {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
}
|
|
365
|
-
if (this.contentToHost === undefined) {
|
|
366
|
-
throw new TreeError("'content' is a required input");
|
|
367
|
-
}
|
|
358
|
+
assert(this.contentContainer !== undefined);
|
|
359
|
+
assert(this.contentToHost !== undefined);
|
|
368
360
|
this.hostedContent = this.contentContainer.createComponent(this.contentToHost);
|
|
369
361
|
this.contentCreated.emit(this.hostedContent.instance);
|
|
370
|
-
|
|
371
|
-
throw new Error("querylist not defined");
|
|
372
|
-
}
|
|
362
|
+
assert(this.dropzones !== undefined);
|
|
373
363
|
const inner = this.dropzones.get(0);
|
|
374
364
|
const lateral = this.dropzones.get(1);
|
|
375
|
-
|
|
376
|
-
throw new Error("dropzones not defined");
|
|
377
|
-
}
|
|
365
|
+
assert(inner !== undefined && lateral !== undefined);
|
|
378
366
|
merge(inner.dropped.pipe(map(() => "inner")), lateral.dropped.pipe(map(() => "lateral"))).subscribe(this.dropped);
|
|
379
367
|
this.hostedContent.changeDetectorRef.detectChanges();
|
|
380
368
|
}
|
|
@@ -476,6 +464,7 @@ class PruneEvent {
|
|
|
476
464
|
|
|
477
465
|
class TreeNodeBase {
|
|
478
466
|
constructor() {
|
|
467
|
+
this.destroyed = false;
|
|
479
468
|
this._branches = [];
|
|
480
469
|
this.events$ = new Subject();
|
|
481
470
|
this.subscriptions = [
|
|
@@ -490,17 +479,14 @@ class TreeNodeBase {
|
|
|
490
479
|
branches() {
|
|
491
480
|
return [...this._branches];
|
|
492
481
|
}
|
|
493
|
-
deleteBranch(index) {
|
|
494
|
-
if (index === undefined) {
|
|
495
|
-
this._branches.pop();
|
|
496
|
-
return;
|
|
497
|
-
}
|
|
498
|
-
this._branches.splice(index, 1);
|
|
499
|
-
}
|
|
500
482
|
destroy() {
|
|
483
|
+
this.branches().forEach((branch) => {
|
|
484
|
+
branch.destroy();
|
|
485
|
+
});
|
|
501
486
|
this.subscriptions.forEach((sub) => {
|
|
502
487
|
sub.unsubscribe();
|
|
503
488
|
});
|
|
489
|
+
this.destroyed = true;
|
|
504
490
|
}
|
|
505
491
|
dispatch(event) {
|
|
506
492
|
this.events$.next(event);
|
|
@@ -511,6 +497,9 @@ class TreeNodeBase {
|
|
|
511
497
|
getBranch(index) {
|
|
512
498
|
return this._branches[index];
|
|
513
499
|
}
|
|
500
|
+
isDestroyed() {
|
|
501
|
+
return this.destroyed;
|
|
502
|
+
}
|
|
514
503
|
plot() {
|
|
515
504
|
return new Map(this.branches().map((branch, index) => [index, branch.plot()]));
|
|
516
505
|
}
|
|
@@ -521,7 +510,7 @@ class TreeNodeBase {
|
|
|
521
510
|
}
|
|
522
511
|
deregisterChildRelationship(child) {
|
|
523
512
|
const index = this.branches().findIndex((branch) => branch === child);
|
|
524
|
-
this.
|
|
513
|
+
this._branches.splice(index, 1);
|
|
525
514
|
}
|
|
526
515
|
graftsToSelf() {
|
|
527
516
|
return this.events().pipe(filter((event) => event instanceof GraftEvent), filter((event) => event.parent().events() === this.events$));
|
|
@@ -538,6 +527,18 @@ class TreeNodeBase {
|
|
|
538
527
|
}
|
|
539
528
|
}
|
|
540
529
|
|
|
530
|
+
class DestructionEvent {
|
|
531
|
+
constructor(source) {
|
|
532
|
+
this._source = source;
|
|
533
|
+
}
|
|
534
|
+
type() {
|
|
535
|
+
return "destruction";
|
|
536
|
+
}
|
|
537
|
+
source() {
|
|
538
|
+
return this._source;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
541
542
|
class RootComponent {
|
|
542
543
|
constructor() {
|
|
543
544
|
this.branchesContainer = undefined;
|
|
@@ -548,9 +549,7 @@ class RootComponent {
|
|
|
548
549
|
}
|
|
549
550
|
ngAfterViewInit() {
|
|
550
551
|
this.afterViewInit.emit();
|
|
551
|
-
|
|
552
|
-
throw new Error("dropzone is not defined");
|
|
553
|
-
}
|
|
552
|
+
assert(this.dropzone !== undefined);
|
|
554
553
|
this.dropzone.dropped.subscribe(this.dropped);
|
|
555
554
|
}
|
|
556
555
|
}
|
|
@@ -571,42 +570,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
571
570
|
type: Output
|
|
572
571
|
}] } });
|
|
573
572
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
573
|
+
/**
|
|
574
|
+
* A wrapper around the BranchComponent that helps instantiate it and handles its events.
|
|
575
|
+
*/
|
|
576
|
+
class RootController {
|
|
577
|
+
constructor(treeRoot, viewContainerRef) {
|
|
578
|
+
this.treeRoot = treeRoot;
|
|
579
|
+
this.rootComponentRef = viewContainerRef.createComponent(RootComponent);
|
|
580
580
|
const viewInitSub = this.rootComponentRef.instance.afterViewInit.subscribe(() => {
|
|
581
581
|
const dropzone = this.rootComponentRef.instance.dropzone;
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
}
|
|
585
|
-
dropzoneRenderer.registerDropzone(dropzone, this);
|
|
582
|
+
assert(dropzone !== undefined);
|
|
583
|
+
dropzoneRenderer.registerDropzone(dropzone, this.treeRoot);
|
|
586
584
|
});
|
|
587
585
|
const droppedSub = this.rootComponentRef.instance.dropped.subscribe(() => {
|
|
588
|
-
dropzoneRenderer.handleDrop(this, "inner");
|
|
586
|
+
dropzoneRenderer.handleDrop(this.treeRoot, "inner");
|
|
589
587
|
});
|
|
590
588
|
this.instanceSubscriptions = [viewInitSub, droppedSub];
|
|
589
|
+
}
|
|
590
|
+
destroy() {
|
|
591
|
+
this.instanceSubscriptions.forEach((sub) => {
|
|
592
|
+
sub.unsubscribe();
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
detectChanges() {
|
|
591
596
|
this.rootComponentRef.changeDetectorRef.detectChanges();
|
|
592
597
|
}
|
|
598
|
+
getBranchesContainer() {
|
|
599
|
+
return this.rootComponentRef.instance.branchesContainer;
|
|
600
|
+
}
|
|
601
|
+
getComponentInstance() {
|
|
602
|
+
return this.rootComponentRef.instance;
|
|
603
|
+
}
|
|
604
|
+
getHostView() {
|
|
605
|
+
return this.rootComponentRef.hostView;
|
|
606
|
+
}
|
|
607
|
+
getNativeElement() {
|
|
608
|
+
return this.rootComponentRef.location.nativeElement;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
class TreeRoot {
|
|
613
|
+
constructor(viewContainerRef) {
|
|
614
|
+
this.viewContainerRef = viewContainerRef;
|
|
615
|
+
this.treeNodeBase = new TreeNodeBase();
|
|
616
|
+
this.rootController = new RootController(this, viewContainerRef);
|
|
617
|
+
this.detectChanges();
|
|
618
|
+
}
|
|
593
619
|
branches() {
|
|
594
620
|
return this.treeNodeBase.branches();
|
|
595
621
|
}
|
|
596
|
-
deleteBranch(index) {
|
|
597
|
-
this.treeNodeBase.deleteBranch(index);
|
|
598
|
-
}
|
|
599
622
|
destroy() {
|
|
623
|
+
if (this.isDestroyed()) {
|
|
624
|
+
throw new TreeError("Cannot destroy a destroyed tree root");
|
|
625
|
+
}
|
|
600
626
|
dropzoneRenderer.clearTreeFromRegistry(this);
|
|
601
|
-
this.branches().forEach((branch) => {
|
|
602
|
-
branch.destroy();
|
|
603
|
-
});
|
|
604
627
|
this.treeNodeBase.destroy();
|
|
605
|
-
this.
|
|
606
|
-
sub.unsubscribe();
|
|
607
|
-
});
|
|
628
|
+
this.rootController.destroy();
|
|
608
629
|
this.viewContainerRef.clear();
|
|
609
630
|
config.delete(this);
|
|
631
|
+
this.dispatch(new DestructionEvent(this));
|
|
632
|
+
}
|
|
633
|
+
detectChanges() {
|
|
634
|
+
this.rootController.detectChanges();
|
|
610
635
|
}
|
|
611
636
|
dispatch(event) {
|
|
612
637
|
this.treeNodeBase.dispatch(event);
|
|
@@ -617,12 +642,39 @@ class TreeRoot {
|
|
|
617
642
|
getBranch(index) {
|
|
618
643
|
return this.treeNodeBase.getBranch(index);
|
|
619
644
|
}
|
|
620
|
-
|
|
621
|
-
|
|
645
|
+
getBranchesContainer() {
|
|
646
|
+
if (this.isDestroyed()) {
|
|
647
|
+
throw new TreeError("Cannot get branches container from a destroyed tree root");
|
|
648
|
+
}
|
|
649
|
+
return this.rootController.getBranchesContainer();
|
|
650
|
+
}
|
|
651
|
+
getComponentInstance() {
|
|
652
|
+
if (this.isDestroyed()) {
|
|
653
|
+
throw new TreeError("Cannot get component instance from a destroyed tree root");
|
|
654
|
+
}
|
|
655
|
+
return this.rootController.getComponentInstance();
|
|
656
|
+
}
|
|
657
|
+
getHostView() {
|
|
658
|
+
if (this.isDestroyed()) {
|
|
659
|
+
throw new TreeError("Cannot get component host view from a destroyed tree root");
|
|
660
|
+
}
|
|
661
|
+
return this.rootController.getHostView();
|
|
662
|
+
}
|
|
663
|
+
getNativeElement() {
|
|
664
|
+
if (this.isDestroyed()) {
|
|
665
|
+
throw new TreeError("Cannot get native element from a destroyed tree root");
|
|
666
|
+
}
|
|
667
|
+
return this.rootController.getNativeElement();
|
|
622
668
|
}
|
|
623
669
|
grow(component, options) {
|
|
670
|
+
if (this.isDestroyed()) {
|
|
671
|
+
throw new TreeError("Cannot grow a branch on a destroyed tree root");
|
|
672
|
+
}
|
|
624
673
|
return new TreeBranch(this, { component, ...options });
|
|
625
674
|
}
|
|
675
|
+
isDestroyed() {
|
|
676
|
+
return this.treeNodeBase.isDestroyed();
|
|
677
|
+
}
|
|
626
678
|
plot() {
|
|
627
679
|
return this.treeNodeBase.plot();
|
|
628
680
|
}
|
|
@@ -650,29 +702,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
650
702
|
args: [{ providedIn: "root" }]
|
|
651
703
|
}] });
|
|
652
704
|
|
|
705
|
+
/**
|
|
706
|
+
* A wrapper around the BranchComponent that helps instantiate it and handles its events.
|
|
707
|
+
*/
|
|
708
|
+
class BranchController {
|
|
709
|
+
constructor(treeBranch, parentBranchesContainer) {
|
|
710
|
+
this.treeBranch = treeBranch;
|
|
711
|
+
this.outputBindingSubscriptions = [];
|
|
712
|
+
this.branchComponentRef = createComponent(BranchComponent, {
|
|
713
|
+
environmentInjector: parentBranchesContainer.injector.get(EnvironmentInjector)
|
|
714
|
+
});
|
|
715
|
+
this.branchComponentRef.instance.contentToHost =
|
|
716
|
+
this.treeBranch.branchOptions.component;
|
|
717
|
+
this.instanceSubscriptions = this.getInstanceSubscriptions(this.branchComponentRef.instance);
|
|
718
|
+
}
|
|
719
|
+
destroy() {
|
|
720
|
+
this.instanceSubscriptions.forEach((sub) => {
|
|
721
|
+
sub.unsubscribe();
|
|
722
|
+
});
|
|
723
|
+
this.outputBindingSubscriptions.forEach((sub) => {
|
|
724
|
+
sub.unsubscribe();
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
detectChanges() {
|
|
728
|
+
this.branchComponentRef.changeDetectorRef.detectChanges();
|
|
729
|
+
}
|
|
730
|
+
getBranchesContainer() {
|
|
731
|
+
return this.branchComponentRef.instance.branchesContainer;
|
|
732
|
+
}
|
|
733
|
+
getComponentInstance() {
|
|
734
|
+
return this.branchComponentRef.instance;
|
|
735
|
+
}
|
|
736
|
+
getHostView() {
|
|
737
|
+
return this.branchComponentRef.hostView;
|
|
738
|
+
}
|
|
739
|
+
getNativeElement() {
|
|
740
|
+
return this.branchComponentRef.location.nativeElement;
|
|
741
|
+
}
|
|
742
|
+
getUserlandComponentRef() {
|
|
743
|
+
return this.branchComponentRef.instance.getHostedContent();
|
|
744
|
+
}
|
|
745
|
+
getContentCreatedSub(instance) {
|
|
746
|
+
return instance.contentCreated.subscribe((userlandComponentInstance) => {
|
|
747
|
+
const component = userlandComponentInstance;
|
|
748
|
+
Object.entries(this.treeBranch.branchOptions.inputBindings ?? {}).forEach(([key, value]) => {
|
|
749
|
+
component[key] = value;
|
|
750
|
+
});
|
|
751
|
+
Object.entries(this.treeBranch.branchOptions.outputBindings ?? {}).forEach(([key, value]) => {
|
|
752
|
+
this.outputBindingSubscriptions.push(component[key].subscribe(value));
|
|
753
|
+
});
|
|
754
|
+
component.treeBranch = this.treeBranch;
|
|
755
|
+
const dropzones = instance.dropzones;
|
|
756
|
+
assert(dropzones !== undefined);
|
|
757
|
+
dropzoneRenderer.registerDropzones(dropzones, this.treeBranch);
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
getInstanceSubscriptions(instance) {
|
|
761
|
+
const droppedSub = instance.dropped.subscribe((placement) => {
|
|
762
|
+
dropzoneRenderer.handleDrop(this.treeBranch, placement);
|
|
763
|
+
});
|
|
764
|
+
return [
|
|
765
|
+
this.getContentCreatedSub(instance),
|
|
766
|
+
this.getShowLowerZonesSub(instance),
|
|
767
|
+
this.getShowUpperZonesSub(instance),
|
|
768
|
+
droppedSub
|
|
769
|
+
];
|
|
770
|
+
}
|
|
771
|
+
getShowLowerZonesSub(instance) {
|
|
772
|
+
return instance.showDropzones
|
|
773
|
+
.pipe(filter((direction) => direction === "lower"))
|
|
774
|
+
.subscribe(() => {
|
|
775
|
+
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
776
|
+
if (currentDropzoneDisplayed?.treeBranch === this.treeBranch &&
|
|
777
|
+
currentDropzoneDisplayed.direction === "lower") {
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
dropzoneRenderer.showLowerZones(this.treeBranch);
|
|
781
|
+
instance.triggerChangeDetection();
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
getShowUpperZonesSub(instance) {
|
|
785
|
+
return instance.showDropzones
|
|
786
|
+
.pipe(filter((direction) => direction === "upper"))
|
|
787
|
+
.subscribe(() => {
|
|
788
|
+
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
789
|
+
if (currentDropzoneDisplayed?.treeBranch === this.treeBranch &&
|
|
790
|
+
currentDropzoneDisplayed.direction === "upper") {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
dropzoneRenderer.showUpperZones(this.treeBranch);
|
|
794
|
+
instance.triggerChangeDetection();
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
|
|
653
799
|
class TreeBranch {
|
|
654
800
|
constructor(parent, branchOptions) {
|
|
655
801
|
this.branchOptions = branchOptions;
|
|
656
802
|
this.detachedView = null;
|
|
657
803
|
this.treeNodeBase = new TreeNodeBase();
|
|
658
|
-
|
|
659
|
-
const parentBranchesContainer = parent.getContents().instance.branchesContainer;
|
|
804
|
+
const parentBranchesContainer = parent.getBranchesContainer();
|
|
660
805
|
assert(parentBranchesContainer !== undefined);
|
|
661
|
-
this.
|
|
662
|
-
environmentInjector: parentBranchesContainer.injector.get(EnvironmentInjector)
|
|
663
|
-
});
|
|
664
|
-
this.contents.instance.contentToHost = this.userlandComponent;
|
|
806
|
+
this.branchController = new BranchController(this, parentBranchesContainer);
|
|
665
807
|
this.setIndentation(parent);
|
|
666
|
-
this.outputBindingSubscriptions = [];
|
|
667
|
-
this.instanceSubscriptions = this.getInstanceSubscriptions();
|
|
668
808
|
if (parent instanceof TreeBranch &&
|
|
669
|
-
parent.branchOptions.
|
|
809
|
+
parent.branchOptions.defaultCollapsed === true) {
|
|
670
810
|
treeCollapser.storePrecollapsedNode(parent, this);
|
|
671
|
-
this.detachedView = this.
|
|
811
|
+
this.detachedView = this.branchController.getHostView();
|
|
672
812
|
}
|
|
673
813
|
else {
|
|
674
|
-
parentBranchesContainer.insert(this.
|
|
675
|
-
this.
|
|
814
|
+
parentBranchesContainer.insert(this.branchController.getHostView());
|
|
815
|
+
this.detectChanges();
|
|
676
816
|
this._parent = parent;
|
|
677
817
|
this.dispatch(new GraftEvent(this, {
|
|
678
818
|
parent: this._parent,
|
|
@@ -684,32 +824,20 @@ class TreeBranch {
|
|
|
684
824
|
branches() {
|
|
685
825
|
return this.treeNodeBase.branches();
|
|
686
826
|
}
|
|
687
|
-
deleteBranch(index) {
|
|
688
|
-
this.treeNodeBase.deleteBranch(index);
|
|
689
|
-
}
|
|
690
827
|
destroy() {
|
|
691
|
-
if (
|
|
692
|
-
|
|
693
|
-
dropzoneRenderer.clearTreeFromRegistry(this);
|
|
694
|
-
}
|
|
695
|
-
this.branches().forEach((branch) => {
|
|
696
|
-
branch.destroy();
|
|
697
|
-
});
|
|
698
|
-
const parent = this._parent;
|
|
699
|
-
const index = this.index();
|
|
700
|
-
if (index !== undefined && parent !== undefined) {
|
|
701
|
-
const container = parent.getContents().instance.branchesContainer;
|
|
702
|
-
assert(container !== undefined);
|
|
703
|
-
container.remove(index);
|
|
704
|
-
parent.deleteBranch(index);
|
|
828
|
+
if (this.isDestroyed()) {
|
|
829
|
+
throw new TreeError("Cannot destroy a destroyed tree branch");
|
|
705
830
|
}
|
|
831
|
+
this.prune();
|
|
832
|
+
treeCollapser.expand(this);
|
|
833
|
+
dropzoneRenderer.clearTreeFromRegistry(this);
|
|
834
|
+
this.branchController.getHostView().destroy();
|
|
706
835
|
this.treeNodeBase.destroy();
|
|
707
|
-
this.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
});
|
|
836
|
+
this.branchController.destroy();
|
|
837
|
+
this.dispatch(new DestructionEvent(this));
|
|
838
|
+
}
|
|
839
|
+
detectChanges() {
|
|
840
|
+
this.branchController.detectChanges();
|
|
713
841
|
}
|
|
714
842
|
dispatch(event) {
|
|
715
843
|
this.treeNodeBase.dispatch(event);
|
|
@@ -721,10 +849,38 @@ class TreeBranch {
|
|
|
721
849
|
getBranch(index) {
|
|
722
850
|
return this.treeNodeBase.getBranch(index);
|
|
723
851
|
}
|
|
724
|
-
|
|
725
|
-
|
|
852
|
+
getBranchesContainer() {
|
|
853
|
+
if (this.isDestroyed()) {
|
|
854
|
+
throw new TreeError("Cannot get branches container from a destroyed tree branch");
|
|
855
|
+
}
|
|
856
|
+
return this.branchController.getBranchesContainer();
|
|
857
|
+
}
|
|
858
|
+
getComponentInstance() {
|
|
859
|
+
if (this.isDestroyed()) {
|
|
860
|
+
throw new TreeError("Cannot get component instance from a destroyed tree branch");
|
|
861
|
+
}
|
|
862
|
+
return this.branchController.getComponentInstance();
|
|
863
|
+
}
|
|
864
|
+
getHostView() {
|
|
865
|
+
if (this.isDestroyed()) {
|
|
866
|
+
throw new TreeError("Cannot get component host view from a destroyed tree branch");
|
|
867
|
+
}
|
|
868
|
+
return this.branchController.getHostView();
|
|
869
|
+
}
|
|
870
|
+
getNativeElement() {
|
|
871
|
+
if (this.isDestroyed()) {
|
|
872
|
+
throw new TreeError("Cannot get native element from a destroyed tree branch");
|
|
873
|
+
}
|
|
874
|
+
return this.branchController.getNativeElement();
|
|
875
|
+
}
|
|
876
|
+
getUserlandComponentRef() {
|
|
877
|
+
if (this.isDestroyed()) {
|
|
878
|
+
throw new TreeError("Cannot get userland component from a destroyed tree branch");
|
|
879
|
+
}
|
|
880
|
+
return this.branchController.getUserlandComponentRef();
|
|
726
881
|
}
|
|
727
882
|
graftTo(newParent, index) {
|
|
883
|
+
this.checkGraftLocationValidity(newParent, index);
|
|
728
884
|
const ownIndex = this.index();
|
|
729
885
|
if (ownIndex !== undefined) {
|
|
730
886
|
this.prune();
|
|
@@ -740,6 +896,9 @@ class TreeBranch {
|
|
|
740
896
|
return newIndex;
|
|
741
897
|
}
|
|
742
898
|
grow(component, options) {
|
|
899
|
+
if (this.isDestroyed()) {
|
|
900
|
+
throw new TreeError("Cannot grow a branch on a destroyed tree branch");
|
|
901
|
+
}
|
|
743
902
|
return new TreeBranch(this, { component, ...options });
|
|
744
903
|
}
|
|
745
904
|
index() {
|
|
@@ -752,6 +911,9 @@ class TreeBranch {
|
|
|
752
911
|
assert(index >= 0);
|
|
753
912
|
return index;
|
|
754
913
|
}
|
|
914
|
+
isDestroyed() {
|
|
915
|
+
return this.treeNodeBase.isDestroyed();
|
|
916
|
+
}
|
|
755
917
|
meta() {
|
|
756
918
|
return this.branchOptions.meta ?? {};
|
|
757
919
|
}
|
|
@@ -773,11 +935,14 @@ class TreeBranch {
|
|
|
773
935
|
return [index];
|
|
774
936
|
}
|
|
775
937
|
prune() {
|
|
938
|
+
if (this.isDestroyed()) {
|
|
939
|
+
throw new TreeError("Cannot prune a destroyed tree branch");
|
|
940
|
+
}
|
|
776
941
|
const parent = this._parent;
|
|
777
942
|
const index = this.index();
|
|
778
943
|
if (index === undefined || parent === undefined)
|
|
779
944
|
return;
|
|
780
|
-
const container = parent.
|
|
945
|
+
const container = parent.getBranchesContainer();
|
|
781
946
|
assert(container !== undefined);
|
|
782
947
|
this.detachedView = container.detach(index);
|
|
783
948
|
assert(this.detachedView !== null);
|
|
@@ -792,81 +957,40 @@ class TreeBranch {
|
|
|
792
957
|
}
|
|
793
958
|
root() {
|
|
794
959
|
const parent = this.parent();
|
|
795
|
-
if (parent === undefined) {
|
|
796
|
-
return undefined;
|
|
797
|
-
}
|
|
798
960
|
if (parent instanceof TreeBranch) {
|
|
799
961
|
return parent.root();
|
|
800
962
|
}
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
}
|
|
804
|
-
throw new Error("unexpected parent type");
|
|
963
|
+
assert(parent instanceof TreeRoot || parent === undefined);
|
|
964
|
+
return parent;
|
|
805
965
|
}
|
|
806
966
|
traverse(callback) {
|
|
807
967
|
callback(this);
|
|
808
968
|
this.treeNodeBase.traverse(callback);
|
|
809
969
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
dropzoneRenderer.registerDropzones(dropzones, this);
|
|
825
|
-
});
|
|
826
|
-
}
|
|
827
|
-
getInstanceSubscriptions() {
|
|
828
|
-
const droppedSub = this.contents.instance.dropped.subscribe((placement) => {
|
|
829
|
-
dropzoneRenderer.handleDrop(this, placement);
|
|
830
|
-
});
|
|
831
|
-
return [
|
|
832
|
-
this.getContentCreatedSub(),
|
|
833
|
-
this.getShowLowerZonesSub(),
|
|
834
|
-
this.getShowUpperZonesSub(),
|
|
835
|
-
droppedSub
|
|
836
|
-
];
|
|
837
|
-
}
|
|
838
|
-
getShowLowerZonesSub() {
|
|
839
|
-
const instance = this.contents.instance;
|
|
840
|
-
return instance.showDropzones
|
|
841
|
-
.pipe(filter((direction) => direction === "lower"))
|
|
842
|
-
.subscribe(() => {
|
|
843
|
-
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
844
|
-
if (currentDropzoneDisplayed?.treeBranch === this &&
|
|
845
|
-
currentDropzoneDisplayed.direction === "lower") {
|
|
846
|
-
return;
|
|
970
|
+
checkGraftLocationValidity(newParent, index) {
|
|
971
|
+
if (this.isDestroyed()) {
|
|
972
|
+
throw new TreeError("Cannot graft a destroyed tree branch");
|
|
973
|
+
}
|
|
974
|
+
if (newParent.isDestroyed()) {
|
|
975
|
+
throw new TreeError("Cannot graft to a destroyed tree branch");
|
|
976
|
+
}
|
|
977
|
+
if (typeof index === "number" &&
|
|
978
|
+
this.indexIsOutOfRange(newParent, index)) {
|
|
979
|
+
throw new TreeError(`Cannot graft branch at index ${index} of the parent. Out of range.`);
|
|
980
|
+
}
|
|
981
|
+
this.traverse((node) => {
|
|
982
|
+
if (node === newParent) {
|
|
983
|
+
throw new TreeError("Cannot graft a branch to itself or any of its own descendants");
|
|
847
984
|
}
|
|
848
|
-
dropzoneRenderer.showLowerZones(this);
|
|
849
|
-
instance.triggerChangeDetection();
|
|
850
985
|
});
|
|
851
986
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
return instance.showDropzones
|
|
855
|
-
.pipe(filter((direction) => direction === "upper"))
|
|
856
|
-
.subscribe(() => {
|
|
857
|
-
const currentDropzoneDisplayed = dropzoneRenderer.getCurrentDisplay();
|
|
858
|
-
if (currentDropzoneDisplayed?.treeBranch === this &&
|
|
859
|
-
currentDropzoneDisplayed.direction === "upper") {
|
|
860
|
-
return;
|
|
861
|
-
}
|
|
862
|
-
dropzoneRenderer.showUpperZones(this);
|
|
863
|
-
instance.triggerChangeDetection();
|
|
864
|
-
});
|
|
987
|
+
indexIsOutOfRange(parent, index) {
|
|
988
|
+
return index < 0 || index > parent.branches().length;
|
|
865
989
|
}
|
|
866
990
|
reattachView(index) {
|
|
867
991
|
assert(this._parent !== undefined);
|
|
868
992
|
assert(this.detachedView !== null);
|
|
869
|
-
const container = this._parent.
|
|
993
|
+
const container = this._parent.getBranchesContainer();
|
|
870
994
|
assert(container !== undefined);
|
|
871
995
|
this.detachedView.reattach();
|
|
872
996
|
container.insert(this.detachedView, index);
|
|
@@ -876,7 +1000,8 @@ class TreeBranch {
|
|
|
876
1000
|
const root = parent.root();
|
|
877
1001
|
assert(root !== undefined);
|
|
878
1002
|
const options = config.getConfig(root);
|
|
879
|
-
const branchesContainerEl = this.
|
|
1003
|
+
const branchesContainerEl = this.branchController
|
|
1004
|
+
.getNativeElement()
|
|
880
1005
|
.getElementsByClassName("branches-container")
|
|
881
1006
|
.item(0);
|
|
882
1007
|
assert(branchesContainerEl instanceof HTMLElement);
|
|
@@ -916,7 +1041,7 @@ class DropzoneRenderer {
|
|
|
916
1041
|
if (this.currentDisplay === null)
|
|
917
1042
|
return;
|
|
918
1043
|
for (const branch of this.registry.values()) {
|
|
919
|
-
const instance = branch.
|
|
1044
|
+
const instance = branch.getComponentInstance();
|
|
920
1045
|
instance.showInnerDropzone = false;
|
|
921
1046
|
if (instance instanceof BranchComponent) {
|
|
922
1047
|
instance.showLateralDropzone = false;
|
|
@@ -1017,7 +1142,7 @@ class DropzoneRenderer {
|
|
|
1017
1142
|
return true;
|
|
1018
1143
|
}
|
|
1019
1144
|
if (treeNode instanceof TreeBranch) {
|
|
1020
|
-
const allowNesting = config.getConfig(treeNode.root())?.allowNesting ??
|
|
1145
|
+
const allowNesting = config.getConfig(treeNode.root())?.dragAndDrop?.allowNesting ??
|
|
1021
1146
|
(() => true);
|
|
1022
1147
|
return allowNesting(treeNode);
|
|
1023
1148
|
}
|
|
@@ -1027,11 +1152,13 @@ class DropzoneRenderer {
|
|
|
1027
1152
|
const sourceNode = dragState.getDragData();
|
|
1028
1153
|
assert(sourceNode instanceof TreeBranch);
|
|
1029
1154
|
if (parent instanceof TreeRoot) {
|
|
1030
|
-
const allowDrop = config.getConfig(parent)?.allowDrop ??
|
|
1155
|
+
const allowDrop = config.getConfig(parent)?.dragAndDrop?.allowDrop ??
|
|
1156
|
+
(() => true);
|
|
1031
1157
|
return allowDrop(sourceNode, parent, index);
|
|
1032
1158
|
}
|
|
1033
1159
|
if (parent instanceof TreeBranch) {
|
|
1034
|
-
const allowDrop = config.getConfig(parent.root())?.allowDrop ??
|
|
1160
|
+
const allowDrop = config.getConfig(parent.root())?.dragAndDrop?.allowDrop ??
|
|
1161
|
+
(() => true);
|
|
1035
1162
|
return allowDrop(sourceNode, parent, index);
|
|
1036
1163
|
}
|
|
1037
1164
|
throw new Error("unsupported treeNode type");
|
|
@@ -1039,14 +1166,14 @@ class DropzoneRenderer {
|
|
|
1039
1166
|
showInnerZone(treeNode) {
|
|
1040
1167
|
if (!this.nestingAllowed(treeNode) || !this.dropAllowed(treeNode, 0))
|
|
1041
1168
|
return;
|
|
1042
|
-
treeNode.
|
|
1169
|
+
treeNode.getComponentInstance().showInnerDropzone = true;
|
|
1043
1170
|
}
|
|
1044
1171
|
showLateralZone(treeBranch) {
|
|
1045
1172
|
const index = treeBranch.index();
|
|
1046
1173
|
assert(index !== undefined);
|
|
1047
1174
|
if (!this.dropAllowed(treeBranch.parent(), index + 1))
|
|
1048
1175
|
return;
|
|
1049
|
-
treeBranch.
|
|
1176
|
+
treeBranch.getComponentInstance().showLateralDropzone = true;
|
|
1050
1177
|
}
|
|
1051
1178
|
}
|
|
1052
1179
|
const dropzoneRenderer = new DropzoneRenderer();
|
|
@@ -1132,32 +1259,34 @@ class LegacyTree {
|
|
|
1132
1259
|
upgradeOptions(legacyOptions) {
|
|
1133
1260
|
return {
|
|
1134
1261
|
indentation: legacyOptions.indent,
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1262
|
+
dragAndDrop: {
|
|
1263
|
+
allowNesting: (branch) => {
|
|
1264
|
+
if (legacyOptions.listMode === true) {
|
|
1265
|
+
return false;
|
|
1266
|
+
}
|
|
1267
|
+
if (legacyOptions.allowNesting === undefined) {
|
|
1268
|
+
return true;
|
|
1269
|
+
}
|
|
1270
|
+
if (typeof legacyOptions.allowNesting === "boolean") {
|
|
1271
|
+
return legacyOptions.allowNesting;
|
|
1272
|
+
}
|
|
1273
|
+
return legacyOptions.allowNesting(branch);
|
|
1274
|
+
},
|
|
1275
|
+
allowDragging: (branch) => {
|
|
1276
|
+
if (legacyOptions.allowDragging === undefined) {
|
|
1277
|
+
return true;
|
|
1278
|
+
}
|
|
1279
|
+
if (typeof legacyOptions.allowDragging === "boolean") {
|
|
1280
|
+
return legacyOptions.allowDragging;
|
|
1281
|
+
}
|
|
1282
|
+
return legacyOptions.allowDragging(branch);
|
|
1283
|
+
},
|
|
1284
|
+
allowDrop: (source, parent, index) => {
|
|
1285
|
+
if (legacyOptions.allowDrop === undefined) {
|
|
1286
|
+
return true;
|
|
1287
|
+
}
|
|
1288
|
+
return legacyOptions.allowDrop(source, parent, index);
|
|
1159
1289
|
}
|
|
1160
|
-
return legacyOptions.allowDrop(source, parent, index);
|
|
1161
1290
|
}
|
|
1162
1291
|
};
|
|
1163
1292
|
}
|
|
@@ -1170,9 +1299,6 @@ class LegacyTree {
|
|
|
1170
1299
|
options.defaultComponent?.bindings ??
|
|
1171
1300
|
{});
|
|
1172
1301
|
const nodeData = node;
|
|
1173
|
-
delete nodeData.nodes;
|
|
1174
|
-
delete nodeData.collapsed;
|
|
1175
|
-
delete nodeData.component;
|
|
1176
1302
|
const branch = parent.grow(component, {
|
|
1177
1303
|
inputBindings: bindings,
|
|
1178
1304
|
meta: { nodeData }
|
|
@@ -1296,5 +1422,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
1296
1422
|
* Generated bundle index. Do not edit.
|
|
1297
1423
|
*/
|
|
1298
1424
|
|
|
1299
|
-
export { DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService, config };
|
|
1425
|
+
export { DestructionEvent, DragEndEvent, DragStartEvent, DraggableDirective, DragoverNoChangeDetectDirective, DropEvent, GraftEvent, LegacyTree, LimbleTreeLegacyModule, LimbleTreeModule, LimbleTreeRootComponent, PruneEvent, TreeBranch, TreeCollapseModule, TreeCollapseService, TreeDragAndDropModule, TreeDragAndDropService, TreeError, TreeRoot, TreeService, config };
|
|
1300
1426
|
//# sourceMappingURL=limble-limble-tree.mjs.map
|