ngx-vflow 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/esm2022/lib/vflow/components/connection/connection.component.mjs +2 -1
  2. package/esm2022/lib/vflow/components/edge/edge.component.mjs +5 -27
  3. package/esm2022/lib/vflow/components/edge-label/edge-label.component.mjs +2 -1
  4. package/esm2022/lib/vflow/components/node/node.component.mjs +3 -3
  5. package/esm2022/lib/vflow/directives/selectable.directive.mjs +1 -6
  6. package/esm2022/lib/vflow/directives/template.directive.mjs +16 -1
  7. package/esm2022/lib/vflow/interfaces/contextable.interface.mjs +2 -0
  8. package/esm2022/lib/vflow/interfaces/template-context.interface.mjs +1 -1
  9. package/esm2022/lib/vflow/models/edge.model.mjs +26 -1
  10. package/esm2022/lib/vflow/models/node.model.mjs +22 -1
  11. package/esm2022/lib/vflow/public-components/custom-template-edge/custom-template-edge.component.mjs +29 -0
  12. package/esm2022/lib/vflow/vflow.mjs +3 -1
  13. package/esm2022/public-api.mjs +2 -1
  14. package/fesm2022/ngx-vflow.mjs +92 -31
  15. package/fesm2022/ngx-vflow.mjs.map +1 -1
  16. package/lib/vflow/components/connection/connection.component.d.ts +2 -6
  17. package/lib/vflow/components/edge/edge.component.d.ts +2 -7
  18. package/lib/vflow/components/edge-label/edge-label.component.d.ts +2 -6
  19. package/lib/vflow/directives/template.directive.d.ts +6 -1
  20. package/lib/vflow/interfaces/contextable.interface.d.ts +5 -0
  21. package/lib/vflow/interfaces/template-context.interface.d.ts +37 -1
  22. package/lib/vflow/models/edge.model.d.ts +20 -1
  23. package/lib/vflow/models/node.model.d.ts +8 -1
  24. package/lib/vflow/public-components/custom-template-edge/custom-template-edge.component.d.ts +17 -0
  25. package/lib/vflow/vflow.d.ts +2 -1
  26. package/package.json +1 -1
  27. package/public-api.d.ts +1 -0
@@ -576,6 +576,9 @@ class EdgeTemplateDirective {
576
576
  constructor() {
577
577
  this.templateRef = inject(TemplateRef);
578
578
  }
579
+ static ngTemplateContextGuard(dir, ctx) {
580
+ return true;
581
+ }
579
582
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
580
583
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: EdgeTemplateDirective, isStandalone: true, selector: "ng-template[edge]", ngImport: i0 }); }
581
584
  }
@@ -590,6 +593,9 @@ class ConnectionTemplateDirective {
590
593
  constructor() {
591
594
  this.templateRef = inject(TemplateRef);
592
595
  }
596
+ static ngTemplateContextGuard(dir, ctx) {
597
+ return true;
598
+ }
593
599
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
594
600
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionTemplateDirective, isStandalone: true, selector: "ng-template[connection]", ngImport: i0 }); }
595
601
  }
@@ -604,6 +610,9 @@ class EdgeLabelHtmlTemplateDirective {
604
610
  constructor() {
605
611
  this.templateRef = inject(TemplateRef);
606
612
  }
613
+ static ngTemplateContextGuard(dir, ctx) {
614
+ return true;
615
+ }
607
616
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeLabelHtmlTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
608
617
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: EdgeLabelHtmlTemplateDirective, isStandalone: true, selector: "ng-template[edgeLabelHtml]", ngImport: i0 }); }
609
618
  }
@@ -618,6 +627,9 @@ class NodeHtmlTemplateDirective {
618
627
  constructor() {
619
628
  this.templateRef = inject(TemplateRef);
620
629
  }
630
+ static ngTemplateContextGuard(dir, ctx) {
631
+ return true;
632
+ }
621
633
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeHtmlTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
622
634
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: NodeHtmlTemplateDirective, isStandalone: true, selector: "ng-template[nodeHtml]", ngImport: i0 }); }
623
635
  }
@@ -632,6 +644,9 @@ class GroupNodeTemplateDirective {
632
644
  constructor() {
633
645
  this.templateRef = inject(TemplateRef);
634
646
  }
647
+ static ngTemplateContextGuard(dir, ctx) {
648
+ return true;
649
+ }
635
650
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: GroupNodeTemplateDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
636
651
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: GroupNodeTemplateDirective, isStandalone: true, selector: "ng-template[groupNode]", ngImport: i0 }); }
637
652
  }
@@ -927,6 +942,9 @@ class NodeModel {
927
942
  this.resizable = signal(false);
928
943
  this.resizing = signal(false);
929
944
  this.resizerTemplate = signal(null);
945
+ this.context = {
946
+ $implicit: {},
947
+ };
930
948
  this.parentId = signal(null);
931
949
  if (isDefined(node.draggable)) {
932
950
  if (isDynamicNode(node)) {
@@ -960,6 +978,24 @@ class NodeModel {
960
978
  this.resizable.set(node.resizable);
961
979
  }
962
980
  }
981
+ if (node.type === 'html-template') {
982
+ this.context = {
983
+ $implicit: {
984
+ node: node,
985
+ selected: this.selected,
986
+ },
987
+ };
988
+ }
989
+ else if (node.type === 'template-group') {
990
+ this.context = {
991
+ $implicit: {
992
+ node: node,
993
+ selected: this.selected.asReadonly(),
994
+ width: this.width,
995
+ height: this.height,
996
+ },
997
+ };
998
+ }
963
999
  }
964
1000
  setPoint(point) {
965
1001
  this.point.set(point);
@@ -1336,6 +1372,30 @@ class EdgeModel {
1336
1372
  ?.handles()
1337
1373
  .find((handle) => handle.rawHandle.type === 'target') ?? null);
1338
1374
  });
1375
+ /**
1376
+ * TODO: not reactive
1377
+ */
1378
+ this.markerStartUrl = computed(() => {
1379
+ const marker = this.edge.markers?.start;
1380
+ return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
1381
+ });
1382
+ /**
1383
+ * TODO: not reactive
1384
+ */
1385
+ this.markerEndUrl = computed(() => {
1386
+ const marker = this.edge.markers?.end;
1387
+ return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
1388
+ });
1389
+ this.context = {
1390
+ $implicit: {
1391
+ // TODO: check if edge could change
1392
+ edge: this.edge,
1393
+ path: computed(() => this.path().path),
1394
+ markerStart: this.markerStartUrl,
1395
+ markerEnd: this.markerEndUrl,
1396
+ selected: this.selected.asReadonly(),
1397
+ },
1398
+ };
1339
1399
  this.edgeLabels = {};
1340
1400
  this.type = edge.type ?? 'default';
1341
1401
  this.curve = edge.curve ?? 'bezier';
@@ -1844,6 +1904,7 @@ class EdgeLabelComponent {
1844
1904
  }), takeUntilDestroyed(this.destroyRef))
1845
1905
  .subscribe();
1846
1906
  }
1907
+ // TODO: move to model with Contextable interface
1847
1908
  getLabelContext() {
1848
1909
  return {
1849
1910
  $implicit: {
@@ -2138,33 +2199,12 @@ class EdgeComponent {
2138
2199
  this.model = input.required();
2139
2200
  this.edgeTemplate = input();
2140
2201
  this.edgeLabelHtmlTemplate = input();
2141
- this.interactiveEdgeRef = viewChild.required('interactiveEdge');
2142
- this.markerStartUrl = computed(() => {
2143
- const marker = this.model().edge.markers?.start;
2144
- return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
2145
- });
2146
- this.markerEndUrl = computed(() => {
2147
- const marker = this.model().edge.markers?.end;
2148
- return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
2149
- });
2150
2202
  this.isReconnecting = computed(() => {
2151
2203
  const status = this.flowStatusService.status();
2152
2204
  const isReconnecting = status.state === 'reconnection-start' || status.state === 'reconnection-validation';
2153
2205
  return isReconnecting && status.payload.oldEdge === this.model();
2154
2206
  });
2155
2207
  }
2156
- ngOnInit() {
2157
- this.edgeContext = {
2158
- $implicit: {
2159
- // TODO: check if edge could change
2160
- edge: this.model().edge,
2161
- path: computed(() => this.model().path().path),
2162
- markerStart: this.markerStartUrl,
2163
- markerEnd: this.markerEndUrl,
2164
- selected: this.model().selected.asReadonly(),
2165
- },
2166
- };
2167
- }
2168
2208
  select() {
2169
2209
  if (this.flowSettingsService.entitiesSelectable()) {
2170
2210
  this.selectionService.select(this.model());
@@ -2181,14 +2221,14 @@ class EdgeComponent {
2181
2221
  this.connectionController?.startReconnection(handle, this.model());
2182
2222
  }
2183
2223
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2184
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, viewQueries: [{ propertyName: "interactiveEdgeRef", first: true, predicate: ["interactiveEdge"], descendants: true, isSignal: true }], ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path\n #interactiveEdge\n class=\"interactive-edge\"\n [attr.d]=\"model().path().path\"\n (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\" />\n\n <svg:path #interactiveEdge class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"pull()\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2224
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EdgeComponent, isStandalone: true, selector: "g[edge]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, edgeTemplate: { classPropertyName: "edgeTemplate", publicName: "edgeTemplate", isSignal: true, isRequired: false, transformFunction: null }, edgeLabelHtmlTemplate: { classPropertyName: "edgeLabelHtmlTemplate", publicName: "edgeLabelHtmlTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.visibility": "isReconnecting() ? \"hidden\" : \"visible\"" }, classAttribute: "selectable" }, ngImport: i0, template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerStartUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }, { kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2185
2225
  }
2186
2226
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, decorators: [{
2187
2227
  type: Component,
2188
2228
  args: [{ standalone: true, selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2189
2229
  class: 'selectable',
2190
2230
  '[style.visibility]': 'isReconnecting() ? "hidden" : "visible"',
2191
- }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path\n #interactiveEdge\n class=\"interactive-edge\"\n [attr.d]=\"model().path().path\"\n (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\" />\n\n <svg:path #interactiveEdge class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"pull()\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2231
+ }, imports: [NgTemplateOutlet, EdgeLabelComponent, PointerDirective], template: "@if (model().type === 'default') {\n <svg:path\n class=\"edge\"\n [attr.d]=\"model().path().path\"\n [attr.marker-start]=\"model().markerStartUrl()\"\n [attr.marker-end]=\"model().markerStartUrl()\"\n [class.edge_selected]=\"model().selected()\" />\n\n <svg:path class=\"interactive-edge\" [attr.d]=\"model().path().path\" (pointerStart)=\"select(); pull()\" />\n}\n\n@if (model().type === 'template' && edgeTemplate()) {\n @if (edgeTemplate(); as edgeTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n }\n}\n\n@if (model().edgeLabels.start; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.start\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.center; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.center\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().edgeLabels.end; as label) {\n <svg:g\n edgeLabel\n [model]=\"label\"\n [point]=\"model().path().points.end\"\n [edgeModel]=\"model()\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate()\" />\n}\n\n@if (model().sourceHandle() && model().targetHandle()) {\n @if (model().reconnectable === true || model().reconnectable === 'source') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().sourceHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().sourceHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().targetHandle()!)\" />\n }\n\n @if (model().reconnectable === true || model().reconnectable === 'target') {\n <svg:circle\n class=\"reconnect-handle\"\n r=\"10\"\n [attr.cx]=\"model().targetHandle()!.pointAbsolute().x\"\n [attr.cy]=\"model().targetHandle()!.pointAbsolute().y\"\n (pointerStart)=\"startReconnection($event, model().sourceHandle()!)\" />\n }\n}\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}.interactive-edge{fill:none;stroke-width:20;stroke:transparent}.reconnect-handle{fill:transparent;cursor:move}\n"] }]
2192
2232
  }] });
2193
2233
 
2194
2234
  class HandleService {
@@ -2713,7 +2753,7 @@ class NodeComponent {
2713
2753
  }
2714
2754
  }
2715
2755
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2716
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], ngImport: i0, template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: { node: model().node, selected: model().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: model().node,\n selected: model().selected,\n width: model().width,\n height: model().height,\n },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }, { kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ResizableComponent, selector: "[resizable]", inputs: ["resizable", "resizerColor", "gap"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: NodeHandlesControllerDirective, selector: "[nodeHandlesController]" }, { kind: "directive", type: NodeResizeControllerDirective, selector: "[nodeResizeController]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2756
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: NodeComponent, isStandalone: true, selector: "g[node]", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null }, nodeTemplate: { classPropertyName: "nodeTemplate", publicName: "nodeTemplate", isSignal: true, isRequired: false, transformFunction: null }, groupNodeTemplate: { classPropertyName: "groupNodeTemplate", publicName: "groupNodeTemplate", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "vflow-node" }, providers: [HandleService, NodeAccessorService], ngImport: i0, template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: PointerDirective, selector: "[pointerStart], [pointerEnd], [pointerOver], [pointerOut]", outputs: ["pointerOver", "pointerOut", "pointerStart", "pointerEnd"] }, { kind: "component", type: DefaultNodeComponent, selector: "default-node", inputs: ["selected"] }, { kind: "component", type: HandleComponent, selector: "handle", inputs: ["position", "type", "id", "template"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: ResizableComponent, selector: "[resizable]", inputs: ["resizable", "resizerColor", "gap"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }, { kind: "directive", type: NodeHandlesControllerDirective, selector: "[nodeHandlesController]" }, { kind: "directive", type: NodeResizeControllerDirective, selector: "[nodeResizeController]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2717
2757
  }
2718
2758
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeComponent, decorators: [{
2719
2759
  type: Component,
@@ -2729,7 +2769,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
2729
2769
  HandleSizeControllerDirective,
2730
2770
  NodeHandlesControllerDirective,
2731
2771
  NodeResizeControllerDirective,
2732
- ], template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: { node: model().node, selected: model().selected },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"{\n $implicit: {\n node: model().node,\n selected: model().selected,\n width: model().width,\n height: model().height,\n },\n }\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
2772
+ ], template: "<!-- Default node -->\n@if (model().node.type === 'default') {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode(); selectNode()\">\n <default-node\n nodeHandlesController\n [selected]=\"model().selected()\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\"\n [style.max-width]=\"model().styleWidth()\"\n [style.max-height]=\"model().styleHeight()\">\n <div [outerHTML]=\"model().text()\"></div>\n\n <handle type=\"source\" position=\"right\" />\n <handle type=\"target\" position=\"left\" />\n </default-node>\n </svg:foreignObject>\n}\n\n<!-- Template node -->\n@if (model().node.type === 'html-template' && nodeTemplate()) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngTemplateOutlet]=\"nodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Component node -->\n@if (model().isComponentType) {\n <svg:foreignObject\n class=\"selectable\"\n [attr.width]=\"model().foWidth()\"\n [attr.height]=\"model().foHeight()\"\n (pointerStart)=\"pullNode()\">\n <div\n nodeHandlesController\n nodeResizeController\n class=\"wrapper\"\n [style.width]=\"model().styleWidth()\"\n [style.height]=\"model().styleHeight()\">\n <ng-container\n [ngComponentOutlet]=\"$any(model().node.type)\"\n [ngComponentOutletInputs]=\"model().componentTypeInputs\"\n [ngComponentOutletInjector]=\"injector\" />\n </div>\n </svg:foreignObject>\n}\n\n<!-- Default group node -->\n@if (model().node.type === 'default-group') {\n <svg:rect\n class=\"default-group-node\"\n rx=\"5\"\n ry=\"5\"\n [resizable]=\"model().resizable()\"\n [gap]=\"3\"\n [resizerColor]=\"model().color()\"\n [class.default-group-node_selected]=\"model().selected()\"\n [attr.width]=\"model().size().width\"\n [attr.height]=\"model().size().height\"\n [style.stroke]=\"model().color()\"\n [style.fill]=\"model().color()\"\n (pointerStart)=\"pullNode(); selectNode()\" />\n}\n\n<!-- Template group node -->\n@if (model().node.type === 'template-group' && groupNodeTemplate()) {\n <svg:g class=\"selectable\" nodeHandlesController (pointerStart)=\"pullNode()\">\n <ng-container\n [ngTemplateOutlet]=\"groupNodeTemplate() ?? null\"\n [ngTemplateOutletContext]=\"model().context\"\n [ngTemplateOutletInjector]=\"injector\" />\n </svg:g>\n}\n\n<!-- Resizer -->\n@if (model().resizerTemplate(); as template) {\n @if (model().resizable()) {\n <ng-template [ngTemplateOutlet]=\"template\" />\n }\n}\n\n<!-- Handles -->\n@for (handle of model().handles(); track handle) {\n @if (!handle.template) {\n <svg:circle\n class=\"default-handle\"\n r=\"5\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\" />\n }\n\n @if (handle.template) {\n <svg:g\n [handleSizeController]=\"handle\"\n (pointerStart)=\"startConnection($event, handle)\"\n (pointerEnd)=\"endConnection()\">\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n }\n\n @if (showMagnet()) {\n <svg:circle\n class=\"magnet\"\n [attr.r]=\"model().magnetRadius\"\n [attr.cx]=\"handle.hostOffset().x\"\n [attr.cy]=\"handle.hostOffset().y\"\n (pointerEnd)=\"endConnection(); resetValidateConnection(handle)\"\n (pointerOver)=\"validateConnection(handle)\"\n (pointerOut)=\"resetValidateConnection(handle)\" />\n }\n}\n\n<!-- Toolbar -->\n@if (toolbar(); as toolbar) {\n <svg:foreignObject\n [attr.width]=\"toolbar.size().width\"\n [attr.height]=\"toolbar.size().height\"\n [attr.transform]=\"toolbar.transform()\">\n <ng-container [ngTemplateOutlet]=\"toolbar.template()\" />\n </svg:foreignObject>\n}\n", styles: [".magnet{opacity:0}.wrapper{display:table-cell}.default-group-node{stroke-width:1.5px;fill-opacity:.05}.default-group-node_selected{stroke-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
2733
2773
  }] });
2734
2774
 
2735
2775
  class ConnectionComponent {
@@ -2791,6 +2831,7 @@ class ConnectionComponent {
2791
2831
  });
2792
2832
  this.defaultColor = 'rgb(177, 177, 183)';
2793
2833
  }
2834
+ // TODO: move context to model
2794
2835
  getContext() {
2795
2836
  return {
2796
2837
  $implicit: {
@@ -3461,11 +3502,6 @@ class SelectableDirective {
3461
3502
  return null;
3462
3503
  }
3463
3504
  getEvent$() {
3464
- if (this.parentEdge) {
3465
- // get not the edge itself, but the interactive edge (which is more UX friendly)
3466
- const interactiveEdge = this.parentEdge.interactiveEdgeRef().nativeElement;
3467
- return merge(fromEvent(interactiveEdge, 'mousedown'), fromEvent(interactiveEdge, 'touchstart'));
3468
- }
3469
3505
  return merge(fromEvent(this.host.nativeElement, 'mousedown'), fromEvent(this.host.nativeElement, 'touchstart'));
3470
3506
  }
3471
3507
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
@@ -3683,6 +3719,7 @@ const Vflow = [
3683
3719
  SelectableDirective,
3684
3720
  MiniMapComponent,
3685
3721
  NodeToolbarComponent,
3722
+ CustomTemplateEdgeComponent,
3686
3723
  DragHandleDirective,
3687
3724
  ConnectionControllerDirective,
3688
3725
  NodeHtmlTemplateDirective,
@@ -3693,6 +3730,30 @@ const Vflow = [
3693
3730
  HandleTemplateDirective,
3694
3731
  ];
3695
3732
 
3733
+ class CustomTemplateEdgeComponent {
3734
+ constructor() {
3735
+ this.edge = inject(EdgeComponent);
3736
+ this.flowSettingsService = inject(FlowSettingsService);
3737
+ this.edgeRenderingService = inject(EdgeRenderingService);
3738
+ this.model = this.edge.model();
3739
+ this.context = this.model.context.$implicit;
3740
+ }
3741
+ pull() {
3742
+ if (this.flowSettingsService.elevateEdgesOnSelect()) {
3743
+ this.edgeRenderingService.pull(this.model);
3744
+ }
3745
+ }
3746
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CustomTemplateEdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3747
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: CustomTemplateEdgeComponent, isStandalone: true, selector: "g[customTemplateEdge]", host: { listeners: { "mousedown": "pull()", "touchstart": "pull()" } }, ngImport: i0, template: "<ng-content />\n\n<svg:path #interactiveEdge class=\"interactive-edge\" [attr.d]=\"context.path()\" />\n", styles: [".interactive-edge{fill:none;stroke-width:20;stroke:transparent}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3748
+ }
3749
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CustomTemplateEdgeComponent, decorators: [{
3750
+ type: Component,
3751
+ args: [{ selector: 'g[customTemplateEdge]', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, host: {
3752
+ '(mousedown)': 'pull()',
3753
+ '(touchstart)': 'pull()',
3754
+ }, template: "<ng-content />\n\n<svg:path #interactiveEdge class=\"interactive-edge\" [attr.d]=\"context.path()\" />\n", styles: [".interactive-edge{fill:none;stroke-width:20;stroke:transparent}\n"] }]
3755
+ }] });
3756
+
3696
3757
  const mockModel = () => new NodeModel({ id: 'mock', type: 'default', point: { x: 0, y: 0 } });
3697
3758
  function provideCustomNodeMocks() {
3698
3759
  return [
@@ -4264,5 +4325,5 @@ const VflowMocks = [
4264
4325
  * Generated bundle index. Do not edit.
4265
4326
  */
4266
4327
 
4267
- export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionControllerMockDirective, ConnectionTemplateDirective, ConnectionTemplateMockDirective, CustomDynamicNodeComponent, CustomNodeComponent, DragHandleDirective, DragHandleMockDirective, EdgeLabelHtmlTemplateDirective, EdgeLabelHtmlTemplateMockDirective, EdgeTemplateDirective, EdgeTemplateMockDirective, GroupNodeTemplateDirective, GroupNodeTemplateMockDirective, HandleComponent, HandleMockComponent, HandleTemplateDirective, HandleTemplateMockDirective, MiniMapComponent, MiniMapMockComponent, NodeHtmlTemplateDirective, NodeHtmlTemplateMockDirective, NodeToolbarComponent, NodeToolbarMockComponent, NodeToolbarWrapperDirective, ResizableComponent, ResizableMockComponent, SelectableDirective, SelectableMockDirective, Vflow, VflowComponent, VflowMockComponent, VflowMocks, isComponentDynamicNode, isComponentStaticNode, isDefaultDynamicGroupNode, isDefaultDynamicNode, isDefaultStaticGroupNode, isDefaultStaticNode, isDynamicNode, isStaticNode, isTemplateDynamicGroupNode, isTemplateDynamicNode, isTemplateStaticGroupNode, isTemplateStaticNode, provideCustomNodeMocks };
4328
+ export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionControllerMockDirective, ConnectionTemplateDirective, ConnectionTemplateMockDirective, CustomDynamicNodeComponent, CustomNodeComponent, CustomTemplateEdgeComponent, DragHandleDirective, DragHandleMockDirective, EdgeLabelHtmlTemplateDirective, EdgeLabelHtmlTemplateMockDirective, EdgeTemplateDirective, EdgeTemplateMockDirective, GroupNodeTemplateDirective, GroupNodeTemplateMockDirective, HandleComponent, HandleMockComponent, HandleTemplateDirective, HandleTemplateMockDirective, MiniMapComponent, MiniMapMockComponent, NodeHtmlTemplateDirective, NodeHtmlTemplateMockDirective, NodeToolbarComponent, NodeToolbarMockComponent, NodeToolbarWrapperDirective, ResizableComponent, ResizableMockComponent, SelectableDirective, SelectableMockDirective, Vflow, VflowComponent, VflowMockComponent, VflowMocks, isComponentDynamicNode, isComponentStaticNode, isDefaultDynamicGroupNode, isDefaultDynamicNode, isDefaultStaticGroupNode, isDefaultStaticNode, isDynamicNode, isStaticNode, isTemplateDynamicGroupNode, isTemplateDynamicNode, isTemplateStaticGroupNode, isTemplateStaticNode, provideCustomNodeMocks };
4268
4329
  //# sourceMappingURL=ngx-vflow.mjs.map