ngx-vflow 1.4.1 → 1.5.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.
- package/esm2022/lib/vflow/components/connection/connection.component.mjs +3 -3
- package/esm2022/lib/vflow/components/edge/edge.component.mjs +30 -5
- package/esm2022/lib/vflow/components/node/node.component.mjs +4 -2
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +15 -3
- package/esm2022/lib/vflow/directives/connection-controller.directive.mjs +55 -37
- package/esm2022/lib/vflow/directives/root-svg-context.directive.mjs +2 -2
- package/esm2022/lib/vflow/directives/selectable.directive.mjs +19 -11
- package/esm2022/lib/vflow/interfaces/connection.interface.mjs +1 -1
- package/esm2022/lib/vflow/interfaces/edge.interface.mjs +1 -1
- package/esm2022/lib/vflow/models/edge.model.mjs +25 -23
- package/esm2022/lib/vflow/public-components/handle/handle.component.mjs +18 -21
- package/esm2022/lib/vflow/public-components/node-toolbar/node-toolbar.component.mjs +1 -1
- package/esm2022/lib/vflow/services/edge-rendering.service.mjs +28 -0
- package/esm2022/lib/vflow/services/flow-settings.service.mjs +2 -1
- package/esm2022/lib/vflow/services/flow-status.service.mjs +13 -1
- package/esm2022/lib/vflow/testing-utils/component-mocks/handle-mock.component.mjs +3 -1
- package/esm2022/lib/vflow/testing-utils/component-mocks/minimap-mock.component.mjs +3 -1
- package/esm2022/lib/vflow/testing-utils/component-mocks/node-toolbar-mock.component.mjs +5 -1
- package/esm2022/lib/vflow/testing-utils/component-mocks/resizable-mock.component.mjs +5 -1
- package/esm2022/lib/vflow/testing-utils/component-mocks/vflow-mock.component.mjs +50 -22
- package/esm2022/lib/vflow/testing-utils/directive-mocks/connection-controller-mock.directive.mjs +14 -2
- package/esm2022/lib/vflow/testing-utils/directive-mocks/drag-handle-mock.directive.mjs +1 -1
- package/esm2022/lib/vflow/testing-utils/directive-mocks/selectable-mock.directive.mjs +1 -1
- package/esm2022/lib/vflow/testing-utils/directive-mocks/template-mock.directive.mjs +1 -1
- package/esm2022/lib/vflow/testing-utils/types.mjs +2 -0
- package/fesm2022/ngx-vflow.mjs +374 -243
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/edge/edge.component.d.ts +10 -2
- package/lib/vflow/components/vflow/vflow.component.d.ts +6 -1
- package/lib/vflow/directives/connection-controller.directive.d.ts +5 -2
- package/lib/vflow/directives/selectable.directive.d.ts +4 -1
- package/lib/vflow/interfaces/connection.interface.d.ts +5 -0
- package/lib/vflow/interfaces/edge.interface.d.ts +1 -0
- package/lib/vflow/models/edge.model.d.ts +4 -0
- package/lib/vflow/public-components/handle/handle.component.d.ts +3 -6
- package/lib/vflow/public-components/node-toolbar/node-toolbar.component.d.ts +1 -1
- package/lib/vflow/services/edge-rendering.service.d.ts +10 -0
- package/lib/vflow/services/flow-settings.service.d.ts +1 -0
- package/lib/vflow/services/flow-status.service.d.ts +24 -1
- package/lib/vflow/testing-utils/component-mocks/handle-mock.component.d.ts +5 -2
- package/lib/vflow/testing-utils/component-mocks/minimap-mock.component.d.ts +5 -2
- package/lib/vflow/testing-utils/component-mocks/node-toolbar-mock.component.d.ts +6 -1
- package/lib/vflow/testing-utils/component-mocks/resizable-mock.component.d.ts +6 -1
- package/lib/vflow/testing-utils/component-mocks/vflow-mock.component.d.ts +27 -13
- package/lib/vflow/testing-utils/directive-mocks/connection-controller-mock.directive.d.ts +12 -3
- package/lib/vflow/testing-utils/directive-mocks/drag-handle-mock.directive.d.ts +3 -1
- package/lib/vflow/testing-utils/directive-mocks/selectable-mock.directive.d.ts +3 -1
- package/lib/vflow/testing-utils/directive-mocks/template-mock.directive.d.ts +8 -6
- package/lib/vflow/testing-utils/types.d.ts +1 -0
- package/package.json +1 -1
- package/esm2022/lib/vflow/decorators/run-in-injection-context.decorator.mjs +0 -18
- package/lib/vflow/decorators/run-in-injection-context.decorator.d.ts +0 -5
package/fesm2022/ngx-vflow.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy,
|
|
2
|
+
import { signal, computed, Injectable, inject, ElementRef, Directive, effect, untracked, TemplateRef, DestroyRef, EventEmitter, OutputEmitterRef, input, NgZone, viewChild, Component, ChangeDetectionStrategy, output, HostListener, Injector, runInInjectionContext, contentChild, Input, forwardRef } from '@angular/core';
|
|
3
3
|
import { select } from 'd3-selection';
|
|
4
4
|
import { zoomIdentity, zoom } from 'd3-zoom';
|
|
5
5
|
import { switchMap, merge, fromEvent, tap, Subject, Observable, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, animationFrameScheduler, share, startWith, of } from 'rxjs';
|
|
@@ -151,6 +151,7 @@ class FlowSettingsService {
|
|
|
151
151
|
constructor() {
|
|
152
152
|
this.entitiesSelectable = signal(true);
|
|
153
153
|
this.elevateNodesOnSelect = signal(true);
|
|
154
|
+
this.elevateEdgesOnSelect = signal(true);
|
|
154
155
|
/**
|
|
155
156
|
* @see {VflowComponent.view}
|
|
156
157
|
*/
|
|
@@ -677,12 +678,24 @@ class FlowStatusService {
|
|
|
677
678
|
setConnectionStartStatus(source, sourceHandle) {
|
|
678
679
|
this.status.set({ state: 'connection-start', payload: { source, sourceHandle } });
|
|
679
680
|
}
|
|
681
|
+
setReconnectionStartStatus(source, sourceHandle, oldEdge) {
|
|
682
|
+
this.status.set({ state: 'reconnection-start', payload: { source, sourceHandle, oldEdge } });
|
|
683
|
+
}
|
|
680
684
|
setConnectionValidationStatus(valid, source, target, sourceHandle, targetHandle) {
|
|
681
685
|
this.status.set({ state: 'connection-validation', payload: { source, target, sourceHandle, targetHandle, valid } });
|
|
682
686
|
}
|
|
687
|
+
setReconnectionValidationStatus(valid, source, target, sourceHandle, targetHandle, oldEdge) {
|
|
688
|
+
this.status.set({
|
|
689
|
+
state: 'reconnection-validation',
|
|
690
|
+
payload: { source, target, sourceHandle, targetHandle, valid, oldEdge },
|
|
691
|
+
});
|
|
692
|
+
}
|
|
683
693
|
setConnectionEndStatus(source, target, sourceHandle, targetHandle) {
|
|
684
694
|
this.status.set({ state: 'connection-end', payload: { source, target, sourceHandle, targetHandle } });
|
|
685
695
|
}
|
|
696
|
+
setReconnectionEndStatus(source, target, sourceHandle, targetHandle, oldEdge) {
|
|
697
|
+
this.status.set({ state: 'reconnection-end', payload: { source, target, sourceHandle, targetHandle, oldEdge } });
|
|
698
|
+
}
|
|
686
699
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
687
700
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FlowStatusService }); }
|
|
688
701
|
}
|
|
@@ -1254,6 +1267,7 @@ class EdgeModel {
|
|
|
1254
1267
|
this.target = signal(undefined);
|
|
1255
1268
|
this.selected = signal(false);
|
|
1256
1269
|
this.selected$ = toObservable(this.selected);
|
|
1270
|
+
this.renderOrder = signal(0);
|
|
1257
1271
|
this.detached = computed(() => {
|
|
1258
1272
|
const source = this.source();
|
|
1259
1273
|
const target = this.target();
|
|
@@ -1278,28 +1292,8 @@ class EdgeModel {
|
|
|
1278
1292
|
});
|
|
1279
1293
|
this.detached$ = toObservable(this.detached);
|
|
1280
1294
|
this.path = computed(() => {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
source = this.source()
|
|
1284
|
-
?.handles()
|
|
1285
|
-
.find((handle) => handle.rawHandle.id === this.edge.sourceHandle);
|
|
1286
|
-
}
|
|
1287
|
-
else {
|
|
1288
|
-
source = this.source()
|
|
1289
|
-
?.handles()
|
|
1290
|
-
.find((handle) => handle.rawHandle.type === 'source');
|
|
1291
|
-
}
|
|
1292
|
-
let target;
|
|
1293
|
-
if (this.edge.targetHandle) {
|
|
1294
|
-
target = this.target()
|
|
1295
|
-
?.handles()
|
|
1296
|
-
.find((handle) => handle.rawHandle.id === this.edge.targetHandle);
|
|
1297
|
-
}
|
|
1298
|
-
else {
|
|
1299
|
-
target = this.target()
|
|
1300
|
-
?.handles()
|
|
1301
|
-
.find((handle) => handle.rawHandle.type === 'target');
|
|
1302
|
-
}
|
|
1295
|
+
const source = this.sourceHandle();
|
|
1296
|
+
const target = this.targetHandle();
|
|
1303
1297
|
// TODO: don't like this
|
|
1304
1298
|
if (!source || !target) {
|
|
1305
1299
|
return {
|
|
@@ -1322,9 +1316,30 @@ class EdgeModel {
|
|
|
1322
1316
|
return smoothStepPath(source.pointAbsolute(), target.pointAbsolute(), source.rawHandle.position, target.rawHandle.position, 0);
|
|
1323
1317
|
}
|
|
1324
1318
|
});
|
|
1319
|
+
this.sourceHandle = computed(() => {
|
|
1320
|
+
if (this.edge.sourceHandle) {
|
|
1321
|
+
return (this.source()
|
|
1322
|
+
?.handles()
|
|
1323
|
+
.find((handle) => handle.rawHandle.id === this.edge.sourceHandle) ?? null);
|
|
1324
|
+
}
|
|
1325
|
+
return (this.source()
|
|
1326
|
+
?.handles()
|
|
1327
|
+
.find((handle) => handle.rawHandle.type === 'source') ?? null);
|
|
1328
|
+
});
|
|
1329
|
+
this.targetHandle = computed(() => {
|
|
1330
|
+
if (this.edge.targetHandle) {
|
|
1331
|
+
return (this.target()
|
|
1332
|
+
?.handles()
|
|
1333
|
+
.find((handle) => handle.rawHandle.id === this.edge.targetHandle) ?? null);
|
|
1334
|
+
}
|
|
1335
|
+
return (this.target()
|
|
1336
|
+
?.handles()
|
|
1337
|
+
.find((handle) => handle.rawHandle.type === 'target') ?? null);
|
|
1338
|
+
});
|
|
1325
1339
|
this.edgeLabels = {};
|
|
1326
1340
|
this.type = edge.type ?? 'default';
|
|
1327
1341
|
this.curve = edge.curve ?? 'bezier';
|
|
1342
|
+
this.reconnectable = edge.reconnectable ?? false;
|
|
1328
1343
|
if (edge.edgeLabels?.start)
|
|
1329
1344
|
this.edgeLabels.start = new EdgeLabelModel(edge.edgeLabels.start);
|
|
1330
1345
|
if (edge.edgeLabels?.center)
|
|
@@ -1845,76 +1860,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
1845
1860
|
args: [{ standalone: true, selector: 'g[edgeLabel]', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet], template: "@if (model(); as model) {\n @if (model.edgeLabel.type === 'html-template' && htmlTemplate()) {\n @if (htmlTemplate(); as htmlTemplate) {\n <svg:foreignObject\n [attr.x]=\"edgeLabelPoint().x\"\n [attr.y]=\"edgeLabelPoint().y\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <div #edgeLabelWrapper class=\"edge-label-wrapper\">\n <ng-container *ngTemplateOutlet=\"htmlTemplate; context: getLabelContext()\" />\n </div>\n </svg:foreignObject>\n }\n }\n\n @if (model.edgeLabel.type === 'default') {\n <svg:foreignObject\n [attr.x]=\"edgeLabelPoint().x\"\n [attr.y]=\"edgeLabelPoint().y\"\n [attr.width]=\"model.size().width\"\n [attr.height]=\"model.size().height\">\n <div #edgeLabelWrapper class=\"edge-label-wrapper\" [style]=\"edgeLabelStyle()\">\n {{ model.edgeLabel.text }}\n </div>\n </svg:foreignObject>\n }\n}\n", styles: [".edge-label-wrapper{width:max-content;margin-top:1px;margin-left:1px}\n"] }]
|
|
1846
1861
|
}] });
|
|
1847
1862
|
|
|
1848
|
-
class EdgeComponent {
|
|
1849
|
-
constructor() {
|
|
1850
|
-
this.injector = inject(Injector);
|
|
1851
|
-
this.selectionService = inject(SelectionService);
|
|
1852
|
-
this.flowSettingsService = inject(FlowSettingsService);
|
|
1853
|
-
this.model = input.required();
|
|
1854
|
-
this.edgeTemplate = input();
|
|
1855
|
-
this.edgeLabelHtmlTemplate = input();
|
|
1856
|
-
this.markerStartUrl = computed(() => {
|
|
1857
|
-
const marker = this.model().edge.markers?.start;
|
|
1858
|
-
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
1859
|
-
});
|
|
1860
|
-
this.markerEndUrl = computed(() => {
|
|
1861
|
-
const marker = this.model().edge.markers?.end;
|
|
1862
|
-
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
1863
|
-
});
|
|
1864
|
-
}
|
|
1865
|
-
ngOnInit() {
|
|
1866
|
-
this.edgeContext = {
|
|
1867
|
-
$implicit: {
|
|
1868
|
-
// TODO: check if edge could change
|
|
1869
|
-
edge: this.model().edge,
|
|
1870
|
-
path: computed(() => this.model().path().path),
|
|
1871
|
-
markerStart: this.markerStartUrl,
|
|
1872
|
-
markerEnd: this.markerEndUrl,
|
|
1873
|
-
selected: this.model().selected.asReadonly(),
|
|
1874
|
-
},
|
|
1875
|
-
};
|
|
1876
|
-
}
|
|
1877
|
-
onEdgeMouseDown() {
|
|
1878
|
-
if (this.flowSettingsService.entitiesSelectable()) {
|
|
1879
|
-
this.selectionService.select(this.model());
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1883
|
-
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: { 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]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n [class.edge_selected]=\"model().selected()\"\n (mousedown)=\"onEdgeMouseDown()\" />\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}\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", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1884
|
-
}
|
|
1885
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, decorators: [{
|
|
1886
|
-
type: Component,
|
|
1887
|
-
args: [{ standalone: true, selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1888
|
-
class: 'selectable',
|
|
1889
|
-
}, imports: [NgTemplateOutlet, EdgeLabelComponent], 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 (mousedown)=\"onEdgeMouseDown()\" />\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}\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", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"] }]
|
|
1890
|
-
}] });
|
|
1891
|
-
|
|
1892
|
-
class HandleService {
|
|
1893
|
-
constructor() {
|
|
1894
|
-
this.node = signal(null);
|
|
1895
|
-
}
|
|
1896
|
-
createHandle(newHandle) {
|
|
1897
|
-
const node = this.node();
|
|
1898
|
-
if (node) {
|
|
1899
|
-
node.handles.update((handles) => [...handles, newHandle]);
|
|
1900
|
-
}
|
|
1901
|
-
}
|
|
1902
|
-
destroyHandle(handleToDestoy) {
|
|
1903
|
-
const node = this.node();
|
|
1904
|
-
if (node) {
|
|
1905
|
-
node.handles.update((handles) => handles.filter((handle) => handle !== handleToDestoy));
|
|
1906
|
-
}
|
|
1907
|
-
}
|
|
1908
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1909
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService }); }
|
|
1910
|
-
}
|
|
1911
|
-
__decorate([
|
|
1912
|
-
Microtask // TODO fixes rendering of handle for group node
|
|
1913
|
-
], HandleService.prototype, "createHandle", null);
|
|
1914
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService, decorators: [{
|
|
1915
|
-
type: Injectable
|
|
1916
|
-
}], propDecorators: { createHandle: [] } });
|
|
1917
|
-
|
|
1918
1863
|
/**
|
|
1919
1864
|
* This function contains a hack-y behavior.
|
|
1920
1865
|
* If the handles are of the same type (source-source or target-target),
|
|
@@ -1960,42 +1905,24 @@ class ConnectionControllerDirective {
|
|
|
1960
1905
|
* @todo add connect event and deprecate onConnect
|
|
1961
1906
|
*/
|
|
1962
1907
|
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
|
1963
|
-
this.onConnect = outputFromObservable(toObservable(this.statusService.status).pipe(filter((status) => status.state === 'connection-end'), map((status) =>
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
const adjusted = adjustDirection({
|
|
1970
|
-
source: status.payload.source,
|
|
1971
|
-
sourceHandle: status.payload.sourceHandle,
|
|
1972
|
-
target: status.payload.target,
|
|
1973
|
-
targetHandle: status.payload.targetHandle,
|
|
1974
|
-
});
|
|
1975
|
-
source = adjusted.source;
|
|
1976
|
-
target = adjusted.target;
|
|
1977
|
-
sourceHandle = adjusted.sourceHandle;
|
|
1978
|
-
targetHandle = adjusted.targetHandle;
|
|
1979
|
-
}
|
|
1980
|
-
const sourceId = source.node.id;
|
|
1981
|
-
const targetId = target.node.id;
|
|
1982
|
-
const sourceHandleId = sourceHandle.rawHandle.id;
|
|
1983
|
-
const targetHandleId = targetHandle.rawHandle.id;
|
|
1984
|
-
return {
|
|
1985
|
-
source: sourceId,
|
|
1986
|
-
target: targetId,
|
|
1987
|
-
sourceHandle: sourceHandleId,
|
|
1988
|
-
targetHandle: targetHandleId,
|
|
1989
|
-
};
|
|
1990
|
-
}), tap(() => this.statusService.setIdleStatus()), filter((connection) => this.flowEntitiesService.connection().validator(connection))));
|
|
1908
|
+
this.onConnect = outputFromObservable(toObservable(this.statusService.status).pipe(filter((status) => status.state === 'connection-end'), map((status) => statusToConnection(status, this.isStrictMode())), tap(() => this.statusService.setIdleStatus()), filter((connection) => this.flowEntitiesService.connection().validator(connection))));
|
|
1909
|
+
this.onReconnect = outputFromObservable(toObservable(this.statusService.status).pipe(filter((status) => status.state === 'reconnection-end'), map((status) => {
|
|
1910
|
+
const connection = statusToConnection(status, this.isStrictMode());
|
|
1911
|
+
const oldEdge = status.payload.oldEdge.edge;
|
|
1912
|
+
return { connection, oldEdge };
|
|
1913
|
+
}), tap(() => this.statusService.setIdleStatus()), filter(({ connection }) => this.flowEntitiesService.connection().validator(connection))));
|
|
1991
1914
|
this.isStrictMode = computed(() => this.flowEntitiesService.connection().mode === 'strict');
|
|
1992
1915
|
}
|
|
1993
1916
|
startConnection(handle) {
|
|
1994
1917
|
this.statusService.setConnectionStartStatus(handle.parentNode, handle);
|
|
1995
1918
|
}
|
|
1919
|
+
startReconnection(handle, oldEdge) {
|
|
1920
|
+
this.statusService.setReconnectionStartStatus(handle.parentNode, handle, oldEdge);
|
|
1921
|
+
}
|
|
1996
1922
|
validateConnection(handle) {
|
|
1997
1923
|
const status = this.statusService.status();
|
|
1998
|
-
if (status.state === 'connection-start') {
|
|
1924
|
+
if (status.state === 'connection-start' || status.state === 'reconnection-start') {
|
|
1925
|
+
const isReconnection = status.state === 'reconnection-start';
|
|
1999
1926
|
let source = status.payload.source;
|
|
2000
1927
|
let target = handle.parentNode;
|
|
2001
1928
|
let sourceHandle = status.payload.sourceHandle;
|
|
@@ -2024,89 +1951,97 @@ class ConnectionControllerDirective {
|
|
|
2024
1951
|
handle.state.set(valid ? 'valid' : 'invalid');
|
|
2025
1952
|
// status is about how we draw connection, so we don't need
|
|
2026
1953
|
// swapped diretion here
|
|
2027
|
-
|
|
1954
|
+
isReconnection
|
|
1955
|
+
? this.statusService.setReconnectionValidationStatus(valid, status.payload.source, handle.parentNode, status.payload.sourceHandle, handle, status.payload.oldEdge)
|
|
1956
|
+
: this.statusService.setConnectionValidationStatus(valid, status.payload.source, handle.parentNode, status.payload.sourceHandle, handle);
|
|
2028
1957
|
}
|
|
2029
1958
|
}
|
|
2030
1959
|
resetValidateConnection(targetHandle) {
|
|
2031
1960
|
targetHandle.state.set('idle');
|
|
2032
1961
|
// drop back to start status
|
|
2033
1962
|
const status = this.statusService.status();
|
|
2034
|
-
if (status.state === 'connection-validation') {
|
|
2035
|
-
|
|
1963
|
+
if (status.state === 'connection-validation' || status.state === 'reconnection-validation') {
|
|
1964
|
+
const isReconnection = status.state === 'reconnection-validation';
|
|
1965
|
+
isReconnection
|
|
1966
|
+
? this.statusService.setReconnectionStartStatus(status.payload.source, status.payload.sourceHandle, status.payload.oldEdge)
|
|
1967
|
+
: this.statusService.setConnectionStartStatus(status.payload.source, status.payload.sourceHandle);
|
|
2036
1968
|
}
|
|
2037
1969
|
}
|
|
2038
1970
|
endConnection() {
|
|
2039
1971
|
const status = this.statusService.status();
|
|
2040
|
-
if (status.state === 'connection-validation') {
|
|
1972
|
+
if (status.state === 'connection-validation' || status.state === 'reconnection-validation') {
|
|
1973
|
+
const isReconnection = status.state === 'reconnection-validation';
|
|
2041
1974
|
const source = status.payload.source;
|
|
2042
1975
|
const sourceHandle = status.payload.sourceHandle;
|
|
2043
1976
|
const target = status.payload.target;
|
|
2044
1977
|
const targetHandle = status.payload.targetHandle;
|
|
2045
|
-
|
|
1978
|
+
isReconnection
|
|
1979
|
+
? this.statusService.setReconnectionEndStatus(source, target, sourceHandle, targetHandle, status.payload.oldEdge)
|
|
1980
|
+
: this.statusService.setConnectionEndStatus(source, target, sourceHandle, targetHandle);
|
|
2046
1981
|
}
|
|
2047
1982
|
}
|
|
2048
1983
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2049
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionControllerDirective, isStandalone: true, selector: "[onConnect]", outputs: { onConnect: "onConnect" }, ngImport: i0 }); }
|
|
1984
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionControllerDirective, isStandalone: true, selector: "[onConnect], [onReconnect]", outputs: { onConnect: "onConnect", onReconnect: "onReconnect" }, ngImport: i0 }); }
|
|
2050
1985
|
}
|
|
2051
1986
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerDirective, decorators: [{
|
|
2052
1987
|
type: Directive,
|
|
2053
1988
|
args: [{
|
|
2054
|
-
selector: '[onConnect]',
|
|
1989
|
+
selector: '[onConnect], [onReconnect]',
|
|
2055
1990
|
standalone: true,
|
|
2056
1991
|
}]
|
|
2057
1992
|
}] });
|
|
1993
|
+
function statusToConnection(status, isStrictMode) {
|
|
1994
|
+
let source = status.payload.source;
|
|
1995
|
+
let target = status.payload.target;
|
|
1996
|
+
let sourceHandle = status.payload.sourceHandle;
|
|
1997
|
+
let targetHandle = status.payload.targetHandle;
|
|
1998
|
+
if (isStrictMode) {
|
|
1999
|
+
const adjusted = adjustDirection({
|
|
2000
|
+
source: status.payload.source,
|
|
2001
|
+
sourceHandle: status.payload.sourceHandle,
|
|
2002
|
+
target: status.payload.target,
|
|
2003
|
+
targetHandle: status.payload.targetHandle,
|
|
2004
|
+
});
|
|
2005
|
+
source = adjusted.source;
|
|
2006
|
+
target = adjusted.target;
|
|
2007
|
+
sourceHandle = adjusted.sourceHandle;
|
|
2008
|
+
targetHandle = adjusted.targetHandle;
|
|
2009
|
+
}
|
|
2010
|
+
const sourceId = source.node.id;
|
|
2011
|
+
const targetId = target.node.id;
|
|
2012
|
+
const sourceHandleId = sourceHandle.rawHandle.id;
|
|
2013
|
+
const targetHandleId = targetHandle.rawHandle.id;
|
|
2014
|
+
return {
|
|
2015
|
+
source: sourceId,
|
|
2016
|
+
target: targetId,
|
|
2017
|
+
sourceHandle: sourceHandleId,
|
|
2018
|
+
targetHandle: targetHandleId,
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
2058
2021
|
|
|
2059
|
-
class
|
|
2022
|
+
class EdgeRenderingService {
|
|
2060
2023
|
constructor() {
|
|
2061
|
-
this.
|
|
2062
|
-
|
|
2024
|
+
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
2025
|
+
this.edges = computed(() => {
|
|
2026
|
+
return this.flowEntitiesService.validEdges().sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder());
|
|
2063
2027
|
});
|
|
2064
|
-
this.
|
|
2065
|
-
|
|
2066
|
-
ngAfterViewInit() {
|
|
2067
|
-
const element = this.handleWrapper.nativeElement;
|
|
2068
|
-
const rect = element.getBBox();
|
|
2069
|
-
const stroke = getChildStrokeWidth(element);
|
|
2070
|
-
this.handleModel().size.set({
|
|
2071
|
-
width: rect.width + stroke,
|
|
2072
|
-
height: rect.height + stroke,
|
|
2028
|
+
this.maxOrder = computed(() => {
|
|
2029
|
+
return Math.max(...this.flowEntitiesService.validEdges().map((n) => n.renderOrder()));
|
|
2073
2030
|
});
|
|
2074
2031
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
type: Directive,
|
|
2080
|
-
args: [{
|
|
2081
|
-
standalone: true,
|
|
2082
|
-
selector: '[handleSizeController]',
|
|
2083
|
-
}]
|
|
2084
|
-
}] });
|
|
2085
|
-
function getChildStrokeWidth(element) {
|
|
2086
|
-
const child = element.firstElementChild;
|
|
2087
|
-
if (child) {
|
|
2088
|
-
const stroke = getComputedStyle(child).strokeWidth;
|
|
2089
|
-
const strokeAsNumber = Number(stroke.replace('px', ''));
|
|
2090
|
-
if (isNaN(strokeAsNumber)) {
|
|
2091
|
-
return 0;
|
|
2032
|
+
pull(edge) {
|
|
2033
|
+
const isAlreadyOnTop = edge.renderOrder() !== 0 && this.maxOrder() === edge.renderOrder();
|
|
2034
|
+
if (isAlreadyOnTop) {
|
|
2035
|
+
return;
|
|
2092
2036
|
}
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
return 0;
|
|
2096
|
-
}
|
|
2097
|
-
|
|
2098
|
-
class DefaultNodeComponent {
|
|
2099
|
-
constructor() {
|
|
2100
|
-
this.selected = input(false);
|
|
2037
|
+
// pull node
|
|
2038
|
+
edge.renderOrder.set(this.maxOrder() + 1);
|
|
2101
2039
|
}
|
|
2102
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type:
|
|
2103
|
-
static { this.ɵ
|
|
2040
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeRenderingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2041
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeRenderingService }); }
|
|
2104
2042
|
}
|
|
2105
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type:
|
|
2106
|
-
type:
|
|
2107
|
-
args: [{ standalone: true, selector: 'default-node', host: {
|
|
2108
|
-
'[class.selected]': 'selected()',
|
|
2109
|
-
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [":host{border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}:host(.selected){border-width:2px}\n"] }]
|
|
2043
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeRenderingService, decorators: [{
|
|
2044
|
+
type: Injectable
|
|
2110
2045
|
}] });
|
|
2111
2046
|
|
|
2112
2047
|
function isTouchEvent(event) {
|
|
@@ -2191,6 +2126,150 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
2191
2126
|
args: ['mouseout', ['$event']]
|
|
2192
2127
|
}] } });
|
|
2193
2128
|
|
|
2129
|
+
class EdgeComponent {
|
|
2130
|
+
constructor() {
|
|
2131
|
+
this.injector = inject(Injector);
|
|
2132
|
+
this.selectionService = inject(SelectionService);
|
|
2133
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
2134
|
+
this.flowStatusService = inject(FlowStatusService);
|
|
2135
|
+
this.edgeRenderingService = inject(EdgeRenderingService);
|
|
2136
|
+
// TODO remove dependency from this directive
|
|
2137
|
+
this.connectionController = inject(ConnectionControllerDirective, { optional: true });
|
|
2138
|
+
this.model = input.required();
|
|
2139
|
+
this.edgeTemplate = input();
|
|
2140
|
+
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
|
+
this.isReconnecting = computed(() => {
|
|
2151
|
+
const status = this.flowStatusService.status();
|
|
2152
|
+
const isReconnecting = status.state === 'reconnection-start' || status.state === 'reconnection-validation';
|
|
2153
|
+
return isReconnecting && status.payload.oldEdge === this.model();
|
|
2154
|
+
});
|
|
2155
|
+
}
|
|
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
|
+
select() {
|
|
2169
|
+
if (this.flowSettingsService.entitiesSelectable()) {
|
|
2170
|
+
this.selectionService.select(this.model());
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
pull() {
|
|
2174
|
+
if (this.flowSettingsService.elevateEdgesOnSelect()) {
|
|
2175
|
+
this.edgeRenderingService.pull(this.model());
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
startReconnection(event, handle) {
|
|
2179
|
+
// ignore drag by stopping propagation
|
|
2180
|
+
event.stopPropagation();
|
|
2181
|
+
this.connectionController?.startReconnection(handle, this.model());
|
|
2182
|
+
}
|
|
2183
|
+
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 }); }
|
|
2185
|
+
}
|
|
2186
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EdgeComponent, decorators: [{
|
|
2187
|
+
type: Component,
|
|
2188
|
+
args: [{ standalone: true, selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2189
|
+
class: 'selectable',
|
|
2190
|
+
'[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"] }]
|
|
2192
|
+
}] });
|
|
2193
|
+
|
|
2194
|
+
class HandleService {
|
|
2195
|
+
constructor() {
|
|
2196
|
+
this.node = signal(null);
|
|
2197
|
+
}
|
|
2198
|
+
createHandle(newHandle) {
|
|
2199
|
+
const node = this.node();
|
|
2200
|
+
if (node) {
|
|
2201
|
+
node.handles.update((handles) => [...handles, newHandle]);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
destroyHandle(handleToDestoy) {
|
|
2205
|
+
const node = this.node();
|
|
2206
|
+
if (node) {
|
|
2207
|
+
node.handles.update((handles) => handles.filter((handle) => handle !== handleToDestoy));
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2211
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService }); }
|
|
2212
|
+
}
|
|
2213
|
+
__decorate([
|
|
2214
|
+
Microtask // TODO fixes rendering of handle for group node
|
|
2215
|
+
], HandleService.prototype, "createHandle", null);
|
|
2216
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleService, decorators: [{
|
|
2217
|
+
type: Injectable
|
|
2218
|
+
}], propDecorators: { createHandle: [] } });
|
|
2219
|
+
|
|
2220
|
+
class HandleSizeControllerDirective {
|
|
2221
|
+
constructor() {
|
|
2222
|
+
this.handleModel = input.required({
|
|
2223
|
+
alias: 'handleSizeController',
|
|
2224
|
+
});
|
|
2225
|
+
this.handleWrapper = inject(ElementRef);
|
|
2226
|
+
}
|
|
2227
|
+
ngAfterViewInit() {
|
|
2228
|
+
const element = this.handleWrapper.nativeElement;
|
|
2229
|
+
const rect = element.getBBox();
|
|
2230
|
+
const stroke = getChildStrokeWidth(element);
|
|
2231
|
+
this.handleModel().size.set({
|
|
2232
|
+
width: rect.width + stroke,
|
|
2233
|
+
height: rect.height + stroke,
|
|
2234
|
+
});
|
|
2235
|
+
}
|
|
2236
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleSizeControllerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2237
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.12", type: HandleSizeControllerDirective, isStandalone: true, selector: "[handleSizeController]", inputs: { handleModel: { classPropertyName: "handleModel", publicName: "handleSizeController", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 }); }
|
|
2238
|
+
}
|
|
2239
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleSizeControllerDirective, decorators: [{
|
|
2240
|
+
type: Directive,
|
|
2241
|
+
args: [{
|
|
2242
|
+
standalone: true,
|
|
2243
|
+
selector: '[handleSizeController]',
|
|
2244
|
+
}]
|
|
2245
|
+
}] });
|
|
2246
|
+
function getChildStrokeWidth(element) {
|
|
2247
|
+
const child = element.firstElementChild;
|
|
2248
|
+
if (child) {
|
|
2249
|
+
const stroke = getComputedStyle(child).strokeWidth;
|
|
2250
|
+
const strokeAsNumber = Number(stroke.replace('px', ''));
|
|
2251
|
+
if (isNaN(strokeAsNumber)) {
|
|
2252
|
+
return 0;
|
|
2253
|
+
}
|
|
2254
|
+
return strokeAsNumber;
|
|
2255
|
+
}
|
|
2256
|
+
return 0;
|
|
2257
|
+
}
|
|
2258
|
+
|
|
2259
|
+
class DefaultNodeComponent {
|
|
2260
|
+
constructor() {
|
|
2261
|
+
this.selected = input(false);
|
|
2262
|
+
}
|
|
2263
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DefaultNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2264
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: DefaultNodeComponent, isStandalone: true, selector: "default-node", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.selected": "selected()" } }, ngImport: i0, template: "<ng-content />\n", styles: [":host{border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}:host(.selected){border-width:2px}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2265
|
+
}
|
|
2266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DefaultNodeComponent, decorators: [{
|
|
2267
|
+
type: Component,
|
|
2268
|
+
args: [{ standalone: true, selector: 'default-node', host: {
|
|
2269
|
+
'[class.selected]': 'selected()',
|
|
2270
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-content />\n", styles: [":host{border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}:host(.selected){border-width:2px}\n"] }]
|
|
2271
|
+
}] });
|
|
2272
|
+
|
|
2194
2273
|
class ResizableComponent {
|
|
2195
2274
|
get model() {
|
|
2196
2275
|
return this.nodeAccessor.model();
|
|
@@ -2470,23 +2549,6 @@ class HandleModel {
|
|
|
2470
2549
|
}
|
|
2471
2550
|
}
|
|
2472
2551
|
|
|
2473
|
-
function InjectionContext(target, key, descriptor) {
|
|
2474
|
-
const originalMethod = descriptor.value;
|
|
2475
|
-
descriptor.value = function (...args) {
|
|
2476
|
-
if (implementsWithInjector(this)) {
|
|
2477
|
-
return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
|
|
2478
|
-
}
|
|
2479
|
-
else {
|
|
2480
|
-
throw new Error('Class that contains decorated method must extends WithInjectorDirective class');
|
|
2481
|
-
}
|
|
2482
|
-
};
|
|
2483
|
-
// Return the modified descriptor
|
|
2484
|
-
return descriptor;
|
|
2485
|
-
}
|
|
2486
|
-
const implementsWithInjector = (instance) => {
|
|
2487
|
-
return 'injector' in instance && 'get' in instance.injector;
|
|
2488
|
-
};
|
|
2489
|
-
|
|
2490
2552
|
class HandleComponent {
|
|
2491
2553
|
constructor() {
|
|
2492
2554
|
this.injector = inject(Injector);
|
|
@@ -2508,30 +2570,29 @@ class HandleComponent {
|
|
|
2508
2570
|
this.template = input();
|
|
2509
2571
|
}
|
|
2510
2572
|
ngOnInit() {
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2573
|
+
runInInjectionContext(this.injector, () => {
|
|
2574
|
+
const node = this.handleService.node();
|
|
2575
|
+
if (node) {
|
|
2576
|
+
const model = new HandleModel({
|
|
2577
|
+
position: this.position(),
|
|
2578
|
+
type: this.type(),
|
|
2579
|
+
id: this.id(),
|
|
2580
|
+
hostReference: this.element.parentElement,
|
|
2581
|
+
template: this.template(),
|
|
2582
|
+
}, node);
|
|
2583
|
+
this.handleService.createHandle(model);
|
|
2584
|
+
requestAnimationFrame(() => model.updateHost());
|
|
2585
|
+
this.destroyRef.onDestroy(() => this.handleService.destroyHandle(model));
|
|
2586
|
+
}
|
|
2587
|
+
});
|
|
2524
2588
|
}
|
|
2525
2589
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2526
2590
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: HandleComponent, isStandalone: true, selector: "handle", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "", changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2527
2591
|
}
|
|
2528
|
-
__decorate([
|
|
2529
|
-
InjectionContext
|
|
2530
|
-
], HandleComponent.prototype, "ngOnInit", null);
|
|
2531
2592
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleComponent, decorators: [{
|
|
2532
2593
|
type: Component,
|
|
2533
2594
|
args: [{ standalone: true, selector: 'handle', changeDetection: ChangeDetectionStrategy.OnPush, template: "" }]
|
|
2534
|
-
}]
|
|
2595
|
+
}] });
|
|
2535
2596
|
|
|
2536
2597
|
class NodeHandlesControllerDirective {
|
|
2537
2598
|
constructor() {
|
|
@@ -2607,7 +2668,9 @@ class NodeComponent {
|
|
|
2607
2668
|
this.nodeTemplate = input();
|
|
2608
2669
|
this.groupNodeTemplate = input();
|
|
2609
2670
|
this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
|
|
2610
|
-
this.flowStatusService.status().state === 'connection-validation'
|
|
2671
|
+
this.flowStatusService.status().state === 'connection-validation' ||
|
|
2672
|
+
this.flowStatusService.status().state === 'reconnection-start' ||
|
|
2673
|
+
this.flowStatusService.status().state === 'reconnection-validation');
|
|
2611
2674
|
this.toolbar = computed(() => this.overlaysService.nodeToolbars().get(this.model()));
|
|
2612
2675
|
}
|
|
2613
2676
|
ngOnInit() {
|
|
@@ -2677,7 +2740,7 @@ class ConnectionComponent {
|
|
|
2677
2740
|
this.spacePointContext = inject(SpacePointContextDirective);
|
|
2678
2741
|
this.path = computed(() => {
|
|
2679
2742
|
const status = this.flowStatusService.status();
|
|
2680
|
-
if (status.state === 'connection-start') {
|
|
2743
|
+
if (status.state === 'connection-start' || status.state === 'reconnection-start') {
|
|
2681
2744
|
const sourceHandle = status.payload.sourceHandle;
|
|
2682
2745
|
const sourcePoint = sourceHandle.pointAbsolute();
|
|
2683
2746
|
const sourcePosition = sourceHandle.rawHandle.position;
|
|
@@ -2694,7 +2757,7 @@ class ConnectionComponent {
|
|
|
2694
2757
|
return smoothStepPath(sourcePoint, targetPoint, sourcePosition, targetPosition, 0).path;
|
|
2695
2758
|
}
|
|
2696
2759
|
}
|
|
2697
|
-
if (status.state === 'connection-validation') {
|
|
2760
|
+
if (status.state === 'connection-validation' || status.state === 'reconnection-validation') {
|
|
2698
2761
|
const sourceHandle = status.payload.sourceHandle;
|
|
2699
2762
|
const sourcePoint = sourceHandle.pointAbsolute();
|
|
2700
2763
|
const sourcePosition = sourceHandle.rawHandle.position;
|
|
@@ -2968,7 +3031,7 @@ class RootSvgContextDirective {
|
|
|
2968
3031
|
// TODO: check for multiple instances on page
|
|
2969
3032
|
resetConnection() {
|
|
2970
3033
|
const status = this.flowStatusService.status();
|
|
2971
|
-
if (status.state === 'connection-start') {
|
|
3034
|
+
if (status.state === 'connection-start' || status.state === 'reconnection-start') {
|
|
2972
3035
|
this.flowStatusService.setIdleStatus();
|
|
2973
3036
|
}
|
|
2974
3037
|
}
|
|
@@ -3034,6 +3097,7 @@ class VflowComponent {
|
|
|
3034
3097
|
this.nodesChangeService = inject(NodesChangeService);
|
|
3035
3098
|
this.edgesChangeService = inject(EdgeChangesService);
|
|
3036
3099
|
this.nodeRenderingService = inject(NodeRenderingService);
|
|
3100
|
+
this.edgeRenderingService = inject(EdgeRenderingService);
|
|
3037
3101
|
this.flowSettingsService = inject(FlowSettingsService);
|
|
3038
3102
|
this.componentEventBusService = inject(ComponentEventBusService);
|
|
3039
3103
|
this.keyboardService = inject(KeyboardService);
|
|
@@ -3044,7 +3108,7 @@ class VflowComponent {
|
|
|
3044
3108
|
this.nodeModels = computed(() => this.nodeRenderingService.nodes());
|
|
3045
3109
|
this.groups = computed(() => this.nodeRenderingService.groups());
|
|
3046
3110
|
this.nonGroups = computed(() => this.nodeRenderingService.nonGroups());
|
|
3047
|
-
this.edgeModels = computed(() => this.
|
|
3111
|
+
this.edgeModels = computed(() => this.edgeRenderingService.edges());
|
|
3048
3112
|
// #endregion
|
|
3049
3113
|
// #region OUTPUTS
|
|
3050
3114
|
/**
|
|
@@ -3162,6 +3226,12 @@ class VflowComponent {
|
|
|
3162
3226
|
set elevateNodesOnSelect(value) {
|
|
3163
3227
|
this.flowSettingsService.elevateNodesOnSelect.set(value);
|
|
3164
3228
|
}
|
|
3229
|
+
/**
|
|
3230
|
+
* Raizing z-index for selected edge
|
|
3231
|
+
*/
|
|
3232
|
+
set elevateEdgesOnSelect(value) {
|
|
3233
|
+
this.flowSettingsService.elevateEdgesOnSelect.set(value);
|
|
3234
|
+
}
|
|
3165
3235
|
// #endregion
|
|
3166
3236
|
// #region MAIN_INPUTS
|
|
3167
3237
|
/**
|
|
@@ -3263,7 +3333,7 @@ class VflowComponent {
|
|
|
3263
3333
|
});
|
|
3264
3334
|
}
|
|
3265
3335
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3266
|
-
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: true, 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 }, nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: false, isRequired: true, transformFunction: null }, edges: { classPropertyName: "edges", publicName: "edges", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, providers: [
|
|
3336
|
+
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: true, 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 }, edges: { classPropertyName: "edges", publicName: "edges", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, providers: [
|
|
3267
3337
|
DraggableService,
|
|
3268
3338
|
ViewportService,
|
|
3269
3339
|
FlowStatusService,
|
|
@@ -3271,6 +3341,7 @@ class VflowComponent {
|
|
|
3271
3341
|
NodesChangeService,
|
|
3272
3342
|
EdgeChangesService,
|
|
3273
3343
|
NodeRenderingService,
|
|
3344
|
+
EdgeRenderingService,
|
|
3274
3345
|
SelectionService,
|
|
3275
3346
|
FlowSettingsService,
|
|
3276
3347
|
ComponentEventBusService,
|
|
@@ -3288,6 +3359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3288
3359
|
NodesChangeService,
|
|
3289
3360
|
EdgeChangesService,
|
|
3290
3361
|
NodeRenderingService,
|
|
3362
|
+
EdgeRenderingService,
|
|
3291
3363
|
SelectionService,
|
|
3292
3364
|
FlowSettingsService,
|
|
3293
3365
|
ComponentEventBusService,
|
|
@@ -3328,6 +3400,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3328
3400
|
type: Input
|
|
3329
3401
|
}], elevateNodesOnSelect: [{
|
|
3330
3402
|
type: Input
|
|
3403
|
+
}], elevateEdgesOnSelect: [{
|
|
3404
|
+
type: Input
|
|
3331
3405
|
}], nodes: [{
|
|
3332
3406
|
type: Input,
|
|
3333
3407
|
args: [{ required: true }]
|
|
@@ -3366,8 +3440,12 @@ class SelectableDirective {
|
|
|
3366
3440
|
this.selectionService = inject(SelectionService);
|
|
3367
3441
|
this.parentEdge = inject(EdgeComponent, { optional: true });
|
|
3368
3442
|
this.parentNode = inject(NodeComponent, { optional: true });
|
|
3443
|
+
this.host = inject(ElementRef);
|
|
3444
|
+
this.selectOnEvent = this.getEvent$()
|
|
3445
|
+
.pipe(tap(() => this.select()), takeUntilDestroyed())
|
|
3446
|
+
.subscribe();
|
|
3369
3447
|
}
|
|
3370
|
-
|
|
3448
|
+
select() {
|
|
3371
3449
|
const entity = this.entity();
|
|
3372
3450
|
if (entity && this.flowSettingsService.entitiesSelectable()) {
|
|
3373
3451
|
this.selectionService.select(entity);
|
|
@@ -3382,8 +3460,16 @@ class SelectableDirective {
|
|
|
3382
3460
|
}
|
|
3383
3461
|
return null;
|
|
3384
3462
|
}
|
|
3463
|
+
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
|
+
return merge(fromEvent(this.host.nativeElement, 'mousedown'), fromEvent(this.host.nativeElement, 'touchstart'));
|
|
3470
|
+
}
|
|
3385
3471
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
3386
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectableDirective, isStandalone: true, selector: "[selectable]",
|
|
3472
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: SelectableDirective, isStandalone: true, selector: "[selectable]", ngImport: i0 }); }
|
|
3387
3473
|
}
|
|
3388
3474
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SelectableDirective, decorators: [{
|
|
3389
3475
|
type: Directive,
|
|
@@ -3391,13 +3477,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3391
3477
|
standalone: true,
|
|
3392
3478
|
selector: '[selectable]',
|
|
3393
3479
|
}]
|
|
3394
|
-
}]
|
|
3395
|
-
type: HostListener,
|
|
3396
|
-
args: ['mousedown']
|
|
3397
|
-
}, {
|
|
3398
|
-
type: HostListener,
|
|
3399
|
-
args: ['touchstart']
|
|
3400
|
-
}] } });
|
|
3480
|
+
}] });
|
|
3401
3481
|
|
|
3402
3482
|
class MinimapModel {
|
|
3403
3483
|
constructor() {
|
|
@@ -3756,20 +3836,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3756
3836
|
|
|
3757
3837
|
class VflowMockComponent {
|
|
3758
3838
|
constructor() {
|
|
3759
|
-
this.
|
|
3760
|
-
this.
|
|
3761
|
-
this.
|
|
3762
|
-
this.
|
|
3763
|
-
this.maxZoom = input(3);
|
|
3764
|
-
this.background = input('#fff');
|
|
3839
|
+
this.view = [400, 400];
|
|
3840
|
+
this.minZoom = 0.5;
|
|
3841
|
+
this.maxZoom = 3;
|
|
3842
|
+
this.background = '#fff';
|
|
3765
3843
|
this.optimization = input({
|
|
3766
3844
|
detachedGroupsLayer: false,
|
|
3767
3845
|
});
|
|
3768
|
-
this.entitiesSelectable =
|
|
3769
|
-
this.keyboardShortcuts =
|
|
3846
|
+
this.entitiesSelectable = true;
|
|
3847
|
+
this.keyboardShortcuts = {
|
|
3770
3848
|
multiSelection: null,
|
|
3771
|
-
}
|
|
3772
|
-
this.connection =
|
|
3849
|
+
};
|
|
3850
|
+
this.connection = new ConnectionModel({});
|
|
3773
3851
|
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
|
3774
3852
|
this.onComponentNodeEvent = output();
|
|
3775
3853
|
this.nodeTemplateDirective = contentChild(NodeHtmlTemplateMockDirective);
|
|
@@ -3788,6 +3866,8 @@ class VflowMockComponent {
|
|
|
3788
3866
|
this.nodesChange$ = toObservable(this.nodesChange);
|
|
3789
3867
|
this.edgesChange$ = toObservable(this.edgesChange);
|
|
3790
3868
|
}
|
|
3869
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
3870
|
+
ngOnInit() { }
|
|
3791
3871
|
viewportTo(viewport) {
|
|
3792
3872
|
this.viewport.set(viewport);
|
|
3793
3873
|
}
|
|
@@ -3802,9 +3882,8 @@ class VflowMockComponent {
|
|
|
3802
3882
|
documentPointToFlowPoint(point) {
|
|
3803
3883
|
return point;
|
|
3804
3884
|
}
|
|
3805
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3806
3885
|
getNode(id) {
|
|
3807
|
-
return this.nodes
|
|
3886
|
+
return this.nodes.find((node) => node.id === id);
|
|
3808
3887
|
}
|
|
3809
3888
|
getDetachedEdges() {
|
|
3810
3889
|
return [];
|
|
@@ -3813,10 +3892,10 @@ class VflowMockComponent {
|
|
|
3813
3892
|
return signal(value);
|
|
3814
3893
|
}
|
|
3815
3894
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: VflowMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3816
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: VflowMockComponent, isStandalone: true, selector: "vflow", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal:
|
|
3895
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: VflowMockComponent, isStandalone: true, selector: "vflow", inputs: { nodes: { classPropertyName: "nodes", publicName: "nodes", isSignal: false, isRequired: true, transformFunction: null }, edges: { classPropertyName: "edges", publicName: "edges", isSignal: false, isRequired: false, transformFunction: null }, 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: true, 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 } }, outputs: { onComponentNodeEvent: "onComponentNodeEvent" }, queries: [{ propertyName: "nodeTemplateDirective", first: true, predicate: NodeHtmlTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "groupNodeTemplateDirective", first: true, predicate: GroupNodeTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateMockDirective, descendants: true, isSignal: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateMockDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3817
3896
|
<ng-content />
|
|
3818
3897
|
|
|
3819
|
-
@for (node of nodes
|
|
3898
|
+
@for (node of nodes; track $index) {
|
|
3820
3899
|
@if (node.type === 'html-template') {
|
|
3821
3900
|
<ng-component
|
|
3822
3901
|
[ngTemplateOutlet]="nodeTemplateDirective()?.templateRef ?? null"
|
|
@@ -3842,7 +3921,7 @@ class VflowMockComponent {
|
|
|
3842
3921
|
}
|
|
3843
3922
|
}
|
|
3844
3923
|
|
|
3845
|
-
@for (edge of edges
|
|
3924
|
+
@for (edge of edges; track $index) {
|
|
3846
3925
|
@if (edge.type === 'template') {
|
|
3847
3926
|
<ng-component
|
|
3848
3927
|
[ngTemplateOutlet]="edgeTemplateDirective()?.templateRef ?? null"
|
|
@@ -3890,7 +3969,7 @@ class VflowMockComponent {
|
|
|
3890
3969
|
}
|
|
3891
3970
|
}
|
|
3892
3971
|
|
|
3893
|
-
@if (connection
|
|
3972
|
+
@if (connection.type === 'template') {
|
|
3894
3973
|
<ng-component
|
|
3895
3974
|
[ngTemplateOutlet]="connectionTemplateDirective()?.templateRef ?? null"
|
|
3896
3975
|
[ngTemplateOutletContext]="{
|
|
@@ -3909,7 +3988,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3909
3988
|
template: `
|
|
3910
3989
|
<ng-content />
|
|
3911
3990
|
|
|
3912
|
-
@for (node of nodes
|
|
3991
|
+
@for (node of nodes; track $index) {
|
|
3913
3992
|
@if (node.type === 'html-template') {
|
|
3914
3993
|
<ng-component
|
|
3915
3994
|
[ngTemplateOutlet]="nodeTemplateDirective()?.templateRef ?? null"
|
|
@@ -3935,7 +4014,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3935
4014
|
}
|
|
3936
4015
|
}
|
|
3937
4016
|
|
|
3938
|
-
@for (edge of edges
|
|
4017
|
+
@for (edge of edges; track $index) {
|
|
3939
4018
|
@if (edge.type === 'template') {
|
|
3940
4019
|
<ng-component
|
|
3941
4020
|
[ngTemplateOutlet]="edgeTemplateDirective()?.templateRef ?? null"
|
|
@@ -3983,7 +4062,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3983
4062
|
}
|
|
3984
4063
|
}
|
|
3985
4064
|
|
|
3986
|
-
@if (connection
|
|
4065
|
+
@if (connection.type === 'template') {
|
|
3987
4066
|
<ng-component
|
|
3988
4067
|
[ngTemplateOutlet]="connectionTemplateDirective()?.templateRef ?? null"
|
|
3989
4068
|
[ngTemplateOutletContext]="{
|
|
@@ -3998,7 +4077,35 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
3998
4077
|
standalone: true,
|
|
3999
4078
|
imports: [NgTemplateOutlet],
|
|
4000
4079
|
}]
|
|
4001
|
-
}]
|
|
4080
|
+
}], propDecorators: { nodes: [{
|
|
4081
|
+
type: Input,
|
|
4082
|
+
args: [{ required: true }]
|
|
4083
|
+
}], edges: [{
|
|
4084
|
+
type: Input
|
|
4085
|
+
}], view: [{
|
|
4086
|
+
type: Input
|
|
4087
|
+
}], minZoom: [{
|
|
4088
|
+
type: Input
|
|
4089
|
+
}], maxZoom: [{
|
|
4090
|
+
type: Input
|
|
4091
|
+
}], background: [{
|
|
4092
|
+
type: Input
|
|
4093
|
+
}], entitiesSelectable: [{
|
|
4094
|
+
type: Input
|
|
4095
|
+
}], keyboardShortcuts: [{
|
|
4096
|
+
type: Input
|
|
4097
|
+
}], connection: [{
|
|
4098
|
+
type: Input,
|
|
4099
|
+
args: [{
|
|
4100
|
+
transform: (settings) => new ConnectionModel(settings),
|
|
4101
|
+
}]
|
|
4102
|
+
}], snapGrid: [{
|
|
4103
|
+
type: Input
|
|
4104
|
+
}], elevateNodesOnSelect: [{
|
|
4105
|
+
type: Input
|
|
4106
|
+
}], elevateEdgesOnSelect: [{
|
|
4107
|
+
type: Input
|
|
4108
|
+
}] } });
|
|
4002
4109
|
|
|
4003
4110
|
class HandleMockComponent {
|
|
4004
4111
|
constructor() {
|
|
@@ -4007,6 +4114,8 @@ class HandleMockComponent {
|
|
|
4007
4114
|
this.id = input();
|
|
4008
4115
|
this.template = input();
|
|
4009
4116
|
}
|
|
4117
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4118
|
+
ngOnInit() { }
|
|
4010
4119
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: HandleMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4011
4120
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: HandleMockComponent, isStandalone: true, selector: "handle", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, template: { classPropertyName: "template", publicName: "template", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4012
4121
|
}
|
|
@@ -4026,6 +4135,10 @@ class ResizableMockComponent {
|
|
|
4026
4135
|
this.resizerColor = input('#2e414c');
|
|
4027
4136
|
this.gap = input(1.5);
|
|
4028
4137
|
}
|
|
4138
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4139
|
+
ngOnInit() { }
|
|
4140
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4141
|
+
ngAfterViewInit() { }
|
|
4029
4142
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ResizableMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4030
4143
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: ResizableMockComponent, isStandalone: true, selector: "[resizable]", inputs: { resizable: { classPropertyName: "resizable", publicName: "resizable", isSignal: true, isRequired: false, transformFunction: null }, resizerColor: { classPropertyName: "resizerColor", publicName: "resizerColor", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<ng-content />', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4031
4144
|
}
|
|
@@ -4046,6 +4159,8 @@ class MiniMapMockComponent {
|
|
|
4046
4159
|
this.position = input('bottom-right');
|
|
4047
4160
|
this.scaleOnHover = input(false);
|
|
4048
4161
|
}
|
|
4162
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4163
|
+
ngOnInit() { }
|
|
4049
4164
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MiniMapMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4050
4165
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: MiniMapMockComponent, isStandalone: true, selector: "mini-map", inputs: { maskColor: { classPropertyName: "maskColor", publicName: "maskColor", isSignal: true, isRequired: false, transformFunction: null }, strokeColor: { classPropertyName: "strokeColor", publicName: "strokeColor", isSignal: true, isRequired: false, transformFunction: null }, position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, scaleOnHover: { classPropertyName: "scaleOnHover", publicName: "scaleOnHover", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4051
4166
|
}
|
|
@@ -4063,6 +4178,10 @@ class NodeToolbarMockComponent {
|
|
|
4063
4178
|
constructor() {
|
|
4064
4179
|
this.position = input('top');
|
|
4065
4180
|
}
|
|
4181
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4182
|
+
ngOnInit() { }
|
|
4183
|
+
// eslint-disable-next-line @angular-eslint/no-empty-lifecycle-method
|
|
4184
|
+
ngOnDestroy() { }
|
|
4066
4185
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: NodeToolbarMockComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4067
4186
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: NodeToolbarMockComponent, isStandalone: true, selector: "node-toolbar", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<ng-content />', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
4068
4187
|
}
|
|
@@ -4080,9 +4199,21 @@ class ConnectionControllerMockDirective {
|
|
|
4080
4199
|
constructor() {
|
|
4081
4200
|
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
|
4082
4201
|
this.onConnect = output();
|
|
4202
|
+
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
|
|
4203
|
+
this.onReconnect = output();
|
|
4083
4204
|
}
|
|
4205
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4206
|
+
startConnection(handle) { }
|
|
4207
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4208
|
+
startReconnection(handle) { }
|
|
4209
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4210
|
+
validateConnection(handle) { }
|
|
4211
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4212
|
+
resetValidateConnection(targetHandle) { }
|
|
4213
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
4214
|
+
endConnection() { }
|
|
4084
4215
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerMockDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
4085
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionControllerMockDirective, isStandalone: true, selector: "[onConnect]", outputs: { onConnect: "onConnect" }, ngImport: i0 }); }
|
|
4216
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "17.3.12", type: ConnectionControllerMockDirective, isStandalone: true, selector: "[onConnect]", outputs: { onConnect: "onConnect", onReconnect: "onReconnect" }, ngImport: i0 }); }
|
|
4086
4217
|
}
|
|
4087
4218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ConnectionControllerMockDirective, decorators: [{
|
|
4088
4219
|
type: Directive,
|