ngx-vflow 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/vflow/components/handle/handle.component.mjs +16 -15
- package/esm2022/lib/vflow/components/node/node.component.mjs +3 -5
- package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +8 -2
- package/esm2022/lib/vflow/models/edge.model.mjs +27 -1
- package/esm2022/lib/vflow/models/handle.model.mjs +7 -5
- package/esm2022/lib/vflow/models/node.model.mjs +6 -6
- package/esm2022/lib/vflow/services/edge-changes.service.mjs +13 -6
- package/esm2022/lib/vflow/services/flow-entities.service.mjs +4 -1
- package/esm2022/lib/vflow/services/handle.service.mjs +11 -4
- package/esm2022/lib/vflow/services/node-changes.service.mjs +6 -3
- package/esm2022/lib/vflow/types/edge-change.type.mjs +1 -1
- package/fesm2022/ngx-vflow.mjs +87 -36
- package/fesm2022/ngx-vflow.mjs.map +1 -1
- package/lib/vflow/components/handle/handle.component.d.ts +5 -2
- package/lib/vflow/components/vflow/vflow.component.d.ts +4 -0
- package/lib/vflow/models/edge.model.d.ts +19 -1
- package/lib/vflow/models/handle.model.d.ts +5 -0
- package/lib/vflow/models/node.model.d.ts +1 -2
- package/lib/vflow/services/flow-entities.service.d.ts +1 -0
- package/lib/vflow/services/handle.service.d.ts +8 -7
- package/lib/vflow/types/edge-change.type.d.ts +3 -0
- package/package.json +1 -1
|
@@ -2,13 +2,20 @@ import { Injectable, signal } from '@angular/core';
|
|
|
2
2
|
import * as i0 from "@angular/core";
|
|
3
3
|
export class HandleService {
|
|
4
4
|
constructor() {
|
|
5
|
-
this.
|
|
5
|
+
this.node = signal(null);
|
|
6
6
|
}
|
|
7
7
|
createHandle(newHandle) {
|
|
8
|
-
this.
|
|
8
|
+
const node = this.node();
|
|
9
|
+
if (node) {
|
|
10
|
+
node.rawHandles.update(handles => [...handles, newHandle]);
|
|
11
|
+
}
|
|
9
12
|
}
|
|
10
13
|
destroyHandle(handleToDestoy) {
|
|
11
|
-
|
|
14
|
+
const node = this.node();
|
|
15
|
+
// TODO: microtask
|
|
16
|
+
if (node) {
|
|
17
|
+
queueMicrotask(() => node.rawHandles.update(handles => handles.filter(handle => handle !== handleToDestoy)));
|
|
18
|
+
}
|
|
12
19
|
}
|
|
13
20
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
14
21
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleService }); }
|
|
@@ -16,4 +23,4 @@ export class HandleService {
|
|
|
16
23
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleService, decorators: [{
|
|
17
24
|
type: Injectable
|
|
18
25
|
}] });
|
|
19
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGFuZGxlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvc2VydmljZXMvaGFuZGxlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBZ0IzRCxNQUFNLE9BQU8sYUFBYTtJQUQxQjtRQUVrQixTQUFJLEdBQUcsTUFBTSxDQUFtQixJQUFJLENBQUMsQ0FBQTtLQWtCdEQ7SUFoQlEsWUFBWSxDQUFDLFNBQXNCO1FBQ3hDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtRQUN4QixJQUFJLElBQUksRUFBRTtZQUNSLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFBO1NBQzNEO0lBQ0gsQ0FBQztJQUVNLGFBQWEsQ0FBQyxjQUEyQjtRQUM5QyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUE7UUFDeEIsa0JBQWtCO1FBQ2xCLElBQUksSUFBSSxFQUFFO1lBQ1IsY0FBYyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUN6QyxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEtBQUssY0FBYyxDQUFDLENBQy9ELENBQUMsQ0FBQztTQUNKO0lBQ0gsQ0FBQzsrR0FsQlUsYUFBYTttSEFBYixhQUFhOzs0RkFBYixhQUFhO2tCQUR6QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgU2lnbmFsLCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFBvc2l0aW9uIH0gZnJvbSAnLi4vdHlwZXMvcG9zaXRpb24udHlwZSc7XG5pbXBvcnQgeyBIYW5kbGVUeXBlIH0gZnJvbSAnLi4vdHlwZXMvaGFuZGxlLXR5cGUudHlwZSc7XG5pbXBvcnQgeyBQb2ludCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcG9pbnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IE5vZGVNb2RlbCB9IGZyb20gJy4uL21vZGVscy9ub2RlLm1vZGVsJztcbmltcG9ydCB7IEhhbmRsZU1vZGVsIH0gZnJvbSAnLi4vbW9kZWxzL2hhbmRsZS5tb2RlbCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZUhhbmRsZSB7XG4gIHBvc2l0aW9uOiBQb3NpdGlvblxuICB0eXBlOiBIYW5kbGVUeXBlXG4gIHBhcmVudFBvc2l0aW9uOiBQb2ludFxuICBwYXJlbnRTaXplOiB7IHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyIH1cbiAgaWQ/OiBzdHJpbmdcbn1cblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEhhbmRsZVNlcnZpY2Uge1xuICBwdWJsaWMgcmVhZG9ubHkgbm9kZSA9IHNpZ25hbDxOb2RlTW9kZWwgfCBudWxsPihudWxsKVxuXG4gIHB1YmxpYyBjcmVhdGVIYW5kbGUobmV3SGFuZGxlOiBIYW5kbGVNb2RlbCkge1xuICAgIGNvbnN0IG5vZGUgPSB0aGlzLm5vZGUoKVxuICAgIGlmIChub2RlKSB7XG4gICAgICBub2RlLnJhd0hhbmRsZXMudXBkYXRlKGhhbmRsZXMgPT4gWy4uLmhhbmRsZXMsIG5ld0hhbmRsZV0pXG4gICAgfVxuICB9XG5cbiAgcHVibGljIGRlc3Ryb3lIYW5kbGUoaGFuZGxlVG9EZXN0b3k6IEhhbmRsZU1vZGVsKSB7XG4gICAgY29uc3Qgbm9kZSA9IHRoaXMubm9kZSgpXG4gICAgLy8gVE9ETzogbWljcm90YXNrXG4gICAgaWYgKG5vZGUpIHtcbiAgICAgIHF1ZXVlTWljcm90YXNrKCgpID0+IG5vZGUucmF3SGFuZGxlcy51cGRhdGUoXG4gICAgICAgIGhhbmRsZXMgPT4gaGFuZGxlcy5maWx0ZXIoaGFuZGxlID0+IGhhbmRsZSAhPT0gaGFuZGxlVG9EZXN0b3kpXG4gICAgICApKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Injectable, inject } from '@angular/core';
|
|
2
2
|
import { FlowEntitiesService } from './flow-entities.service';
|
|
3
3
|
import { toObservable } from '@angular/core/rxjs-interop';
|
|
4
|
-
import { filter, map, merge, pairwise, skip, switchMap } from 'rxjs';
|
|
4
|
+
import { asyncScheduler, filter, map, merge, observeOn, pairwise, skip, switchMap } from 'rxjs';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
6
|
export class NodesChangeService {
|
|
7
7
|
constructor() {
|
|
@@ -21,7 +21,10 @@ export class NodesChangeService {
|
|
|
21
21
|
.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 }))));
|
|
22
22
|
this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes)
|
|
23
23
|
.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 }))));
|
|
24
|
-
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$)
|
|
24
|
+
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$).pipe(
|
|
25
|
+
// this fixes a bug when on fire node event change,
|
|
26
|
+
// you can't get valid list of detached edges
|
|
27
|
+
observeOn(asyncScheduler));
|
|
25
28
|
}
|
|
26
29
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodesChangeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
27
30
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodesChangeService }); }
|
|
@@ -29,4 +32,4 @@ export class NodesChangeService {
|
|
|
29
32
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodesChangeService, decorators: [{
|
|
30
33
|
type: Injectable
|
|
31
34
|
}] });
|
|
32
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS1jaGFuZ2VzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvc2VydmljZXMvbm9kZS1jaGFuZ2VzLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0QsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFlBQVksRUFBWSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BFLE9BQU8sRUFBYyxjQUFjLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFNLFFBQVEsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDOztBQUloSCxNQUFNLE9BQU8sa0JBQWtCO0lBRC9CO1FBRVksb0JBQWUsR0FBRyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQTtRQUU3Qyx5QkFBb0IsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUM7YUFDdEUsSUFBSTtRQUNILDZGQUE2RjtRQUM3RixTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNsQixLQUFLLENBQ0gsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSTtRQUNkLG9DQUFvQztRQUNwQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQ1AsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUNoQixDQUNGLENBQ0YsQ0FDRjtRQUNELGtFQUFrRTtRQUNsRSxtQ0FBbUM7UUFDbkMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDakIsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRSxXQUFXLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUssRUFBRSxFQUFFO1NBQzFFLENBQUMsQ0FDZ0MsQ0FBQTtRQUU1QixtQkFBYyxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQzthQUNoRSxJQUFJLENBQ0gsUUFBUSxFQUFFLEVBQ1YsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUN6QixPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQ2hELEVBQ0QsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxFQUNqQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUNaLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQ3ZELENBQ2lDLENBQUE7UUFFNUIsc0JBQWlCLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDO2FBQ25FLElBQUksQ0FDSCxRQUFRLEVBQUUsRUFDVixHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQ3pCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FDaEQsRUFDRCxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQ2pDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQ1osS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FDMUQsQ0FDaUMsQ0FBQTtRQUV0QixhQUFRLEdBQTZCLEtBQUssQ0FDeEQsSUFBSSxDQUFDLG9CQUFvQixFQUN6QixJQUFJLENBQUMsY0FBYyxFQUNuQixJQUFJLENBQUMsaUJBQWlCLENBQ3ZCLENBQUMsSUFBSTtRQUNKLG1EQUFtRDtRQUNuRCw2Q0FBNkM7UUFDN0MsU0FBUyxDQUFDLGNBQWMsQ0FBQyxDQUMxQixDQUFBO0tBQ0Y7K0dBekRZLGtCQUFrQjttSEFBbEIsa0JBQWtCOzs0RkFBbEIsa0JBQWtCO2tCQUQ5QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgU2lnbmFsLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZsb3dFbnRpdGllc1NlcnZpY2UgfSBmcm9tICcuL2Zsb3ctZW50aXRpZXMuc2VydmljZSc7XG5pbXBvcnQgeyB0b09ic2VydmFibGUsIHRvU2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgYXN5bmNTY2hlZHVsZXIsIGZpbHRlciwgbWFwLCBtZXJnZSwgb2JzZXJ2ZU9uLCBvZiwgcGFpcndpc2UsIHNraXAsIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTm9kZUNoYW5nZSB9IGZyb20gJy4uL3R5cGVzL25vZGUtY2hhbmdlLnR5cGUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTm9kZXNDaGFuZ2VTZXJ2aWNlIHtcbiAgcHJvdGVjdGVkIGVudGl0aWVzU2VydmljZSA9IGluamVjdChGbG93RW50aXRpZXNTZXJ2aWNlKVxuXG4gIHByb3RlY3RlZCBub2Rlc1Bvc2l0aW9uQ2hhbmdlJCA9IHRvT2JzZXJ2YWJsZSh0aGlzLmVudGl0aWVzU2VydmljZS5ub2RlcylcbiAgICAucGlwZShcbiAgICAgIC8vIENoZWNrIGZvciBub2RlcyBsaXN0IGNoYW5nZSBhbmQgd2F0Y2ggZm9yIHNwZWNpZmljIG5vZGUgZnJvbSB0aGlzIGxpc3QgY2hhbmdlIGl0cyBwb3NpdGlvblxuICAgICAgc3dpdGNoTWFwKChub2RlcykgPT5cbiAgICAgICAgbWVyZ2UoXG4gICAgICAgICAgLi4ubm9kZXMubWFwKG5vZGUgPT5cbiAgICAgICAgICAgIG5vZGUucG9pbnQkLnBpcGUoXG4gICAgICAgICAgICAgIC8vIHNraXAgaW5pdGlhbCBwb3NpdGlvbiBmcm9tIHNpZ25hbFxuICAgICAgICAgICAgICBza2lwKDEpLFxuICAgICAgICAgICAgICBtYXAoKCkgPT4gbm9kZSlcbiAgICAgICAgICAgIClcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICksXG4gICAgICAvLyBGb3Igbm93IGl0J3MgYSBzaW5nbGUgbm9kZSwgbGF0ZXIgdGhpcyBsaXN0IHdpbGwgYWxzbyBiZSBmaWxsZWRcbiAgICAgIC8vIHdpdGggY2hpbGQgbm9kZSBwb3NpdGlvbiBjaGFuZ2VzXG4gICAgICBtYXAoY2hhbmdlZE5vZGUgPT4gW1xuICAgICAgICB7IHR5cGU6ICdwb3NpdGlvbicsIGlkOiBjaGFuZ2VkTm9kZS5ub2RlLmlkLCBwb2ludDogY2hhbmdlZE5vZGUucG9pbnQoKSB9XG4gICAgICBdKVxuICAgICkgc2F0aXNmaWVzIE9ic2VydmFibGU8Tm9kZUNoYW5nZVtdPlxuXG4gIHByb3RlY3RlZCBub2RlQWRkQ2hhbmdlJCA9IHRvT2JzZXJ2YWJsZSh0aGlzLmVudGl0aWVzU2VydmljZS5ub2RlcylcbiAgICAucGlwZShcbiAgICAgIHBhaXJ3aXNlKCksXG4gICAgICBtYXAoKFtvbGRMaXN0LCBuZXdMaXN0XSkgPT5cbiAgICAgICAgbmV3TGlzdC5maWx0ZXIobm9kZSA9PiAhb2xkTGlzdC5pbmNsdWRlcyhub2RlKSlcbiAgICAgICksXG4gICAgICBmaWx0ZXIoKG5vZGVzKSA9PiAhIW5vZGVzLmxlbmd0aCksXG4gICAgICBtYXAoKG5vZGVzKSA9PlxuICAgICAgICBub2Rlcy5tYXAobm9kZSA9PiAoeyB0eXBlOiAnYWRkJywgaWQ6IG5vZGUubm9kZS5pZCB9KSlcbiAgICAgIClcbiAgICApIHNhdGlzZmllcyBPYnNlcnZhYmxlPE5vZGVDaGFuZ2VbXT5cblxuICBwcm90ZWN0ZWQgbm9kZVJlbW92ZUNoYW5nZSQgPSB0b09ic2VydmFibGUodGhpcy5lbnRpdGllc1NlcnZpY2Uubm9kZXMpXG4gICAgLnBpcGUoXG4gICAgICBwYWlyd2lzZSgpLFxuICAgICAgbWFwKChbb2xkTGlzdCwgbmV3TGlzdF0pID0+XG4gICAgICAgIG9sZExpc3QuZmlsdGVyKG5vZGUgPT4gIW5ld0xpc3QuaW5jbHVkZXMobm9kZSkpXG4gICAgICApLFxuICAgICAgZmlsdGVyKChub2RlcykgPT4gISFub2Rlcy5sZW5ndGgpLFxuICAgICAgbWFwKChub2RlcykgPT5cbiAgICAgICAgbm9kZXMubWFwKG5vZGUgPT4gKHsgdHlwZTogJ3JlbW92ZScsIGlkOiBub2RlLm5vZGUuaWQgfSkpXG4gICAgICApXG4gICAgKSBzYXRpc2ZpZXMgT2JzZXJ2YWJsZTxOb2RlQ2hhbmdlW10+XG5cbiAgcHVibGljIHJlYWRvbmx5IGNoYW5nZXMkOiBPYnNlcnZhYmxlPE5vZGVDaGFuZ2VbXT4gPSBtZXJnZShcbiAgICB0aGlzLm5vZGVzUG9zaXRpb25DaGFuZ2UkLFxuICAgIHRoaXMubm9kZUFkZENoYW5nZSQsXG4gICAgdGhpcy5ub2RlUmVtb3ZlQ2hhbmdlJFxuICApLnBpcGUoXG4gICAgLy8gdGhpcyBmaXhlcyBhIGJ1ZyB3aGVuIG9uIGZpcmUgbm9kZSBldmVudCBjaGFuZ2UsXG4gICAgLy8geW91IGNhbid0IGdldCB2YWxpZCBsaXN0IG9mIGRldGFjaGVkIGVkZ2VzXG4gICAgb2JzZXJ2ZU9uKGFzeW5jU2NoZWR1bGVyKSxcbiAgKVxufVxuIl19
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export {};
|
|
2
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRnZS1jaGFuZ2UudHlwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC12Zmxvdy1saWIvc3JjL2xpYi92Zmxvdy90eXBlcy9lZGdlLWNoYW5nZS50eXBlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdHlwZSBFZGdlQ2hhbmdlID0gRWRnZURldGFjaGVkQ2hhbmdlIHwgRWRnZUFkZENoYW5nZSB8IEVkZ2VSZW1vdmVDaGFuZ2VcblxuLyoqXG4gKiBAZXhwZXJpbWVudGFsXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWRnZURldGFjaGVkQ2hhbmdlIGV4dGVuZHMgRWRnZUNoYW5nZVNoYXJlZCB7XG4gIHR5cGU6ICdkZXRhY2hlZCdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFZGdlQWRkQ2hhbmdlIGV4dGVuZHMgRWRnZUNoYW5nZVNoYXJlZCB7XG4gIHR5cGU6ICdhZGQnXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRWRnZVJlbW92ZUNoYW5nZSBleHRlbmRzIEVkZ2VDaGFuZ2VTaGFyZWQge1xuICB0eXBlOiAncmVtb3ZlJ1xufVxuXG5pbnRlcmZhY2UgRWRnZUNoYW5nZVNoYXJlZCB7XG4gIGlkOiBzdHJpbmdcbn1cbiJdfQ==
|
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, computed, EventEmitter, Output, untracked, Injector,
|
|
4
|
+
import { signal, Injectable, inject, ElementRef, Directive, effect, Input, TemplateRef, computed, EventEmitter, Output, untracked, Injector, Component, ChangeDetectionStrategy, ViewChild, HostListener, runInInjectionContext, ContentChild, NgModule } from '@angular/core';
|
|
5
5
|
import { select } from 'd3-selection';
|
|
6
6
|
import { zoomIdentity, zoom } from 'd3-zoom';
|
|
7
7
|
import { drag } from 'd3-drag';
|
|
8
8
|
import { toObservable, takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
9
|
-
import { switchMap, merge, skip, map, pairwise, filter, observeOn, asyncScheduler, tap, fromEvent } from 'rxjs';
|
|
9
|
+
import { switchMap, merge, skip, map, pairwise, filter, observeOn, asyncScheduler, zip, distinctUntilChanged, tap, fromEvent } from 'rxjs';
|
|
10
10
|
import { path } from 'd3-path';
|
|
11
11
|
|
|
12
12
|
class ViewportService {
|
|
@@ -350,6 +350,9 @@ class FlowEntitiesService {
|
|
|
350
350
|
getNode(id) {
|
|
351
351
|
return this.nodes().find(({ node }) => node.id === id);
|
|
352
352
|
}
|
|
353
|
+
getDetachedEdges() {
|
|
354
|
+
return this.edges().filter(e => e.detached());
|
|
355
|
+
}
|
|
353
356
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
354
357
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: FlowEntitiesService }); }
|
|
355
358
|
}
|
|
@@ -412,18 +415,18 @@ class HandleModel {
|
|
|
412
415
|
switch (this.rawHandle.position) {
|
|
413
416
|
case 'left': return {
|
|
414
417
|
x: 0,
|
|
415
|
-
y: this.
|
|
418
|
+
y: this.parentPosition().y + (this.parentSize().height / 2)
|
|
416
419
|
};
|
|
417
420
|
case 'right': return {
|
|
418
421
|
x: this.parentNode.size().width,
|
|
419
|
-
y: this.
|
|
422
|
+
y: this.parentPosition().y + (this.parentSize().height / 2)
|
|
420
423
|
};
|
|
421
424
|
case 'top': return {
|
|
422
|
-
x: this.
|
|
425
|
+
x: this.parentPosition().x + (this.parentSize().width / 2),
|
|
423
426
|
y: 0
|
|
424
427
|
};
|
|
425
428
|
case 'bottom': return {
|
|
426
|
-
x: this.
|
|
429
|
+
x: this.parentPosition().x + this.parentSize().width / 2,
|
|
427
430
|
y: this.parentNode.size().height
|
|
428
431
|
};
|
|
429
432
|
}
|
|
@@ -442,6 +445,8 @@ class HandleModel {
|
|
|
442
445
|
y: this.parentNode.point().y + this.offset().y + this.sizeOffset().y,
|
|
443
446
|
};
|
|
444
447
|
});
|
|
448
|
+
this.parentSize = signal(this.rawHandle.parentSize);
|
|
449
|
+
this.parentPosition = signal(this.rawHandle.parentPosition);
|
|
445
450
|
}
|
|
446
451
|
}
|
|
447
452
|
|
|
@@ -457,20 +462,20 @@ class NodeModel {
|
|
|
457
462
|
this.targetPosition = computed(() => this.flow.handlePositions().target);
|
|
458
463
|
this.handles = computed(() => {
|
|
459
464
|
if (this.node.type === 'html-template') {
|
|
460
|
-
return this.rawHandles()
|
|
465
|
+
return this.rawHandles();
|
|
461
466
|
}
|
|
462
467
|
return [
|
|
463
468
|
new HandleModel({
|
|
464
469
|
position: this.sourcePosition(),
|
|
465
470
|
type: 'source',
|
|
466
|
-
parentPosition:
|
|
467
|
-
parentSize:
|
|
471
|
+
parentPosition: { x: 0, y: 0 },
|
|
472
|
+
parentSize: this.size()
|
|
468
473
|
}, this),
|
|
469
474
|
new HandleModel({
|
|
470
475
|
position: this.targetPosition(),
|
|
471
476
|
type: 'target',
|
|
472
|
-
parentPosition:
|
|
473
|
-
parentSize:
|
|
477
|
+
parentPosition: { x: 0, y: 0 },
|
|
478
|
+
parentSize: this.size()
|
|
474
479
|
}, this),
|
|
475
480
|
];
|
|
476
481
|
});
|
|
@@ -605,6 +610,31 @@ function getPointOnBezier(sourcePoint, targetPoint, controlPoint1, controlPoint2
|
|
|
605
610
|
class EdgeModel {
|
|
606
611
|
constructor(edge) {
|
|
607
612
|
this.edge = edge;
|
|
613
|
+
this.detached = computed(() => {
|
|
614
|
+
if (!this.source || !this.target) {
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
617
|
+
let existsSourceHandle = false;
|
|
618
|
+
let existsTargetHandle = false;
|
|
619
|
+
if (this.edge.sourceHandle) {
|
|
620
|
+
existsSourceHandle = !!this.source.handles()
|
|
621
|
+
.find(handle => handle.rawHandle.id === this.edge.sourceHandle);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
existsSourceHandle = !!this.source.handles()
|
|
625
|
+
.find(handle => handle.rawHandle.type === 'source');
|
|
626
|
+
}
|
|
627
|
+
if (this.edge.targetHandle) {
|
|
628
|
+
existsTargetHandle = !!this.target.handles()
|
|
629
|
+
.find(handle => handle.rawHandle.id === this.edge.targetHandle);
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
existsTargetHandle = !!this.target.handles()
|
|
633
|
+
.find(handle => handle.rawHandle.type === 'target');
|
|
634
|
+
}
|
|
635
|
+
return !existsSourceHandle || !existsTargetHandle;
|
|
636
|
+
});
|
|
637
|
+
this.detached$ = toObservable(this.detached);
|
|
608
638
|
this.path = computed(() => {
|
|
609
639
|
let source;
|
|
610
640
|
if (this.edge.sourceHandle) {
|
|
@@ -702,7 +732,10 @@ class NodesChangeService {
|
|
|
702
732
|
.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 }))));
|
|
703
733
|
this.nodeRemoveChange$ = toObservable(this.entitiesService.nodes)
|
|
704
734
|
.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 }))));
|
|
705
|
-
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$)
|
|
735
|
+
this.changes$ = merge(this.nodesPositionChange$, this.nodeAddChange$, this.nodeRemoveChange$).pipe(
|
|
736
|
+
// this fixes a bug when on fire node event change,
|
|
737
|
+
// you can't get valid list of detached edges
|
|
738
|
+
observeOn(asyncScheduler));
|
|
706
739
|
}
|
|
707
740
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodesChangeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
708
741
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodesChangeService }); }
|
|
@@ -711,16 +744,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
711
744
|
type: Injectable
|
|
712
745
|
}] });
|
|
713
746
|
|
|
747
|
+
const haveSameContents = (a, b) => a.length === b.length &&
|
|
748
|
+
[...new Set([...a, ...b])].every(v => a.filter(e => e === v).length === b.filter(e => e === v).length);
|
|
714
749
|
class EdgeChangesService {
|
|
715
750
|
constructor() {
|
|
716
751
|
this.entitiesService = inject(FlowEntitiesService);
|
|
717
|
-
this.edgeDetachedChange$ = toObservable(computed(() => {
|
|
752
|
+
this.edgeDetachedChange$ = merge(toObservable(computed(() => {
|
|
718
753
|
const nodes = this.entitiesService.nodes();
|
|
719
754
|
const edges = untracked(this.entitiesService.edges);
|
|
720
755
|
return edges.filter(({ source, target }) => !nodes.includes(source) || !nodes.includes(target));
|
|
721
|
-
})).pipe(
|
|
722
|
-
|
|
723
|
-
|
|
756
|
+
})), toObservable(this.entitiesService.edges).pipe(switchMap((edges) => {
|
|
757
|
+
return zip(...edges.map(e => e.detached$.pipe(map(() => e))));
|
|
758
|
+
}), map((edges) => edges.filter(e => e.detached())),
|
|
759
|
+
// TODO check why there are 2 emits
|
|
760
|
+
skip(2))).pipe(
|
|
761
|
+
// here we check if 2 approaches to detect detached edges emits same
|
|
762
|
+
// and same values (this may happen on node delete)
|
|
763
|
+
distinctUntilChanged(haveSameContents), filter(edges => !!edges.length), map((edges) => edges.map(({ edge }) => ({ type: 'detached', id: edge.id }))));
|
|
724
764
|
this.edgeAddChange$ = toObservable(this.entitiesService.edges)
|
|
725
765
|
.pipe(pairwise(), map(([oldList, newList]) => {
|
|
726
766
|
return newList.filter(edge => !oldList.includes(edge));
|
|
@@ -780,13 +820,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
780
820
|
|
|
781
821
|
class HandleService {
|
|
782
822
|
constructor() {
|
|
783
|
-
this.
|
|
823
|
+
this.node = signal(null);
|
|
784
824
|
}
|
|
785
825
|
createHandle(newHandle) {
|
|
786
|
-
this.
|
|
826
|
+
const node = this.node();
|
|
827
|
+
if (node) {
|
|
828
|
+
node.rawHandles.update(handles => [...handles, newHandle]);
|
|
829
|
+
}
|
|
787
830
|
}
|
|
788
831
|
destroyHandle(handleToDestoy) {
|
|
789
|
-
|
|
832
|
+
const node = this.node();
|
|
833
|
+
// TODO: microtask
|
|
834
|
+
if (node) {
|
|
835
|
+
queueMicrotask(() => node.rawHandles.update(handles => handles.filter(handle => handle !== handleToDestoy)));
|
|
836
|
+
}
|
|
790
837
|
}
|
|
791
838
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
792
839
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleService }); }
|
|
@@ -809,9 +856,7 @@ class NodeComponent {
|
|
|
809
856
|
this.targetHandleState = signal('idle');
|
|
810
857
|
}
|
|
811
858
|
ngOnInit() {
|
|
812
|
-
|
|
813
|
-
effect(() => this.nodeModel.rawHandles.set(this.handleService.handles()), { allowSignalWrites: true });
|
|
814
|
-
});
|
|
859
|
+
this.handleService.node.set(this.nodeModel);
|
|
815
860
|
this.draggableService.toggleDraggable(this.hostRef.nativeElement, this.nodeModel);
|
|
816
861
|
}
|
|
817
862
|
ngAfterViewInit() {
|
|
@@ -1277,7 +1322,7 @@ class VflowComponent {
|
|
|
1277
1322
|
* Edges to render
|
|
1278
1323
|
*/
|
|
1279
1324
|
set edges(newEdges) {
|
|
1280
|
-
const newModels = ReferenceKeeper.edges(newEdges, this.flowEntitiesService.edges());
|
|
1325
|
+
const newModels = runInInjectionContext(this.injector, () => ReferenceKeeper.edges(newEdges, this.flowEntitiesService.edges()));
|
|
1281
1326
|
// quick and dirty binding nodes to edges
|
|
1282
1327
|
addNodesToEdges(this.nodeModels, newModels);
|
|
1283
1328
|
this.flowEntitiesService.edges.set(newModels);
|
|
@@ -1316,6 +1361,12 @@ class VflowComponent {
|
|
|
1316
1361
|
getNode(id) {
|
|
1317
1362
|
return this.flowEntitiesService.getNode(id)?.node;
|
|
1318
1363
|
}
|
|
1364
|
+
/**
|
|
1365
|
+
* Sync method to get detached edges
|
|
1366
|
+
*/
|
|
1367
|
+
getDetachedEdges() {
|
|
1368
|
+
return this.flowEntitiesService.getDetachedEdges().map(e => e.edge);
|
|
1369
|
+
}
|
|
1319
1370
|
// #endregion
|
|
1320
1371
|
trackNodes(idx, { node }) {
|
|
1321
1372
|
return node.id;
|
|
@@ -1391,27 +1442,27 @@ class HandleComponent {
|
|
|
1391
1442
|
}
|
|
1392
1443
|
ngOnInit() {
|
|
1393
1444
|
queueMicrotask(() => {
|
|
1394
|
-
const
|
|
1395
|
-
this.
|
|
1445
|
+
const { width, height, x, y } = this.parentRect();
|
|
1446
|
+
this.model = new HandleModel({
|
|
1396
1447
|
position: this.position,
|
|
1397
1448
|
type: this.type,
|
|
1398
1449
|
id: this.id,
|
|
1399
|
-
parentPosition:
|
|
1400
|
-
parentSize:
|
|
1401
|
-
});
|
|
1450
|
+
parentPosition: { x, y },
|
|
1451
|
+
parentSize: { width, height }
|
|
1452
|
+
}, this.handleService.node());
|
|
1453
|
+
this.handleService.createHandle(this.model);
|
|
1402
1454
|
});
|
|
1403
1455
|
}
|
|
1456
|
+
ngOnDestroy() {
|
|
1457
|
+
this.handleService.destroyHandle(this.model);
|
|
1458
|
+
}
|
|
1404
1459
|
parentRect() {
|
|
1405
|
-
// we assume there is only one foreignObject that wraps node
|
|
1406
|
-
const fo = this.element.closest('foreignObject');
|
|
1407
1460
|
const parent = this.element.parentElement;
|
|
1408
|
-
const foRect = fo.getBoundingClientRect();
|
|
1409
|
-
const parentRect = parent.getBoundingClientRect();
|
|
1410
1461
|
return {
|
|
1411
|
-
x:
|
|
1412
|
-
y:
|
|
1413
|
-
width:
|
|
1414
|
-
height:
|
|
1462
|
+
x: parent.offsetLeft,
|
|
1463
|
+
y: parent.offsetTop,
|
|
1464
|
+
width: parent.clientWidth,
|
|
1465
|
+
height: parent.clientHeight
|
|
1415
1466
|
};
|
|
1416
1467
|
}
|
|
1417
1468
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: HandleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|