ngx-vflow 1.15.0 → 1.16.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.
@@ -554,10 +554,58 @@ function align(num, constant) {
554
554
  return Math.ceil(num / constant) * constant;
555
555
  }
556
556
 
557
+ class FlowStatusService {
558
+ constructor() {
559
+ this.status = signal({ state: 'idle', payload: null });
560
+ }
561
+ setIdleStatus() {
562
+ this.status.set({ state: 'idle', payload: null });
563
+ }
564
+ setConnectionStartStatus(source, sourceHandle) {
565
+ this.status.set({ state: 'connection-start', payload: { source, sourceHandle } });
566
+ }
567
+ setReconnectionStartStatus(source, sourceHandle, oldEdge) {
568
+ this.status.set({ state: 'reconnection-start', payload: { source, sourceHandle, oldEdge } });
569
+ }
570
+ setConnectionValidationStatus(valid, source, target, sourceHandle, targetHandle) {
571
+ this.status.set({ state: 'connection-validation', payload: { source, target, sourceHandle, targetHandle, valid } });
572
+ }
573
+ setReconnectionValidationStatus(valid, source, target, sourceHandle, targetHandle, oldEdge) {
574
+ this.status.set({
575
+ state: 'reconnection-validation',
576
+ payload: { source, target, sourceHandle, targetHandle, valid, oldEdge },
577
+ });
578
+ }
579
+ setConnectionEndStatus(source, target, sourceHandle, targetHandle) {
580
+ this.status.set({ state: 'connection-end', payload: { source, target, sourceHandle, targetHandle } });
581
+ }
582
+ setReconnectionEndStatus(source, target, sourceHandle, targetHandle, oldEdge) {
583
+ this.status.set({ state: 'reconnection-end', payload: { source, target, sourceHandle, targetHandle, oldEdge } });
584
+ }
585
+ setNodeDragStartStatus(node) {
586
+ this.status.set({ state: 'node-drag-start', payload: { node } });
587
+ }
588
+ setNodeDragEndStatus(node) {
589
+ this.status.set({ state: 'node-drag-end', payload: { node } });
590
+ }
591
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
592
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService }); }
593
+ }
594
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService, decorators: [{
595
+ type: Injectable
596
+ }] });
597
+ function isNodeDragStartStatus(params) {
598
+ return params.state === 'node-drag-start';
599
+ }
600
+ function isNodeDragEndStatus(params) {
601
+ return params.state === 'node-drag-end';
602
+ }
603
+
557
604
  class DraggableService {
558
605
  constructor() {
559
606
  this.entitiesService = inject(FlowEntitiesService);
560
607
  this.settingsService = inject(FlowSettingsService);
608
+ this.flowStatusService = inject(FlowStatusService);
561
609
  }
562
610
  /**
563
611
  * Enable draggable behavior for element.
@@ -605,6 +653,7 @@ class DraggableService {
605
653
  .filter(filterCondition)
606
654
  .on('start', (event) => {
607
655
  dragNodes = this.getDragNodes(model);
656
+ this.flowStatusService.setNodeDragStartStatus(model);
608
657
  initialPositions = dragNodes.map((node) => ({
609
658
  x: node.point().x - event.x,
610
659
  y: node.point().y - event.y,
@@ -618,6 +667,9 @@ class DraggableService {
618
667
  };
619
668
  this.moveNode(model, point);
620
669
  });
670
+ })
671
+ .on('end', () => {
672
+ this.flowStatusService.setNodeDragEndStatus(model);
621
673
  });
622
674
  }
623
675
  getDragNodes(model) {
@@ -792,41 +844,6 @@ function addNodesToEdges(nodes, edges) {
792
844
  });
793
845
  }
794
846
 
795
- class FlowStatusService {
796
- constructor() {
797
- this.status = signal({ state: 'idle', payload: null });
798
- }
799
- setIdleStatus() {
800
- this.status.set({ state: 'idle', payload: null });
801
- }
802
- setConnectionStartStatus(source, sourceHandle) {
803
- this.status.set({ state: 'connection-start', payload: { source, sourceHandle } });
804
- }
805
- setReconnectionStartStatus(source, sourceHandle, oldEdge) {
806
- this.status.set({ state: 'reconnection-start', payload: { source, sourceHandle, oldEdge } });
807
- }
808
- setConnectionValidationStatus(valid, source, target, sourceHandle, targetHandle) {
809
- this.status.set({ state: 'connection-validation', payload: { source, target, sourceHandle, targetHandle, valid } });
810
- }
811
- setReconnectionValidationStatus(valid, source, target, sourceHandle, targetHandle, oldEdge) {
812
- this.status.set({
813
- state: 'reconnection-validation',
814
- payload: { source, target, sourceHandle, targetHandle, valid, oldEdge },
815
- });
816
- }
817
- setConnectionEndStatus(source, target, sourceHandle, targetHandle) {
818
- this.status.set({ state: 'connection-end', payload: { source, target, sourceHandle, targetHandle } });
819
- }
820
- setReconnectionEndStatus(source, target, sourceHandle, targetHandle, oldEdge) {
821
- this.status.set({ state: 'reconnection-end', payload: { source, target, sourceHandle, targetHandle, oldEdge } });
822
- }
823
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
824
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService }); }
825
- }
826
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService, decorators: [{
827
- type: Injectable
828
- }] });
829
-
830
847
  function isCallable(fn) {
831
848
  try {
832
849
  new Proxy(fn, { apply: () => undefined })();
@@ -1044,10 +1061,6 @@ function toSignalProperties(obj) {
1044
1061
  return newObj;
1045
1062
  }
1046
1063
 
1047
- function isGroupNode(node) {
1048
- return node.rawNode.type === 'default-group' || node.rawNode.type === 'template-group';
1049
- }
1050
-
1051
1064
  // MIT License
1052
1065
  // Copyright (c) 2023 Chau Tran
1053
1066
  // Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1118,10 +1131,10 @@ class NodeRenderingService {
1118
1131
  return this.viewportNodesAfterInteraction().sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder());
1119
1132
  });
1120
1133
  this.groups = computed(() => {
1121
- return this.nodes().filter((n) => isGroupNode(n));
1134
+ return this.nodes().filter((n) => !!n.children().length);
1122
1135
  });
1123
1136
  this.nonGroups = computed(() => {
1124
- return this.nodes().filter((n) => !isGroupNode(n));
1137
+ return this.nodes().filter((n) => !n.children().length);
1125
1138
  });
1126
1139
  this.viewportNodes = computed(() => {
1127
1140
  const nodes = this.flowEntitiesService.nodes();
@@ -3863,6 +3876,109 @@ function skipFrames(count) {
3863
3876
  });
3864
3877
  }
3865
3878
 
3879
+ function rectToRectWithSides(rect) {
3880
+ return {
3881
+ ...rect,
3882
+ left: rect.x,
3883
+ right: rect.x + rect.width,
3884
+ top: rect.y,
3885
+ bottom: rect.y + rect.height,
3886
+ };
3887
+ }
3888
+
3889
+ class AlignmentHelperComponent {
3890
+ constructor() {
3891
+ this.nodeRenderingService = inject(NodeRenderingService);
3892
+ this.flowStatus = inject(FlowStatusService);
3893
+ this.tolerance = input(10);
3894
+ this.lineColor = input('#1b262c');
3895
+ this.isNodeDragging = computed(() => isNodeDragStartStatus(this.flowStatus.status()));
3896
+ this.intersections = extendedComputed((lastValue) => {
3897
+ const status = this.flowStatus.status();
3898
+ if (isNodeDragStartStatus(status)) {
3899
+ const node = status.payload.node;
3900
+ const d = rectToRectWithSides(nodeToRect(node));
3901
+ const otherRects = this.nodeRenderingService
3902
+ .viewportNodes()
3903
+ .filter((n) => n !== node)
3904
+ // do not check children of the dragged node
3905
+ .filter((n) => !node.children().includes(n))
3906
+ .map((n) => rectToRectWithSides(nodeToRect(n)));
3907
+ const lines = [];
3908
+ let snappedX = d.x;
3909
+ let snappedY = d.y;
3910
+ let closestXDiff = Infinity;
3911
+ let closestYDiff = Infinity;
3912
+ otherRects.forEach((o) => {
3913
+ const dCenterX = d.left + d.width / 2;
3914
+ const oCenterX = o.left + o.width / 2;
3915
+ for (const [dX, oX, snapX, isCenter] of [
3916
+ // center check
3917
+ [dCenterX, oCenterX, oCenterX - d.width / 2, true],
3918
+ [d.left, o.left, o.left, false],
3919
+ [d.left, o.right, o.right, false],
3920
+ [d.right, o.left, o.left - d.width, false],
3921
+ [d.right, o.right, o.right - d.width, false],
3922
+ ]) {
3923
+ const diff = Math.abs(dX - oX);
3924
+ if (diff <= this.tolerance()) {
3925
+ const y = Math.min(d.top, o.top);
3926
+ const y2 = Math.max(d.bottom, o.bottom);
3927
+ lines.push({ x: oX, y, x2: oX, y2, isCenter });
3928
+ if (diff < closestXDiff) {
3929
+ closestXDiff = diff;
3930
+ snappedX = snapX;
3931
+ }
3932
+ if (isCenter)
3933
+ break;
3934
+ }
3935
+ }
3936
+ const dCenterY = d.top + d.height / 2;
3937
+ const oCenterY = o.top + o.height / 2;
3938
+ for (const [dY, oY, snapY, isCenter] of [
3939
+ // center check
3940
+ [dCenterY, oCenterY, oCenterY - d.height / 2, true],
3941
+ [d.top, o.top, o.top, false],
3942
+ [d.top, o.bottom, o.bottom, false],
3943
+ [d.bottom, o.top, o.top - d.height, false],
3944
+ [d.bottom, o.bottom, o.bottom - d.height, false],
3945
+ ]) {
3946
+ const diff = Math.abs(dY - oY);
3947
+ if (diff <= this.tolerance()) {
3948
+ const x = Math.min(d.left, o.left);
3949
+ const x2 = Math.max(d.right, o.right);
3950
+ lines.push({ x, y: oY, x2, y2: oY, isCenter });
3951
+ if (diff < closestYDiff) {
3952
+ closestYDiff = diff;
3953
+ snappedY = snapY;
3954
+ }
3955
+ if (isCenter)
3956
+ break;
3957
+ }
3958
+ }
3959
+ });
3960
+ return { lines, snappedX, snappedY };
3961
+ }
3962
+ return lastValue;
3963
+ });
3964
+ toObservable(this.flowStatus.status)
3965
+ .pipe(filter(isNodeDragEndStatus), map((status) => status.payload.node), map((node) => [node, this.intersections()]), tap(([node, intersections]) => {
3966
+ if (intersections) {
3967
+ const snapped = { x: intersections.snappedX, y: intersections.snappedY };
3968
+ const parentIfExists = node.parent() ? [node.parent()] : [];
3969
+ node.setPoint(getSpacePoints(snapped, parentIfExists)[0]);
3970
+ }
3971
+ }), takeUntilDestroyed())
3972
+ .subscribe();
3973
+ }
3974
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AlignmentHelperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3975
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: AlignmentHelperComponent, isStandalone: true, selector: "g[alignmentHelper]", inputs: { tolerance: { classPropertyName: "tolerance", publicName: "tolerance", isSignal: true, isRequired: false, transformFunction: null }, lineColor: { classPropertyName: "lineColor", publicName: "lineColor", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (isNodeDragging()) {\n @if (intersections(); as intersections) {\n @for (intersection of intersections.lines; track $index) {\n <svg:line\n [attr.stroke]=\"lineColor()\"\n [attr.stroke-dasharray]=\"intersection.isCenter ? 4 : null\"\n [attr.x1]=\"intersection.x\"\n [attr.y1]=\"intersection.y\"\n [attr.x2]=\"intersection.x2\"\n [attr.y2]=\"intersection.y2\" />\n }\n }\n}\n", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3976
+ }
3977
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: AlignmentHelperComponent, decorators: [{
3978
+ type: Component,
3979
+ args: [{ selector: 'g[alignmentHelper]', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "@if (isNodeDragging()) {\n @if (intersections(); as intersections) {\n @for (intersection of intersections.lines; track $index) {\n <svg:line\n [attr.stroke]=\"lineColor()\"\n [attr.stroke-dasharray]=\"intersection.isCenter ? 4 : null\"\n [attr.x1]=\"intersection.x\"\n [attr.y1]=\"intersection.y\"\n [attr.x2]=\"intersection.x2\"\n [attr.y2]=\"intersection.y2\" />\n }\n }\n}\n" }]
3980
+ }], ctorParameters: () => [] });
3981
+
3866
3982
  const changesControllerHostDirective = {
3867
3983
  directive: ChangesControllerDirective,
3868
3984
  outputs: [
@@ -3911,6 +4027,7 @@ class VflowComponent {
3911
4027
  this.keyboardService = inject(KeyboardService);
3912
4028
  this.injector = inject(Injector);
3913
4029
  this.flowRenderingService = inject(FlowRenderingService);
4030
+ this.alignmentHelper = input(false);
3914
4031
  this.nodeModels = this.nodeRenderingService.nodes;
3915
4032
  this.groups = this.nodeRenderingService.groups;
3916
4033
  this.nonGroups = this.nodeRenderingService.nonGroups;
@@ -4172,7 +4289,7 @@ class VflowComponent {
4172
4289
  return edge;
4173
4290
  }
4174
4291
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4175
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: VflowComponent, isStandalone: true, selector: "vflow", inputs: { view: "view", minZoom: "minZoom", maxZoom: "maxZoom", background: "background", optimization: "optimization", entitiesSelectable: "entitiesSelectable", keyboardShortcuts: "keyboardShortcuts", connection: ["connection", "connection", (settings) => new ConnectionModel(settings)], snapGrid: "snapGrid", elevateNodesOnSelect: "elevateNodesOnSelect", elevateEdgesOnSelect: "elevateEdgesOnSelect", nodes: "nodes", edges: "edges" }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, providers: [
4292
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: VflowComponent, isStandalone: true, selector: "vflow", inputs: { view: { classPropertyName: "view", publicName: "view", isSignal: false, isRequired: false, transformFunction: null }, minZoom: { classPropertyName: "minZoom", publicName: "minZoom", isSignal: false, isRequired: false, transformFunction: null }, maxZoom: { classPropertyName: "maxZoom", publicName: "maxZoom", isSignal: false, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: false, isRequired: false, transformFunction: null }, optimization: { classPropertyName: "optimization", publicName: "optimization", isSignal: false, isRequired: false, transformFunction: null }, entitiesSelectable: { classPropertyName: "entitiesSelectable", publicName: "entitiesSelectable", isSignal: false, isRequired: false, transformFunction: null }, keyboardShortcuts: { classPropertyName: "keyboardShortcuts", publicName: "keyboardShortcuts", isSignal: false, isRequired: false, transformFunction: null }, connection: { classPropertyName: "connection", publicName: "connection", isSignal: false, isRequired: false, transformFunction: (settings) => new ConnectionModel(settings) }, snapGrid: { classPropertyName: "snapGrid", publicName: "snapGrid", isSignal: false, isRequired: false, transformFunction: null }, elevateNodesOnSelect: { classPropertyName: "elevateNodesOnSelect", publicName: "elevateNodesOnSelect", isSignal: false, isRequired: false, transformFunction: null }, elevateEdgesOnSelect: { classPropertyName: "elevateEdgesOnSelect", publicName: "elevateEdgesOnSelect", isSignal: false, isRequired: false, transformFunction: null }, nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: false, isRequired: true, transformFunction: null }, alignmentHelper: { classPropertyName: "alignmentHelper", publicName: "alignmentHelper", isSignal: true, isRequired: false, transformFunction: null }, edges: { classPropertyName: "edges", publicName: "edges", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, providers: [
4176
4293
  DraggableService,
4177
4294
  ViewportService,
4178
4295
  FlowStatusService,
@@ -4188,7 +4305,7 @@ class VflowComponent {
4188
4305
  OverlaysService,
4189
4306
  { provide: PreviewFlowRenderStrategyService, useClass: ViewportPreviewFlowRenderStrategyService },
4190
4307
  FlowRenderingService,
4191
- ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (flowOptimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!flowOptimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n\n@if (flowOptimization().virtualization) {\n <canvas previewFlow class=\"preview-flow\" [width]=\"flowWidth()\" [height]=\"flowHeight()\"></canvas>\n}\n", styles: [":host{display:grid;grid-template-columns:1fr;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}.root-svg{grid-row-start:1;grid-column-start:1}.preview-flow{pointer-events:none;grid-row-start:1;grid-column-start:1}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PreviewFlowComponent, selector: "canvas[previewFlow]", inputs: ["width", "height"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4308
+ ], queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "nodeSvgTemplateDirective", first: true, predicate: NodeSvgTemplateDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true, isSignal: true }, { propertyName: "spacePointContext", first: true, predicate: SpacePointContextDirective, descendants: true, isSignal: true }], hostDirectives: [{ directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onNodesChange.position", "onNodesChange.position", "onNodesChange.position.single", "onNodesChange.position.single", "onNodesChange.position.many", "onNodesChange.position.many", "onNodesChange.size", "onNodesChange.size", "onNodesChange.size.single", "onNodesChange.size.single", "onNodesChange.size.many", "onNodesChange.size.many", "onNodesChange.add", "onNodesChange.add", "onNodesChange.add.single", "onNodesChange.add.single", "onNodesChange.add.many", "onNodesChange.add.many", "onNodesChange.remove", "onNodesChange.remove", "onNodesChange.remove.single", "onNodesChange.remove.single", "onNodesChange.remove.many", "onNodesChange.remove.many", "onNodesChange.select", "onNodesChange.select", "onNodesChange.select.single", "onNodesChange.select.single", "onNodesChange.select.many", "onNodesChange.select.many", "onEdgesChange", "onEdgesChange", "onEdgesChange.detached", "onEdgesChange.detached", "onEdgesChange.detached.single", "onEdgesChange.detached.single", "onEdgesChange.detached.many", "onEdgesChange.detached.many", "onEdgesChange.add", "onEdgesChange.add", "onEdgesChange.add.single", "onEdgesChange.add.single", "onEdgesChange.add.many", "onEdgesChange.add.many", "onEdgesChange.remove", "onEdgesChange.remove", "onEdgesChange.remove.single", "onEdgesChange.remove.single", "onEdgesChange.remove.many", "onEdgesChange.remove.many", "onEdgesChange.select", "onEdgesChange.select", "onEdgesChange.select.single", "onEdgesChange.select.single", "onEdgesChange.select.many", "onEdgesChange.select.many"] }], ngImport: i0, template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n @if (alignmentHelper(); as alignmentHelper) {\n @if (alignmentHelper === true) {\n <svg:g alignmentHelper />\n } @else {\n <svg:g alignmentHelper [tolerance]=\"alignmentHelper.tolerance\" [lineColor]=\"alignmentHelper.lineColor\" />\n }\n }\n\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (flowOptimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!flowOptimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n\n@if (flowOptimization().virtualization) {\n <canvas previewFlow class=\"preview-flow\" [width]=\"flowWidth()\" [height]=\"flowHeight()\"></canvas>\n}\n", styles: [":host{display:grid;grid-template-columns:1fr;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}.root-svg{grid-row-start:1;grid-column-start:1}.preview-flow{pointer-events:none;grid-row-start:1;grid-column-start:1}\n"], dependencies: [{ kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }, { kind: "directive", type: RootPointerDirective, selector: "svg[rootPointer]" }, { kind: "directive", type: FlowSizeControllerDirective, selector: "svg[flowSizeController]" }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "component", type: BackgroundComponent, selector: "g[background]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]" }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["model", "nodeTemplate", "nodeSvgTemplate", "groupNodeTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: PreviewFlowComponent, selector: "canvas[previewFlow]", inputs: ["width", "height"] }, { kind: "component", type: AlignmentHelperComponent, selector: "g[alignmentHelper]", inputs: ["tolerance", "lineColor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4192
4309
  }
4193
4310
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, decorators: [{
4194
4311
  type: Component,
@@ -4222,7 +4339,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
4222
4339
  EdgeComponent,
4223
4340
  NgTemplateOutlet,
4224
4341
  PreviewFlowComponent,
4225
- ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (flowOptimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!flowOptimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n\n@if (flowOptimization().virtualization) {\n <canvas previewFlow class=\"preview-flow\" [width]=\"flowWidth()\" [height]=\"flowHeight()\"></canvas>\n}\n", styles: [":host{display:grid;grid-template-columns:1fr;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}.root-svg{grid-row-start:1;grid-column-start:1}.preview-flow{pointer-events:none;grid-row-start:1;grid-column-start:1}\n"] }]
4342
+ AlignmentHelperComponent,
4343
+ ], template: "<svg:svg #flow rootSvgRef rootSvgContext rootPointer flowSizeController class=\"root-svg\">\n <defs flowDefs [markers]=\"markers()\" />\n\n <g background />\n\n <svg:g mapContext spacePointContext>\n @if (alignmentHelper(); as alignmentHelper) {\n @if (alignmentHelper === true) {\n <svg:g alignmentHelper />\n } @else {\n <svg:g alignmentHelper [tolerance]=\"alignmentHelper.tolerance\" [lineColor]=\"alignmentHelper.lineColor\" />\n }\n }\n\n <!-- Connection -->\n <svg:g connection [model]=\"connection\" [template]=\"connectionTemplateDirective()?.templateRef\" />\n\n @if (flowOptimization().detachedGroupsLayer) {\n <!-- Groups -->\n @for (model of groups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n <!-- Nodes -->\n @for (model of nonGroups(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n\n @if (!flowOptimization().detachedGroupsLayer) {\n <!-- Edges -->\n @for (model of edgeModels(); track trackEdges($index, model)) {\n <svg:g\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective()?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective()?.templateRef\" />\n }\n\n @for (model of nodeModels(); track trackNodes($index, model)) {\n <svg:g\n node\n [model]=\"model\"\n [nodeTemplate]=\"nodeTemplateDirective()?.templateRef\"\n [nodeSvgTemplate]=\"nodeSvgTemplateDirective()?.templateRef\"\n [groupNodeTemplate]=\"groupNodeTemplateDirective()?.templateRef\"\n [attr.transform]=\"model.pointTransform()\" />\n }\n }\n </svg:g>\n\n <!-- Minimap -->\n @if (minimap(); as minimap) {\n <ng-container [ngTemplateOutlet]=\"minimap.template()\" />\n }\n</svg:svg>\n\n@if (flowOptimization().virtualization) {\n <canvas previewFlow class=\"preview-flow\" [width]=\"flowWidth()\" [height]=\"flowHeight()\"></canvas>\n}\n", styles: [":host{display:grid;grid-template-columns:1fr;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}.root-svg{grid-row-start:1;grid-column-start:1}.preview-flow{pointer-events:none;grid-row-start:1;grid-column-start:1}\n"] }]
4226
4344
  }], propDecorators: { view: [{
4227
4345
  type: Input
4228
4346
  }], minZoom: [{