ngx-vflow 0.3.0 → 0.4.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/edge/edge.component.mjs +18 -6
- package/esm2022/lib/vflow/components/handle/handle.component.mjs +7 -7
- package/esm2022/lib/vflow/components/node/node.component.mjs +22 -8
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +33 -20
- package/esm2022/lib/vflow/decorators/run-in-injection-context.decorator.mjs +6 -14
- package/esm2022/lib/vflow/directives/map-context.directive.mjs +31 -4
- package/esm2022/lib/vflow/directives/root-svg-context.directive.mjs +1 -1
- package/esm2022/lib/vflow/directives/selectable.directive.mjs +39 -0
- package/esm2022/lib/vflow/interfaces/flow-entity.interface.mjs +2 -0
- package/esm2022/lib/vflow/interfaces/template-context.interface.mjs +1 -1
- package/esm2022/lib/vflow/models/edge.model.mjs +3 -1
- package/esm2022/lib/vflow/models/node.model.mjs +9 -12
- package/esm2022/lib/vflow/services/edge-changes.service.mjs +6 -2
- package/esm2022/lib/vflow/services/flow-entities.service.mjs +5 -1
- package/esm2022/lib/vflow/services/flow-settings.service.mjs +25 -0
- package/esm2022/lib/vflow/services/node-changes.service.mjs +7 -3
- package/esm2022/lib/vflow/services/node-rendering.service.mjs +22 -0
- package/esm2022/lib/vflow/services/selection.service.mjs +45 -0
- package/esm2022/lib/vflow/types/edge-change.type.mjs +1 -1
- package/esm2022/lib/vflow/types/node-change.type.mjs +1 -1
- package/esm2022/lib/vflow/vflow.module.mjs +9 -4
- package/esm2022/public-api.mjs +2 -1
- package/fesm2022/ngx-vflow.mjs +307 -144
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/edge/edge.component.d.ts +5 -2
- package/lib/vflow/components/handle/handle.component.d.ts +4 -3
- package/lib/vflow/components/node/node.component.d.ts +9 -3
- package/lib/vflow/components/vflow/vflow.component.d.ts +11 -5
- package/lib/vflow/decorators/run-in-injection-context.decorator.d.ts +2 -5
- package/lib/vflow/directives/map-context.directive.d.ts +5 -0
- package/lib/vflow/directives/selectable.directive.d.ts +11 -0
- package/lib/vflow/interfaces/flow-entity.interface.d.ts +4 -0
- package/lib/vflow/interfaces/template-context.interface.d.ts +1 -0
- package/lib/vflow/models/edge.model.d.ts +7 -3
- package/lib/vflow/models/node.model.d.ts +6 -9
- package/lib/vflow/services/edge-changes.service.d.ts +5 -0
- package/lib/vflow/services/flow-entities.service.d.ts +5 -2
- package/lib/vflow/services/flow-settings.service.d.ts +20 -0
- package/lib/vflow/services/node-changes.service.d.ts +5 -0
- package/lib/vflow/services/node-rendering.service.d.ts +9 -0
- package/lib/vflow/services/selection.service.d.ts +19 -0
- package/lib/vflow/types/edge-change.type.d.ts +5 -1
- package/lib/vflow/types/node-change.type.d.ts +5 -1
- package/lib/vflow/vflow.module.d.ts +4 -3
- package/package.json +3 -3
- package/public-api.d.ts +1 -0
- package/esm2022/lib/vflow/models/flow.model.mjs +0 -18
- package/lib/vflow/models/flow.model.d.ts +0 -16
package/fesm2022/ngx-vflow.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { signal, Injectable, inject, ElementRef, Directive, effect, Input, TemplateRef,
|
|
4
|
+
import { signal, Injectable, inject, ElementRef, Directive, computed, effect, Input, TemplateRef, EventEmitter, Output, untracked, runInInjectionContext, Injector, NgZone, Component, ChangeDetectionStrategy, ViewChild, HostListener, ContentChild, NgModule } from '@angular/core';
|
|
5
5
|
import { select } from 'd3-selection';
|
|
6
6
|
import { zoomIdentity, zoom } from 'd3-zoom';
|
|
7
|
+
import { Subject, tap, switchMap, merge, skip, map, pairwise, filter, distinctUntilChanged, observeOn, asyncScheduler, zip, Observable, Subscription, startWith, fromEvent } from 'rxjs';
|
|
8
|
+
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
7
9
|
import { drag } from 'd3-drag';
|
|
8
|
-
import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
9
|
-
import { switchMap, merge, skip, map, pairwise, filter, observeOn, asyncScheduler, zip, distinctUntilChanged, tap, Subject, Observable, Subscription, startWith, fromEvent } from 'rxjs';
|
|
10
10
|
import { path } from 'd3-path';
|
|
11
11
|
import { __decorate } from 'tslib';
|
|
12
12
|
|
|
@@ -58,13 +58,123 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
58
58
|
}]
|
|
59
59
|
}] });
|
|
60
60
|
|
|
61
|
+
class ConnectionModel {
|
|
62
|
+
constructor(connection) {
|
|
63
|
+
this.connection = connection;
|
|
64
|
+
this.curve = connection.curve ?? 'bezier';
|
|
65
|
+
this.type = connection.type ?? 'default';
|
|
66
|
+
this.validator = connection.validator ?? (() => true);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function hashCode(str) {
|
|
71
|
+
return str.split('').reduce((a, b) => {
|
|
72
|
+
a = ((a << 5) - a) + b.charCodeAt(0);
|
|
73
|
+
return a & a;
|
|
74
|
+
}, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
class FlowEntitiesService {
|
|
78
|
+
constructor() {
|
|
79
|
+
this.nodes = signal([], {
|
|
80
|
+
// empty arrays considered equal, other arrays may not be equal
|
|
81
|
+
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
82
|
+
});
|
|
83
|
+
this.edges = signal([], {
|
|
84
|
+
// empty arrays considered equal, other arrays may not be equal
|
|
85
|
+
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
86
|
+
});
|
|
87
|
+
this.connection = signal(new ConnectionModel({}));
|
|
88
|
+
this.markers = computed(() => {
|
|
89
|
+
const markersMap = new Map();
|
|
90
|
+
this.validEdges().forEach(e => {
|
|
91
|
+
if (e.edge.markers?.start) {
|
|
92
|
+
const hash = hashCode(JSON.stringify(e.edge.markers.start));
|
|
93
|
+
markersMap.set(hash, e.edge.markers.start);
|
|
94
|
+
}
|
|
95
|
+
if (e.edge.markers?.end) {
|
|
96
|
+
const hash = hashCode(JSON.stringify(e.edge.markers.end));
|
|
97
|
+
markersMap.set(hash, e.edge.markers.end);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
const connectionMarker = this.connection().connection.marker;
|
|
101
|
+
if (connectionMarker) {
|
|
102
|
+
const hash = hashCode(JSON.stringify(connectionMarker));
|
|
103
|
+
markersMap.set(hash, connectionMarker);
|
|
104
|
+
}
|
|
105
|
+
return markersMap;
|
|
106
|
+
});
|
|
107
|
+
this.validEdges = computed(() => {
|
|
108
|
+
const nodes = this.nodes();
|
|
109
|
+
return this.edges().filter(e => nodes.includes(e.source()) && nodes.includes(e.target()));
|
|
110
|
+
});
|
|
111
|
+
this.entities = computed(() => [
|
|
112
|
+
...this.nodes(),
|
|
113
|
+
...this.edges()
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
getNode(id) {
|
|
117
|
+
return this.nodes().find(({ node }) => node.id === id);
|
|
118
|
+
}
|
|
119
|
+
getDetachedEdges() {
|
|
120
|
+
return this.edges().filter(e => e.detached());
|
|
121
|
+
}
|
|
122
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
123
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService }); }
|
|
124
|
+
}
|
|
125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, decorators: [{
|
|
126
|
+
type: Injectable
|
|
127
|
+
}] });
|
|
128
|
+
|
|
129
|
+
class SelectionService {
|
|
130
|
+
constructor() {
|
|
131
|
+
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
132
|
+
this.viewport$ = new Subject();
|
|
133
|
+
this.resetSelection = this.viewport$.pipe(tap(({ start, end, target }) => {
|
|
134
|
+
if (start && end) {
|
|
135
|
+
const delta = SelectionService.delta;
|
|
136
|
+
const diffX = Math.abs(end.x - start.x);
|
|
137
|
+
const diffY = Math.abs(end.y - start.y);
|
|
138
|
+
// click (not drag)
|
|
139
|
+
const isClick = diffX < delta && diffY < delta;
|
|
140
|
+
// do not reset if event chain contains selectable elems
|
|
141
|
+
const isNotSelectable = !target.closest('.selectable');
|
|
142
|
+
if (isClick && isNotSelectable) {
|
|
143
|
+
this.select(null);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}), takeUntilDestroyed()).subscribe();
|
|
147
|
+
}
|
|
148
|
+
static { this.delta = 6; }
|
|
149
|
+
setViewport(viewport) {
|
|
150
|
+
this.viewport$.next(viewport);
|
|
151
|
+
}
|
|
152
|
+
select(entity) {
|
|
153
|
+
// undo select for previously selected nodes
|
|
154
|
+
this.flowEntitiesService.entities()
|
|
155
|
+
.filter(n => n.selected)
|
|
156
|
+
.forEach(n => n.selected.set(false));
|
|
157
|
+
if (entity) {
|
|
158
|
+
// select passed entity
|
|
159
|
+
entity.selected.set(true);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
163
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService }); }
|
|
164
|
+
}
|
|
165
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectionService, decorators: [{
|
|
166
|
+
type: Injectable
|
|
167
|
+
}] });
|
|
168
|
+
|
|
61
169
|
class MapContextDirective {
|
|
62
170
|
constructor() {
|
|
63
171
|
this.rootSvg = inject(RootSvgReferenceDirective).element;
|
|
64
172
|
this.host = inject(ElementRef).nativeElement;
|
|
173
|
+
this.selectionService = inject(SelectionService);
|
|
65
174
|
this.viewportService = inject(ViewportService);
|
|
66
175
|
this.rootSvgSelection = select(this.rootSvg);
|
|
67
176
|
this.zoomableSelection = select(this.host);
|
|
177
|
+
this.viewportForSelection = {};
|
|
68
178
|
// under the hood this effect triggers handleZoom, so error throws without this flag
|
|
69
179
|
// TODO: hack with timer fixes wrong node scaling (handle positions not matched with content size)
|
|
70
180
|
this.manualViewportChangeEffect = effect(() => setTimeout(() => {
|
|
@@ -91,15 +201,32 @@ class MapContextDirective {
|
|
|
91
201
|
}), { allowSignalWrites: true });
|
|
92
202
|
this.handleZoom = ({ transform }) => {
|
|
93
203
|
// update public signal for user to read
|
|
94
|
-
this.viewportService.readableViewport.set(
|
|
204
|
+
this.viewportService.readableViewport.set(mapTransformToViewportState(transform));
|
|
95
205
|
this.zoomableSelection.attr('transform', transform.toString());
|
|
96
206
|
};
|
|
97
207
|
}
|
|
98
208
|
ngOnInit() {
|
|
99
209
|
this.zoomBehavior = zoom()
|
|
100
210
|
.scaleExtent([this.minZoom, this.maxZoom])
|
|
101
|
-
.on('
|
|
102
|
-
|
|
211
|
+
.on('start', (event) => this.onD3zoomStart(event))
|
|
212
|
+
.on('zoom', (event) => this.handleZoom(event))
|
|
213
|
+
.on('end', (event) => this.onD3zoomEnd(event));
|
|
214
|
+
this.rootSvgSelection
|
|
215
|
+
.call(this.zoomBehavior)
|
|
216
|
+
.on('dblclick.zoom', null);
|
|
217
|
+
}
|
|
218
|
+
onD3zoomStart({ transform }) {
|
|
219
|
+
this.viewportForSelection = {
|
|
220
|
+
start: mapTransformToViewportState(transform)
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
onD3zoomEnd({ transform, sourceEvent }) {
|
|
224
|
+
this.viewportForSelection = {
|
|
225
|
+
...this.viewportForSelection,
|
|
226
|
+
end: mapTransformToViewportState(transform),
|
|
227
|
+
target: evTarget(sourceEvent)
|
|
228
|
+
};
|
|
229
|
+
this.selectionService.setViewport(this.viewportForSelection);
|
|
103
230
|
}
|
|
104
231
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: MapContextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
105
232
|
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: MapContextDirective, selector: "g[mapContext]", inputs: { minZoom: "minZoom", maxZoom: "maxZoom" }, ngImport: i0 }); }
|
|
@@ -112,6 +239,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
112
239
|
}], maxZoom: [{
|
|
113
240
|
type: Input
|
|
114
241
|
}] } });
|
|
242
|
+
const mapTransformToViewportState = (transform) => ({ zoom: transform.k, x: transform.x, y: transform.y });
|
|
243
|
+
const evTarget = (anyEvent) => {
|
|
244
|
+
if (anyEvent instanceof Event && anyEvent.target instanceof Element) {
|
|
245
|
+
return anyEvent.target;
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
};
|
|
115
249
|
|
|
116
250
|
const round = (num) => Math.round(num * 100) / 100;
|
|
117
251
|
|
|
@@ -243,23 +377,6 @@ function addNodesToEdges(nodes, edges) {
|
|
|
243
377
|
});
|
|
244
378
|
}
|
|
245
379
|
|
|
246
|
-
class FlowModel {
|
|
247
|
-
constructor() {
|
|
248
|
-
/**
|
|
249
|
-
* Global setting with handle positions. Nodes derive this value
|
|
250
|
-
*
|
|
251
|
-
* @deprecated
|
|
252
|
-
*/
|
|
253
|
-
this.handlePositions = signal({ source: 'right', target: 'left' });
|
|
254
|
-
/**
|
|
255
|
-
* @see {VflowComponent.view}
|
|
256
|
-
*/
|
|
257
|
-
this.view = signal([400, 400]);
|
|
258
|
-
this.flowWidth = computed(() => this.view() === 'auto' ? '100%' : this.view()[0]);
|
|
259
|
-
this.flowHeight = computed(() => this.view() === 'auto' ? '100%' : this.view()[1]);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
380
|
class FlowStatusService {
|
|
264
381
|
constructor() {
|
|
265
382
|
this.status = signal({ state: 'idle', payload: null });
|
|
@@ -297,70 +414,6 @@ function batchStatusChanges(...changes) {
|
|
|
297
414
|
}
|
|
298
415
|
}
|
|
299
416
|
|
|
300
|
-
class ConnectionModel {
|
|
301
|
-
constructor(connection) {
|
|
302
|
-
this.connection = connection;
|
|
303
|
-
this.curve = connection.curve ?? 'bezier';
|
|
304
|
-
this.type = connection.type ?? 'default';
|
|
305
|
-
this.validator = connection.validator ?? (() => true);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function hashCode(str) {
|
|
310
|
-
return str.split('').reduce((a, b) => {
|
|
311
|
-
a = ((a << 5) - a) + b.charCodeAt(0);
|
|
312
|
-
return a & a;
|
|
313
|
-
}, 0);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
class FlowEntitiesService {
|
|
317
|
-
constructor() {
|
|
318
|
-
this.nodes = signal([], {
|
|
319
|
-
// empty arrays considered equal, other arrays may not be equal
|
|
320
|
-
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
321
|
-
});
|
|
322
|
-
this.edges = signal([], {
|
|
323
|
-
// empty arrays considered equal, other arrays may not be equal
|
|
324
|
-
equal: (a, b) => !a.length && !b.length ? true : a === b
|
|
325
|
-
});
|
|
326
|
-
this.connection = signal(new ConnectionModel({}));
|
|
327
|
-
this.markers = computed(() => {
|
|
328
|
-
const markersMap = new Map();
|
|
329
|
-
this.validEdges().forEach(e => {
|
|
330
|
-
if (e.edge.markers?.start) {
|
|
331
|
-
const hash = hashCode(JSON.stringify(e.edge.markers.start));
|
|
332
|
-
markersMap.set(hash, e.edge.markers.start);
|
|
333
|
-
}
|
|
334
|
-
if (e.edge.markers?.end) {
|
|
335
|
-
const hash = hashCode(JSON.stringify(e.edge.markers.end));
|
|
336
|
-
markersMap.set(hash, e.edge.markers.end);
|
|
337
|
-
}
|
|
338
|
-
});
|
|
339
|
-
const connectionMarker = this.connection().connection.marker;
|
|
340
|
-
if (connectionMarker) {
|
|
341
|
-
const hash = hashCode(JSON.stringify(connectionMarker));
|
|
342
|
-
markersMap.set(hash, connectionMarker);
|
|
343
|
-
}
|
|
344
|
-
return markersMap;
|
|
345
|
-
});
|
|
346
|
-
this.validEdges = computed(() => {
|
|
347
|
-
const nodes = this.nodes();
|
|
348
|
-
return this.edges().filter(e => nodes.includes(e.source()) && nodes.includes(e.target()));
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
getNode(id) {
|
|
352
|
-
return this.nodes().find(({ node }) => node.id === id);
|
|
353
|
-
}
|
|
354
|
-
getDetachedEdges() {
|
|
355
|
-
return this.edges().filter(e => e.detached());
|
|
356
|
-
}
|
|
357
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
358
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService }); }
|
|
359
|
-
}
|
|
360
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, decorators: [{
|
|
361
|
-
type: Injectable
|
|
362
|
-
}] });
|
|
363
|
-
|
|
364
417
|
class ConnectionControllerDirective {
|
|
365
418
|
constructor() {
|
|
366
419
|
/**
|
|
@@ -403,16 +456,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
403
456
|
type: Output
|
|
404
457
|
}] } });
|
|
405
458
|
|
|
459
|
+
class FlowSettingsService {
|
|
460
|
+
constructor() {
|
|
461
|
+
this.entitiesSelectable = signal(true);
|
|
462
|
+
/**
|
|
463
|
+
* Global setting with handle positions. Nodes derive this value
|
|
464
|
+
*
|
|
465
|
+
* @deprecated
|
|
466
|
+
*/
|
|
467
|
+
this.handlePositions = signal({ source: 'right', target: 'left' });
|
|
468
|
+
/**
|
|
469
|
+
* @see {VflowComponent.view}
|
|
470
|
+
*/
|
|
471
|
+
this.view = signal([400, 400]);
|
|
472
|
+
this.flowWidth = computed(() => this.view() === 'auto' ? '100%' : this.view()[0]);
|
|
473
|
+
this.flowHeight = computed(() => this.view() === 'auto' ? '100%' : this.view()[1]);
|
|
474
|
+
}
|
|
475
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
476
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService }); }
|
|
477
|
+
}
|
|
478
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowSettingsService, decorators: [{
|
|
479
|
+
type: Injectable
|
|
480
|
+
}] });
|
|
481
|
+
|
|
406
482
|
class NodeModel {
|
|
407
483
|
constructor(node) {
|
|
408
484
|
this.node = node;
|
|
485
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
409
486
|
this.point = signal({ x: 0, y: 0 });
|
|
410
487
|
this.point$ = toObservable(this.point);
|
|
411
488
|
this.size = signal({ width: 0, height: 0 });
|
|
489
|
+
this.renderOrder = signal(0);
|
|
490
|
+
this.selected = signal(false);
|
|
491
|
+
this.selected$ = toObservable(this.selected);
|
|
412
492
|
this.pointTransform = computed(() => `translate(${this.point().x}, ${this.point().y})`);
|
|
413
493
|
// Now source and handle positions derived from parent flow
|
|
414
|
-
this.sourcePosition = computed(() => this.
|
|
415
|
-
this.targetPosition = computed(() => this.
|
|
494
|
+
this.sourcePosition = computed(() => this.flowSettingsService.handlePositions().source);
|
|
495
|
+
this.targetPosition = computed(() => this.flowSettingsService.handlePositions().target);
|
|
416
496
|
this.handles = signal([]);
|
|
417
497
|
this.handles$ = toObservable(this.handles);
|
|
418
498
|
this.draggable = true;
|
|
@@ -422,14 +502,6 @@ class NodeModel {
|
|
|
422
502
|
if (isDefined(node.draggable))
|
|
423
503
|
this.draggable = node.draggable;
|
|
424
504
|
}
|
|
425
|
-
/**
|
|
426
|
-
* Bind parent flow model to node
|
|
427
|
-
*
|
|
428
|
-
* @param flow parent flow
|
|
429
|
-
*/
|
|
430
|
-
bindFlow(flow) {
|
|
431
|
-
this.flow = flow;
|
|
432
|
-
}
|
|
433
505
|
}
|
|
434
506
|
|
|
435
507
|
class EdgeLabelModel {
|
|
@@ -547,6 +619,8 @@ class EdgeModel {
|
|
|
547
619
|
this.edge = edge;
|
|
548
620
|
this.source = signal(undefined);
|
|
549
621
|
this.target = signal(undefined);
|
|
622
|
+
this.selected = signal(false);
|
|
623
|
+
this.selected$ = toObservable(this.selected);
|
|
550
624
|
this.detached = computed(() => {
|
|
551
625
|
const source = this.source();
|
|
552
626
|
const target = this.target();
|
|
@@ -671,7 +745,11 @@ class NodesChangeService {
|
|
|
671
745
|
.pipe(pairwise(), map(([oldList, newList]) => newList.filter(node => !oldList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map(node => ({ type: 'add', id: node.node.id }))));
|
|
672
746
|
this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes)
|
|
673
747
|
.pipe(pairwise(), map(([oldList, newList]) => oldList.filter(node => !newList.includes(node))), filter((nodes) => !!nodes.length), map((nodes) => nodes.map(node => ({ type: 'remove', id: node.node.id }))));
|
|
674
|
-
this.
|
|
748
|
+
this.nodeSelectedChange$ = toObservable(this.entitiesService.nodes)
|
|
749
|
+
.pipe(switchMap((nodes) => merge(...nodes.map(node => node.selected$.pipe(distinctUntilChanged(), skip(1), map(() => node))))), map((changedNode) => [
|
|
750
|
+
{ type: 'select', id: changedNode.node.id, selected: changedNode.selected() }
|
|
751
|
+
]));
|
|
752
|
+
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$, this.nodeSelectedChange$).pipe(
|
|
675
753
|
// this fixes a bug when on fire node event change,
|
|
676
754
|
// you can't get valid list of detached edges
|
|
677
755
|
observeOn(asyncScheduler));
|
|
@@ -708,7 +786,11 @@ class EdgeChangesService {
|
|
|
708
786
|
.pipe(pairwise(), map(([oldList, newList]) => {
|
|
709
787
|
return oldList.filter(edge => !newList.includes(edge));
|
|
710
788
|
}), filter(edges => !!edges.length), map((edges) => edges.map(({ edge }) => ({ type: 'remove', id: edge.id }))));
|
|
711
|
-
this.
|
|
789
|
+
this.edgeSelectChange$ = toObservable(this.entitiesService.edges)
|
|
790
|
+
.pipe(switchMap((edges) => merge(...edges.map(edge => edge.selected$.pipe(distinctUntilChanged(), skip(1), map(() => edge))))), map((changedEdge) => [
|
|
791
|
+
{ type: 'select', id: changedEdge.edge.id, selected: changedEdge.selected() }
|
|
792
|
+
]));
|
|
793
|
+
this.changes$ = merge(this.edgeDetachedChange$, this.edgeAddChange$, this.edgeRemoveChange$, this.edgeSelectChange$)
|
|
712
794
|
.pipe(
|
|
713
795
|
// this fixes the case when user gets 'deteched' changes
|
|
714
796
|
// and tries to delete these edges inside stream
|
|
@@ -757,6 +839,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
757
839
|
type: Output
|
|
758
840
|
}] } });
|
|
759
841
|
|
|
842
|
+
class NodeRenderingService {
|
|
843
|
+
constructor() {
|
|
844
|
+
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
845
|
+
this.nodes = computed(() => {
|
|
846
|
+
return this.flowEntitiesService.nodes()
|
|
847
|
+
.sort((aNode, bNode) => aNode.renderOrder() - bNode.renderOrder());
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
pullNode(node) {
|
|
851
|
+
const maxOrder = Math.max(...this.flowEntitiesService.nodes().map((n) => n.renderOrder()));
|
|
852
|
+
node.renderOrder.set(maxOrder + 1);
|
|
853
|
+
}
|
|
854
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
855
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService }); }
|
|
856
|
+
}
|
|
857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeRenderingService, decorators: [{
|
|
858
|
+
type: Injectable
|
|
859
|
+
}] });
|
|
860
|
+
|
|
760
861
|
class HandleService {
|
|
761
862
|
constructor() {
|
|
762
863
|
this.node = signal(null);
|
|
@@ -868,7 +969,7 @@ function resizable(elems, zone) {
|
|
|
868
969
|
function InjectionContext(target, key, descriptor) {
|
|
869
970
|
const originalMethod = descriptor.value;
|
|
870
971
|
descriptor.value = function (...args) {
|
|
871
|
-
if (this
|
|
972
|
+
if (implementsWithInjector(this)) {
|
|
872
973
|
return runInInjectionContext(this.injector, () => originalMethod.apply(this, args));
|
|
873
974
|
}
|
|
874
975
|
else {
|
|
@@ -878,16 +979,9 @@ function InjectionContext(target, key, descriptor) {
|
|
|
878
979
|
// Return the modified descriptor
|
|
879
980
|
return descriptor;
|
|
880
981
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
}
|
|
885
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WithInjectorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
886
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: WithInjectorDirective, ngImport: i0 }); }
|
|
887
|
-
}
|
|
888
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: WithInjectorDirective, decorators: [{
|
|
889
|
-
type: Directive
|
|
890
|
-
}] });
|
|
982
|
+
const implementsWithInjector = (instance) => {
|
|
983
|
+
return 'injector' in instance && 'get' in instance.injector;
|
|
984
|
+
};
|
|
891
985
|
|
|
892
986
|
function Microtask(target, key, descriptor) {
|
|
893
987
|
const originalMethod = descriptor.value;
|
|
@@ -936,14 +1030,17 @@ function getChildStrokeWidth(element) {
|
|
|
936
1030
|
return 0;
|
|
937
1031
|
}
|
|
938
1032
|
|
|
939
|
-
class NodeComponent
|
|
1033
|
+
class NodeComponent {
|
|
940
1034
|
constructor() {
|
|
941
|
-
|
|
1035
|
+
this.injector = inject(Injector);
|
|
942
1036
|
this.handleService = inject(HandleService);
|
|
943
1037
|
this.zone = inject(NgZone);
|
|
944
1038
|
this.draggableService = inject(DraggableService);
|
|
945
1039
|
this.flowStatusService = inject(FlowStatusService);
|
|
946
1040
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
1041
|
+
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1042
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1043
|
+
this.selectionService = inject(SelectionService);
|
|
947
1044
|
this.hostRef = inject(ElementRef);
|
|
948
1045
|
this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
|
|
949
1046
|
this.flowStatusService.status().state === 'connection-validation');
|
|
@@ -1029,6 +1126,14 @@ class NodeComponent extends WithInjectorDirective {
|
|
|
1029
1126
|
this.flowStatusService.setConnectionStartStatus(status.payload.sourceNode, status.payload.sourceHandle);
|
|
1030
1127
|
}
|
|
1031
1128
|
}
|
|
1129
|
+
pullNode() {
|
|
1130
|
+
this.nodeRenderingService.pullNode(this.nodeModel);
|
|
1131
|
+
}
|
|
1132
|
+
selectNode() {
|
|
1133
|
+
if (this.flowSettingsService.entitiesSelectable()) {
|
|
1134
|
+
this.selectionService.select(this.nodeModel);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1032
1137
|
setInitialHandles() {
|
|
1033
1138
|
if (this.nodeModel.node.type === 'default') {
|
|
1034
1139
|
this.handleService.createHandle(new HandleModel({
|
|
@@ -1043,8 +1148,8 @@ class NodeComponent extends WithInjectorDirective {
|
|
|
1043
1148
|
}, this.nodeModel));
|
|
1044
1149
|
}
|
|
1045
1150
|
}
|
|
1046
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps:
|
|
1047
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeComponent, selector: "g[node]", inputs: { nodeModel: "nodeModel", nodeHtmlTemplate: "nodeHtmlTemplate" }, providers: [HandleService], viewQueries: [{ propertyName: "nodeContentRef", first: true, predicate: ["nodeContent"], descendants: true }, { propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true }],
|
|
1151
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1152
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeComponent, selector: "g[node]", inputs: { nodeModel: "nodeModel", nodeHtmlTemplate: "nodeHtmlTemplate" }, providers: [HandleService], viewQueries: [{ propertyName: "nodeContentRef", first: true, predicate: ["nodeContent"], descendants: true }, { propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true }], ngImport: i0, template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [innerHTML]=\"nodeModel.node.text ?? ''\"\n ></div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngTemplateOutlet]=\"nodeHtmlTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { node: nodeModel.node, selected: nodeModel.selected } }\"\n [ngTemplateOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngFor=\"let handle of nodeModel.handles()\">\n <svg:circle\n *ngIf=\"!handle.template\"\n class=\"default-handle\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n r=\"5\"\n (mousedown)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (mouseup)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (mousedown)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (mouseup)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"handle.rawHandle.type === 'target' && showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (mouseup)=\"endConnection(); resetValidateTargetHandle(handle)\"\n (mouseover)=\"validateTargetHandle(handle)\"\n (mouseout)=\"resetValidateTargetHandle(handle)\"\n />\n</ng-container>\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}.default-node_selected{border-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HandleSizeControllerDirective, selector: "[handleSizeController]", inputs: ["handleSizeController"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1048
1153
|
}
|
|
1049
1154
|
__decorate([
|
|
1050
1155
|
Microtask
|
|
@@ -1054,7 +1159,7 @@ __decorate([
|
|
|
1054
1159
|
], NodeComponent.prototype, "setInitialHandles", null);
|
|
1055
1160
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, decorators: [{
|
|
1056
1161
|
type: Component,
|
|
1057
|
-
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n>\n <div
|
|
1162
|
+
args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, providers: [HandleService], template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n class=\"selectable\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n (mousedown)=\"pullNode(); selectNode()\"\n>\n <div\n #htmlWrapper\n class=\"default-node\"\n [class.default-node_selected]=\"nodeModel.selected()\"\n [innerHTML]=\"nodeModel.node.text ?? ''\"\n ></div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n class=\"selectable\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n (mousedown)=\"pullNode()\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n [ngTemplateOutlet]=\"nodeHtmlTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: { node: nodeModel.node, selected: nodeModel.selected } }\"\n [ngTemplateOutletInjector]=\"injector\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngFor=\"let handle of nodeModel.handles()\">\n <svg:circle\n *ngIf=\"!handle.template\"\n class=\"default-handle\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n [attr.stroke-width]=\"handle.strokeWidth\"\n r=\"5\"\n (mousedown)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (mouseup)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n />\n\n <svg:g\n *ngIf=\"handle.template\"\n [handleSizeController]=\"handle\"\n (mousedown)=\"handle.rawHandle.type === 'source' ? startConnection($event, handle) : null\"\n (mouseup)=\"handle.rawHandle.type === 'target' ? endConnection() : null\"\n >\n <ng-container *ngTemplateOutlet=\"handle.template; context: handle.templateContext\" />\n </svg:g>\n\n <svg:circle\n *ngIf=\"handle.rawHandle.type === 'target' && showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"handle.offset().x\"\n [attr.cy]=\"handle.offset().y\"\n (mouseup)=\"endConnection(); resetValidateTargetHandle(handle)\"\n (mouseover)=\"validateTargetHandle(handle)\"\n (mouseout)=\"resetValidateTargetHandle(handle)\"\n />\n</ng-container>\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;border:1.5px solid #1b262c;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}.default-node_selected{border-width:2px}.default-handle{stroke:#fff;fill:#1b262c}\n"] }]
|
|
1058
1163
|
}], propDecorators: { nodeModel: [{
|
|
1059
1164
|
type: Input
|
|
1060
1165
|
}], nodeHtmlTemplate: [{
|
|
@@ -1125,6 +1230,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1125
1230
|
|
|
1126
1231
|
class EdgeComponent {
|
|
1127
1232
|
constructor() {
|
|
1233
|
+
this.injector = inject(Injector);
|
|
1234
|
+
this.selectionService = inject(SelectionService);
|
|
1235
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1128
1236
|
this.markerStartUrl = computed(() => {
|
|
1129
1237
|
const marker = this.model.edge.markers?.start;
|
|
1130
1238
|
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
@@ -1133,7 +1241,6 @@ class EdgeComponent {
|
|
|
1133
1241
|
const marker = this.model.edge.markers?.end;
|
|
1134
1242
|
return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
|
|
1135
1243
|
});
|
|
1136
|
-
this.defaultColor = 'rgb(177, 177, 183)';
|
|
1137
1244
|
}
|
|
1138
1245
|
ngOnInit() {
|
|
1139
1246
|
this.edgeContext = {
|
|
@@ -1142,16 +1249,24 @@ class EdgeComponent {
|
|
|
1142
1249
|
edge: this.model.edge,
|
|
1143
1250
|
path: computed(() => this.model.path().path),
|
|
1144
1251
|
markerStart: this.markerStartUrl,
|
|
1145
|
-
markerEnd: this.markerEndUrl
|
|
1252
|
+
markerEnd: this.markerEndUrl,
|
|
1253
|
+
selected: this.model.selected.asReadonly()
|
|
1146
1254
|
}
|
|
1147
1255
|
};
|
|
1148
1256
|
}
|
|
1257
|
+
onEdgeMouseDown() {
|
|
1258
|
+
if (this.flowSettingsService.entitiesSelectable()) {
|
|
1259
|
+
this.selectionService.select(this.model);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1149
1262
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1150
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EdgeComponent, selector: "g[edge]", inputs: { model: "model", edgeTemplate: "edgeTemplate", edgeLabelHtmlTemplate: "edgeLabelHtmlTemplate" }, ngImport: i0, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n
|
|
1263
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EdgeComponent, selector: "g[edge]", inputs: { model: "model", edgeTemplate: "edgeTemplate", edgeLabelHtmlTemplate: "edgeLabelHtmlTemplate" }, host: { classAttribute: "selectable" }, ngImport: i0, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n (mousedown)=\"onEdgeMouseDown()\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n class=\"edge\"\n [class.edge_selected]=\"model.selected()\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\"\n ></ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.start as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.start\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.center as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.center\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.end as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.end\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1151
1264
|
}
|
|
1152
1265
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, decorators: [{
|
|
1153
1266
|
type: Component,
|
|
1154
|
-
args: [{ selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1267
|
+
args: [{ selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1268
|
+
'class': 'selectable'
|
|
1269
|
+
}, template: "<svg:path\n *ngIf=\"model.type === 'default'\"\n (mousedown)=\"onEdgeMouseDown()\"\n [attr.d]=\"model.path().path\"\n [attr.marker-start]=\"markerStartUrl()\"\n [attr.marker-end]=\"markerEndUrl()\"\n class=\"edge\"\n [class.edge_selected]=\"model.selected()\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container\n [ngTemplateOutlet]=\"edgeTemplate\"\n [ngTemplateOutletContext]=\"edgeContext\"\n [ngTemplateOutletInjector]=\"injector\"\n ></ng-container>\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.start as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.start\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.center as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.center\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n\n<ng-container *ngIf=\"model.edgeLabels?.end as label\">\n <svg:g edgeLabel\n [model]=\"label\"\n [point]=\"model.path().points.end\"\n [edgeModel]=\"model\"\n [htmlTemplate]=\"edgeLabelHtmlTemplate\"\n />\n</ng-container>\n", styles: [".edge{fill:none;stroke-width:2;stroke:#b1b1b7}.edge_selected{stroke-width:2.5;stroke:#0f4c75}\n"] }]
|
|
1155
1270
|
}], propDecorators: { model: [{
|
|
1156
1271
|
type: Input
|
|
1157
1272
|
}], edgeTemplate: [{
|
|
@@ -1350,6 +1465,8 @@ class VflowComponent {
|
|
|
1350
1465
|
this.flowEntitiesService = inject(FlowEntitiesService);
|
|
1351
1466
|
this.nodesChangeService = inject(NodesChangeService);
|
|
1352
1467
|
this.edgesChangeService = inject(EdgeChangesService);
|
|
1468
|
+
this.nodeRenderingService = inject(NodeRenderingService);
|
|
1469
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1353
1470
|
this.injector = inject(Injector);
|
|
1354
1471
|
/**
|
|
1355
1472
|
* Minimum zoom value
|
|
@@ -1363,6 +1480,8 @@ class VflowComponent {
|
|
|
1363
1480
|
* Background color for flow
|
|
1364
1481
|
*/
|
|
1365
1482
|
this.background = '#FFFFFF';
|
|
1483
|
+
this.nodeModels = computed(() => this.nodeRenderingService.nodes());
|
|
1484
|
+
this.edgeModels = computed(() => this.flowEntitiesService.validEdges());
|
|
1366
1485
|
// #endregion
|
|
1367
1486
|
// #region SIGNAL_API
|
|
1368
1487
|
/**
|
|
@@ -1393,8 +1512,8 @@ class VflowComponent {
|
|
|
1393
1512
|
*/
|
|
1394
1513
|
this.edgesChange$ = this.edgesChangeService.changes$;
|
|
1395
1514
|
// #endregion
|
|
1396
|
-
|
|
1397
|
-
this.
|
|
1515
|
+
this.flowWidth = this.flowSettingsService.flowWidth;
|
|
1516
|
+
this.flowHeight = this.flowSettingsService.flowHeight;
|
|
1398
1517
|
this.markers = this.flowEntitiesService.markers;
|
|
1399
1518
|
}
|
|
1400
1519
|
// #endregion
|
|
@@ -1407,7 +1526,7 @@ class VflowComponent {
|
|
|
1407
1526
|
* - 'auto' to compute size based on parent element size
|
|
1408
1527
|
*/
|
|
1409
1528
|
set view(view) {
|
|
1410
|
-
this.
|
|
1529
|
+
this.flowSettingsService.view.set(view);
|
|
1411
1530
|
}
|
|
1412
1531
|
/**
|
|
1413
1532
|
* Object that controls flow direction.
|
|
@@ -1418,7 +1537,13 @@ class VflowComponent {
|
|
|
1418
1537
|
* @deprecated
|
|
1419
1538
|
*/
|
|
1420
1539
|
set handlePositions(handlePositions) {
|
|
1421
|
-
this.
|
|
1540
|
+
this.flowSettingsService.handlePositions.set(handlePositions);
|
|
1541
|
+
}
|
|
1542
|
+
/**
|
|
1543
|
+
* Global rule if you can or can't select entities
|
|
1544
|
+
*/
|
|
1545
|
+
set entitiesSelectable(value) {
|
|
1546
|
+
this.flowSettingsService.entitiesSelectable.set(value);
|
|
1422
1547
|
}
|
|
1423
1548
|
/**
|
|
1424
1549
|
* Settings for connection (it renders when user tries to create edge between nodes)
|
|
@@ -1434,23 +1559,19 @@ class VflowComponent {
|
|
|
1434
1559
|
*/
|
|
1435
1560
|
set nodes(newNodes) {
|
|
1436
1561
|
const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.nodes(newNodes, this.flowEntitiesService.nodes()));
|
|
1437
|
-
// TODO better to solve this by DI
|
|
1438
|
-
bindFlowToNodes(this.flowModel, newModels);
|
|
1439
1562
|
// quick and dirty binding nodes to edges
|
|
1440
1563
|
addNodesToEdges(newModels, this.flowEntitiesService.edges());
|
|
1441
1564
|
this.flowEntitiesService.nodes.set(newModels);
|
|
1442
1565
|
}
|
|
1443
|
-
get nodeModels() { return this.flowEntitiesService.nodes(); }
|
|
1444
1566
|
/**
|
|
1445
1567
|
* Edges to render
|
|
1446
1568
|
*/
|
|
1447
1569
|
set edges(newEdges) {
|
|
1448
1570
|
const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.edges(newEdges, this.flowEntitiesService.edges()));
|
|
1449
1571
|
// quick and dirty binding nodes to edges
|
|
1450
|
-
addNodesToEdges(this.nodeModels, newModels);
|
|
1572
|
+
addNodesToEdges(this.nodeModels(), newModels);
|
|
1451
1573
|
this.flowEntitiesService.edges.set(newModels);
|
|
1452
1574
|
}
|
|
1453
|
-
get edgeModels() { return this.flowEntitiesService.validEdges(); }
|
|
1454
1575
|
// #region METHODS_API
|
|
1455
1576
|
/**
|
|
1456
1577
|
* Change viewport to specified state
|
|
@@ -1498,14 +1619,17 @@ class VflowComponent {
|
|
|
1498
1619
|
return edge;
|
|
1499
1620
|
}
|
|
1500
1621
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1501
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: VflowComponent, selector: "vflow", inputs: { view: "view", minZoom: "minZoom", maxZoom: "maxZoom", handlePositions: "handlePositions", background: "background", connection: ["connection", "connection", (settings) => new ConnectionModel(settings)], nodes: "nodes", edges: "edges" }, providers: [
|
|
1622
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "16.2.12", type: VflowComponent, selector: "vflow", inputs: { view: "view", minZoom: "minZoom", maxZoom: "maxZoom", handlePositions: "handlePositions", background: "background", entitiesSelectable: "entitiesSelectable", connection: ["connection", "connection", (settings) => new ConnectionModel(settings)], nodes: "nodes", edges: "edges" }, providers: [
|
|
1502
1623
|
DraggableService,
|
|
1503
1624
|
ViewportService,
|
|
1504
1625
|
FlowStatusService,
|
|
1505
1626
|
FlowEntitiesService,
|
|
1506
1627
|
NodesChangeService,
|
|
1507
|
-
EdgeChangesService
|
|
1508
|
-
|
|
1628
|
+
EdgeChangesService,
|
|
1629
|
+
NodeRenderingService,
|
|
1630
|
+
SelectionService,
|
|
1631
|
+
FlowSettingsService
|
|
1632
|
+
], queries: [{ propertyName: "nodeHtmlDirective", first: true, predicate: NodeHtmlTemplateDirective, descendants: true }, { propertyName: "edgeTemplateDirective", first: true, predicate: EdgeTemplateDirective, descendants: true }, { propertyName: "edgeLabelHtmlDirective", first: true, predicate: EdgeLabelHtmlTemplateDirective, descendants: true }, { propertyName: "connectionTemplateDirective", first: true, predicate: ConnectionTemplateDirective, descendants: true }], viewQueries: [{ propertyName: "mapContext", first: true, predicate: MapContextDirective, descendants: true }], hostDirectives: [{ directive: ConnectionControllerDirective, outputs: ["onConnect", "onConnect"] }, { directive: ChangesControllerDirective, outputs: ["onNodesChange", "onNodesChange", "onEdgesChange", "onEdgesChange"] }], ngImport: i0, template: "<svg:svg\n rootSvgRef\n rootSvgContext\n class=\"root-svg\"\n #flow\n [style.backgroundColor]=\"background\"\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\n\n <svg:g\n mapContext\n spacePointContext\n [minZoom]=\"minZoom\"\n [maxZoom]=\"maxZoom\"\n >\n <!-- Connection -->\n <svg:g\n connection\n [model]=\"connection\"\n [template]=\"connectionTemplateDirective?.templateRef\"\n />\n\n <!-- Edges -->\n <svg:g\n *ngFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective?.templateRef\"\n />\n\n <!-- Nodes -->\n <svg:g\n *ngFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [nodeModel]=\"model\"\n [nodeHtmlTemplate]=\"nodeHtmlDirective?.templateRef\"\n [attr.transform]=\"model.pointTransform()\"\n />\n </svg:g>\n\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: NodeComponent, selector: "g[node]", inputs: ["nodeModel", "nodeHtmlTemplate"] }, { kind: "component", type: EdgeComponent, selector: "g[edge]", inputs: ["model", "edgeTemplate", "edgeLabelHtmlTemplate"] }, { kind: "component", type: ConnectionComponent, selector: "g[connection]", inputs: ["model", "template"] }, { kind: "component", type: DefsComponent, selector: "defs[flowDefs]", inputs: ["markers"] }, { kind: "directive", type: SpacePointContextDirective, selector: "g[spacePointContext]" }, { kind: "directive", type: MapContextDirective, selector: "g[mapContext]", inputs: ["minZoom", "maxZoom"] }, { kind: "directive", type: RootSvgReferenceDirective, selector: "svg[rootSvgRef]" }, { kind: "directive", type: RootSvgContextDirective, selector: "svg[rootSvgContext]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
1509
1633
|
}
|
|
1510
1634
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: VflowComponent, decorators: [{
|
|
1511
1635
|
type: Component,
|
|
@@ -1515,11 +1639,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1515
1639
|
FlowStatusService,
|
|
1516
1640
|
FlowEntitiesService,
|
|
1517
1641
|
NodesChangeService,
|
|
1518
|
-
EdgeChangesService
|
|
1642
|
+
EdgeChangesService,
|
|
1643
|
+
NodeRenderingService,
|
|
1644
|
+
SelectionService,
|
|
1645
|
+
FlowSettingsService
|
|
1519
1646
|
], hostDirectives: [
|
|
1520
1647
|
connectionControllerHostDirective,
|
|
1521
1648
|
changesControllerHostDirective
|
|
1522
|
-
], template: "<svg:svg\n rootSvgRef\n rootSvgContext\n class=\"root-svg\"\n #flow\n [style.backgroundColor]=\"background\"\n [attr.width]=\"
|
|
1649
|
+
], template: "<svg:svg\n rootSvgRef\n rootSvgContext\n class=\"root-svg\"\n #flow\n [style.backgroundColor]=\"background\"\n [attr.width]=\"flowWidth()\"\n [attr.height]=\"flowHeight()\"\n>\n <defs [markers]=\"markers()\" flowDefs />\n\n <svg:g\n mapContext\n spacePointContext\n [minZoom]=\"minZoom\"\n [maxZoom]=\"maxZoom\"\n >\n <!-- Connection -->\n <svg:g\n connection\n [model]=\"connection\"\n [template]=\"connectionTemplateDirective?.templateRef\"\n />\n\n <!-- Edges -->\n <svg:g\n *ngFor=\"let model of edgeModels(); trackBy: trackEdges\"\n edge\n [model]=\"model\"\n [edgeTemplate]=\"edgeTemplateDirective?.templateRef\"\n [edgeLabelHtmlTemplate]=\"edgeLabelHtmlDirective?.templateRef\"\n />\n\n <!-- Nodes -->\n <svg:g\n *ngFor=\"let model of nodeModels(); trackBy: trackNodes\"\n node\n [nodeModel]=\"model\"\n [nodeHtmlTemplate]=\"nodeHtmlDirective?.templateRef\"\n [attr.transform]=\"model.pointTransform()\"\n />\n </svg:g>\n\n</svg:svg>\n", styles: [":host{display:block;width:100%;height:100%;-webkit-user-select:none;user-select:none}:host ::ng-deep *{box-sizing:border-box}\n"] }]
|
|
1523
1650
|
}], propDecorators: { view: [{
|
|
1524
1651
|
type: Input
|
|
1525
1652
|
}], minZoom: [{
|
|
@@ -1530,6 +1657,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1530
1657
|
type: Input
|
|
1531
1658
|
}], background: [{
|
|
1532
1659
|
type: Input
|
|
1660
|
+
}], entitiesSelectable: [{
|
|
1661
|
+
type: Input
|
|
1533
1662
|
}], connection: [{
|
|
1534
1663
|
type: Input,
|
|
1535
1664
|
args: [{ transform: (settings) => new ConnectionModel(settings) }]
|
|
@@ -1554,13 +1683,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1554
1683
|
type: ViewChild,
|
|
1555
1684
|
args: [MapContextDirective]
|
|
1556
1685
|
}] } });
|
|
1557
|
-
function bindFlowToNodes(flow, nodes) {
|
|
1558
|
-
nodes.forEach(n => n.bindFlow(flow));
|
|
1559
|
-
}
|
|
1560
1686
|
|
|
1561
|
-
class HandleComponent
|
|
1687
|
+
class HandleComponent {
|
|
1562
1688
|
constructor() {
|
|
1563
|
-
|
|
1689
|
+
this.injector = inject(Injector);
|
|
1564
1690
|
this.handleService = inject(HandleService);
|
|
1565
1691
|
this.element = inject(ElementRef).nativeElement;
|
|
1566
1692
|
}
|
|
@@ -1578,8 +1704,8 @@ class HandleComponent extends WithInjectorDirective {
|
|
|
1578
1704
|
ngOnDestroy() {
|
|
1579
1705
|
this.handleService.destroyHandle(this.model);
|
|
1580
1706
|
}
|
|
1581
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps:
|
|
1582
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HandleComponent, selector: "handle", inputs: { position: "position", type: "type", id: "id", template: "template" },
|
|
1707
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1708
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: HandleComponent, selector: "handle", inputs: { position: "position", type: "type", id: "id", template: "template" }, ngImport: i0, template: "" }); }
|
|
1583
1709
|
}
|
|
1584
1710
|
__decorate([
|
|
1585
1711
|
InjectionContext
|
|
@@ -1599,6 +1725,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1599
1725
|
type: Input
|
|
1600
1726
|
}], ngOnInit: [] } });
|
|
1601
1727
|
|
|
1728
|
+
class SelectableDirective {
|
|
1729
|
+
constructor() {
|
|
1730
|
+
this.flowSettingsService = inject(FlowSettingsService);
|
|
1731
|
+
this.selectionService = inject(SelectionService);
|
|
1732
|
+
this.parentEdge = inject(EdgeComponent, { optional: true });
|
|
1733
|
+
this.parentNode = inject(NodeComponent, { optional: true });
|
|
1734
|
+
}
|
|
1735
|
+
onMousedown() {
|
|
1736
|
+
const entity = this.entity();
|
|
1737
|
+
if (entity && this.flowSettingsService.entitiesSelectable()) {
|
|
1738
|
+
this.selectionService.select(entity);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
entity() {
|
|
1742
|
+
if (this.parentNode) {
|
|
1743
|
+
return this.parentNode.nodeModel;
|
|
1744
|
+
}
|
|
1745
|
+
else if (this.parentEdge) {
|
|
1746
|
+
return this.parentEdge.model;
|
|
1747
|
+
}
|
|
1748
|
+
return null;
|
|
1749
|
+
}
|
|
1750
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1751
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: SelectableDirective, selector: "[selectable]", host: { listeners: { "mousedown": "onMousedown()" } }, ngImport: i0 }); }
|
|
1752
|
+
}
|
|
1753
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SelectableDirective, decorators: [{
|
|
1754
|
+
type: Directive,
|
|
1755
|
+
args: [{ selector: '[selectable]' }]
|
|
1756
|
+
}], propDecorators: { onMousedown: [{
|
|
1757
|
+
type: HostListener,
|
|
1758
|
+
args: ['mousedown']
|
|
1759
|
+
}] } });
|
|
1760
|
+
|
|
1602
1761
|
const components = [
|
|
1603
1762
|
VflowComponent,
|
|
1604
1763
|
NodeComponent,
|
|
@@ -1613,7 +1772,8 @@ const directives = [
|
|
|
1613
1772
|
MapContextDirective,
|
|
1614
1773
|
RootSvgReferenceDirective,
|
|
1615
1774
|
RootSvgContextDirective,
|
|
1616
|
-
HandleSizeControllerDirective
|
|
1775
|
+
HandleSizeControllerDirective,
|
|
1776
|
+
SelectableDirective
|
|
1617
1777
|
];
|
|
1618
1778
|
const templateDirectives = [
|
|
1619
1779
|
NodeHtmlTemplateDirective,
|
|
@@ -1634,12 +1794,14 @@ class VflowModule {
|
|
|
1634
1794
|
MapContextDirective,
|
|
1635
1795
|
RootSvgReferenceDirective,
|
|
1636
1796
|
RootSvgContextDirective,
|
|
1637
|
-
HandleSizeControllerDirective,
|
|
1797
|
+
HandleSizeControllerDirective,
|
|
1798
|
+
SelectableDirective, NodeHtmlTemplateDirective,
|
|
1638
1799
|
EdgeLabelHtmlTemplateDirective,
|
|
1639
1800
|
EdgeTemplateDirective,
|
|
1640
1801
|
ConnectionTemplateDirective,
|
|
1641
1802
|
HandleTemplateDirective], imports: [CommonModule], exports: [VflowComponent,
|
|
1642
|
-
HandleComponent,
|
|
1803
|
+
HandleComponent,
|
|
1804
|
+
SelectableDirective, NodeHtmlTemplateDirective,
|
|
1643
1805
|
EdgeLabelHtmlTemplateDirective,
|
|
1644
1806
|
EdgeTemplateDirective,
|
|
1645
1807
|
ConnectionTemplateDirective,
|
|
@@ -1653,6 +1815,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1653
1815
|
exports: [
|
|
1654
1816
|
VflowComponent,
|
|
1655
1817
|
HandleComponent,
|
|
1818
|
+
SelectableDirective,
|
|
1656
1819
|
...templateDirectives
|
|
1657
1820
|
],
|
|
1658
1821
|
declarations: [...components, ...directives, ...templateDirectives],
|
|
@@ -1665,5 +1828,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
1665
1828
|
* Generated bundle index. Do not edit.
|
|
1666
1829
|
*/
|
|
1667
1830
|
|
|
1668
|
-
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, VflowComponent, VflowModule };
|
|
1831
|
+
export { ChangesControllerDirective, ConnectionControllerDirective, ConnectionTemplateDirective, EdgeLabelHtmlTemplateDirective, EdgeTemplateDirective, HandleComponent, HandleTemplateDirective, NodeHtmlTemplateDirective, SelectableDirective, VflowComponent, VflowModule };
|
|
1669
1832
|
//# sourceMappingURL=ngx-vflow.mjs.map
|