ngx-vflow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +24 -0
  2. package/esm2022/lib/vflow/components/connection/connection.component.mjs +100 -0
  3. package/esm2022/lib/vflow/components/defs/defs.component.mjs +19 -0
  4. package/esm2022/lib/vflow/components/edge/edge.component.mjs +42 -0
  5. package/esm2022/lib/vflow/components/edge-label/edge-label.component.mjs +58 -0
  6. package/esm2022/lib/vflow/components/node/node.component.mjs +146 -0
  7. package/esm2022/lib/vflow/components/vflow/vflow.component.mjs +183 -0
  8. package/esm2022/lib/vflow/directives/changes-controller.directive.mjs +34 -0
  9. package/esm2022/lib/vflow/directives/connection-controller.directive.mjs +36 -0
  10. package/esm2022/lib/vflow/directives/map-context.directive.mjs +62 -0
  11. package/esm2022/lib/vflow/directives/reference.directive.mjs +16 -0
  12. package/esm2022/lib/vflow/directives/root-svg-context.directive.mjs +26 -0
  13. package/esm2022/lib/vflow/directives/space-point-context.directive.mjs +29 -0
  14. package/esm2022/lib/vflow/directives/template.directive.mjs +58 -0
  15. package/esm2022/lib/vflow/interfaces/connection-settings.interface.mjs +2 -0
  16. package/esm2022/lib/vflow/interfaces/connection.interface.mjs +2 -0
  17. package/esm2022/lib/vflow/interfaces/edge-label.interface.mjs +2 -0
  18. package/esm2022/lib/vflow/interfaces/edge.interface.mjs +2 -0
  19. package/esm2022/lib/vflow/interfaces/handle-positions.interface.mjs +2 -0
  20. package/esm2022/lib/vflow/interfaces/marker.interface.mjs +2 -0
  21. package/esm2022/lib/vflow/interfaces/node.interface.mjs +2 -0
  22. package/esm2022/lib/vflow/interfaces/path-data.interface.mjs +2 -0
  23. package/esm2022/lib/vflow/interfaces/point.interface.mjs +2 -0
  24. package/esm2022/lib/vflow/interfaces/template-context.interface.mjs +2 -0
  25. package/esm2022/lib/vflow/interfaces/viewport.interface.mjs +2 -0
  26. package/esm2022/lib/vflow/math/edge-path/bezier-path.mjs +77 -0
  27. package/esm2022/lib/vflow/math/edge-path/straigh-path.mjs +18 -0
  28. package/esm2022/lib/vflow/math/point-on-line-by-ratio.mjs +12 -0
  29. package/esm2022/lib/vflow/models/connection.model.mjs +9 -0
  30. package/esm2022/lib/vflow/models/edge-label.model.mjs +8 -0
  31. package/esm2022/lib/vflow/models/edge.model.mjs +30 -0
  32. package/esm2022/lib/vflow/models/flow.model.mjs +16 -0
  33. package/esm2022/lib/vflow/models/node.model.mjs +90 -0
  34. package/esm2022/lib/vflow/services/draggable.service.mjs +66 -0
  35. package/esm2022/lib/vflow/services/edge-changes.service.mjs +38 -0
  36. package/esm2022/lib/vflow/services/flow-entities.service.mjs +49 -0
  37. package/esm2022/lib/vflow/services/flow-status.service.mjs +39 -0
  38. package/esm2022/lib/vflow/services/node-changes.service.mjs +32 -0
  39. package/esm2022/lib/vflow/services/viewport.service.mjs +32 -0
  40. package/esm2022/lib/vflow/types/edge-change.type.mjs +2 -0
  41. package/esm2022/lib/vflow/types/node-change.type.mjs +2 -0
  42. package/esm2022/lib/vflow/types/position.type.mjs +2 -0
  43. package/esm2022/lib/vflow/types/using-points.type.mjs +2 -0
  44. package/esm2022/lib/vflow/types/viewport-change-type.type.mjs +2 -0
  45. package/esm2022/lib/vflow/utils/add-nodes-to-edges.mjs +11 -0
  46. package/esm2022/lib/vflow/utils/hash.mjs +7 -0
  47. package/esm2022/lib/vflow/utils/is-defined.mjs +4 -0
  48. package/esm2022/lib/vflow/utils/reference-keeper.mjs +31 -0
  49. package/esm2022/lib/vflow/utils/round.mjs +2 -0
  50. package/esm2022/lib/vflow/vflow.module.mjs +68 -0
  51. package/esm2022/ngx-vflow.mjs +5 -0
  52. package/esm2022/public-api.mjs +23 -0
  53. package/fesm2022/ngx-vflow.mjs +1332 -0
  54. package/fesm2022/ngx-vflow.mjs.map +1 -0
  55. package/index.d.ts +5 -0
  56. package/lib/vflow/components/connection/connection.component.d.ts +20 -0
  57. package/lib/vflow/components/defs/defs.component.d.ts +8 -0
  58. package/lib/vflow/components/edge/edge.component.d.ts +16 -0
  59. package/lib/vflow/components/edge-label/edge-label.component.d.ts +31 -0
  60. package/lib/vflow/components/node/node.component.d.ts +53 -0
  61. package/lib/vflow/components/vflow/vflow.component.d.ts +73 -0
  62. package/lib/vflow/directives/changes-controller.directive.d.ts +16 -0
  63. package/lib/vflow/directives/connection-controller.directive.d.ts +11 -0
  64. package/lib/vflow/directives/map-context.directive.d.ts +19 -0
  65. package/lib/vflow/directives/reference.directive.d.ts +6 -0
  66. package/lib/vflow/directives/root-svg-context.directive.d.ts +7 -0
  67. package/lib/vflow/directives/space-point-context.directive.d.ts +14 -0
  68. package/lib/vflow/directives/template.directive.d.ts +28 -0
  69. package/lib/vflow/interfaces/connection-settings.interface.d.ts +10 -0
  70. package/lib/vflow/interfaces/connection.interface.d.ts +4 -0
  71. package/lib/vflow/interfaces/edge-label.interface.d.ts +6 -0
  72. package/lib/vflow/interfaces/edge.interface.d.ts +18 -0
  73. package/lib/vflow/interfaces/handle-positions.interface.d.ts +5 -0
  74. package/lib/vflow/interfaces/marker.interface.d.ts +9 -0
  75. package/lib/vflow/interfaces/node.interface.d.ts +16 -0
  76. package/lib/vflow/interfaces/path-data.interface.d.ts +8 -0
  77. package/lib/vflow/interfaces/point.interface.d.ts +4 -0
  78. package/lib/vflow/interfaces/template-context.interface.d.ts +10 -0
  79. package/lib/vflow/interfaces/viewport.interface.d.ts +9 -0
  80. package/lib/vflow/math/edge-path/bezier-path.d.ts +5 -0
  81. package/lib/vflow/math/edge-path/straigh-path.d.ts +4 -0
  82. package/lib/vflow/math/point-on-line-by-ratio.d.ts +7 -0
  83. package/lib/vflow/models/connection.model.d.ts +9 -0
  84. package/lib/vflow/models/edge-label.model.d.ts +9 -0
  85. package/lib/vflow/models/edge.model.d.ts +17 -0
  86. package/lib/vflow/models/flow.model.d.ts +14 -0
  87. package/lib/vflow/models/node.model.d.ts +70 -0
  88. package/lib/vflow/services/draggable.service.d.ts +32 -0
  89. package/lib/vflow/services/edge-changes.service.d.ts +22 -0
  90. package/lib/vflow/services/flow-entities.service.d.ts +15 -0
  91. package/lib/vflow/services/flow-status.service.d.ts +43 -0
  92. package/lib/vflow/services/node-changes.service.d.ts +26 -0
  93. package/lib/vflow/services/viewport.service.d.ts +24 -0
  94. package/lib/vflow/types/edge-change.type.d.ts +14 -0
  95. package/lib/vflow/types/node-change.type.d.ts +16 -0
  96. package/lib/vflow/types/position.type.d.ts +1 -0
  97. package/lib/vflow/types/using-points.type.d.ts +5 -0
  98. package/lib/vflow/types/viewport-change-type.type.d.ts +3 -0
  99. package/lib/vflow/utils/add-nodes-to-edges.d.ts +3 -0
  100. package/lib/vflow/utils/hash.d.ts +1 -0
  101. package/lib/vflow/utils/is-defined.d.ts +1 -0
  102. package/lib/vflow/utils/reference-keeper.d.ts +14 -0
  103. package/lib/vflow/utils/round.d.ts +1 -0
  104. package/lib/vflow/vflow.module.d.ts +18 -0
  105. package/package.json +25 -0
  106. package/public-api.d.ts +18 -0
package/README.md ADDED
@@ -0,0 +1,24 @@
1
+ # ngx-vflow
2
+
3
+ This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Run `ng generate component component-name --project ngx-vflow-lib` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project ngx-vflow-lib`.
8
+ > Note: Don't forget to add `--project ngx-vflow-lib` or else it will be added to the default project in your `angular.json` file.
9
+
10
+ ## Build
11
+
12
+ Run `ng build ngx-vflow-lib` to build the project. The build artifacts will be stored in the `dist/` directory.
13
+
14
+ ## Publishing
15
+
16
+ After building your library with `ng build ngx-vflow-lib`, go to the dist folder `cd dist/ngx-vflow-lib` and run `npm publish`.
17
+
18
+ ## Running unit tests
19
+
20
+ Run `ng test ngx-vflow-lib` to execute the unit tests via [Karma](https://karma-runner.github.io).
21
+
22
+ ## Further help
23
+
24
+ To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
@@ -0,0 +1,100 @@
1
+ import { ChangeDetectionStrategy, Component, Input, computed, inject } from '@angular/core';
2
+ import { FlowStatusService } from '../../services/flow-status.service';
3
+ import { straightPath } from '../../math/edge-path/straigh-path';
4
+ import { SpacePointContextDirective } from '../../directives/space-point-context.directive';
5
+ import { bezierPath } from '../../math/edge-path/bezier-path';
6
+ import { hashCode } from '../../utils/hash';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ export class ConnectionComponent {
10
+ constructor() {
11
+ this.flowStatusService = inject(FlowStatusService);
12
+ this.spacePointContext = inject(SpacePointContextDirective);
13
+ this.path = computed(() => {
14
+ const status = this.flowStatusService.status();
15
+ if (status.state === 'connection-start') {
16
+ const sourceNode = status.payload.sourceNode;
17
+ const sourcePoint = sourceNode.sourcePointAbsolute();
18
+ const targetPoint = this.spacePointContext.svgCurrentSpacePoint();
19
+ switch (this.model.curve) {
20
+ case 'straight': return straightPath(sourcePoint, targetPoint).path;
21
+ case 'bezier': return bezierPath(sourcePoint, targetPoint, sourceNode.sourcePosition(), sourceNode.targetPosition()).path;
22
+ }
23
+ }
24
+ if (status.state === 'connection-validation') {
25
+ const sourcePoint = status.payload.sourceNode.sourcePointAbsolute();
26
+ // ignore magnet if validation failed
27
+ const targetPoint = status.payload.valid
28
+ ? status.payload.targetNode.targetPointAbsolute()
29
+ : this.spacePointContext.svgCurrentSpacePoint();
30
+ switch (this.model.curve) {
31
+ case 'straight': return straightPath(sourcePoint, targetPoint).path;
32
+ case 'bezier': return bezierPath(sourcePoint, targetPoint, status.payload.sourceNode.sourcePosition(), status.payload.sourceNode.targetPosition()).path;
33
+ }
34
+ }
35
+ return null;
36
+ });
37
+ this.markerUrl = computed(() => {
38
+ const marker = this.model.connection.marker;
39
+ if (marker) {
40
+ return `url(#${hashCode(JSON.stringify(marker))})`;
41
+ }
42
+ return '';
43
+ });
44
+ this.defaultColor = 'rgb(177, 177, 183)';
45
+ }
46
+ getContext() {
47
+ return {
48
+ $implicit: {
49
+ path: this.path,
50
+ marker: this.markerUrl
51
+ }
52
+ };
53
+ }
54
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConnectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
55
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ConnectionComponent, selector: "g[connection]", inputs: { model: "model", template: "template" }, ngImport: i0, template: `
56
+ <ng-container *ngIf="model.type === 'default'">
57
+ <svg:path
58
+ *ngIf="path() as path"
59
+ [attr.d]="path"
60
+ [attr.marker-end]="markerUrl()"
61
+ [attr.stroke]="defaultColor"
62
+ fill="none"
63
+ stroke-width="2"
64
+ />
65
+ </ng-container>
66
+
67
+ <ng-container *ngIf="model.type === 'template' && template">
68
+ <ng-container *ngTemplateOutlet="template; context: getContext()" />
69
+ </ng-container>
70
+ `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
71
+ }
72
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ConnectionComponent, decorators: [{
73
+ type: Component,
74
+ args: [{
75
+ selector: 'g[connection]',
76
+ template: `
77
+ <ng-container *ngIf="model.type === 'default'">
78
+ <svg:path
79
+ *ngIf="path() as path"
80
+ [attr.d]="path"
81
+ [attr.marker-end]="markerUrl()"
82
+ [attr.stroke]="defaultColor"
83
+ fill="none"
84
+ stroke-width="2"
85
+ />
86
+ </ng-container>
87
+
88
+ <ng-container *ngIf="model.type === 'template' && template">
89
+ <ng-container *ngTemplateOutlet="template; context: getContext()" />
90
+ </ng-container>
91
+ `,
92
+ changeDetection: ChangeDetectionStrategy.OnPush
93
+ }]
94
+ }], propDecorators: { model: [{
95
+ type: Input,
96
+ args: [{ required: true }]
97
+ }], template: [{
98
+ type: Input
99
+ }] } });
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvY29tcG9uZW50cy9jb25uZWN0aW9uL2Nvbm5lY3Rpb24uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFlLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekcsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDdkUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGdEQUFnRCxDQUFDO0FBRTVGLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUM5RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7OztBQXNCNUMsTUFBTSxPQUFPLG1CQUFtQjtJQXBCaEM7UUEyQlUsc0JBQWlCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDN0Msc0JBQWlCLEdBQUcsTUFBTSxDQUFDLDBCQUEwQixDQUFDLENBQUE7UUFFcEQsU0FBSSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFBO1lBRTlDLElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxrQkFBa0IsRUFBRTtnQkFDdkMsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUE7Z0JBQzVDLE1BQU0sV0FBVyxHQUFHLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO2dCQUNwRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsb0JBQW9CLEVBQUUsQ0FBQTtnQkFFakUsUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRTtvQkFDeEIsS0FBSyxVQUFVLENBQUMsQ0FBQyxPQUFPLFlBQVksQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFBO29CQUNuRSxLQUFLLFFBQVEsQ0FBQyxDQUFDLE9BQU8sVUFBVSxDQUM5QixXQUFXLEVBQUUsV0FBVyxFQUN4QixVQUFVLENBQUMsY0FBYyxFQUFFLEVBQUUsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUN6RCxDQUFDLElBQUksQ0FBQTtpQkFDUDthQUNGO1lBRUQsSUFBSSxNQUFNLENBQUMsS0FBSyxLQUFLLHVCQUF1QixFQUFFO2dCQUM1QyxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxtQkFBbUIsRUFBRSxDQUFBO2dCQUNuRSxxQ0FBcUM7Z0JBQ3JDLE1BQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSztvQkFDdEMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLG1CQUFtQixFQUFFO29CQUNqRCxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG9CQUFvQixFQUFFLENBQUE7Z0JBRWpELFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUU7b0JBQ3hCLEtBQUssVUFBVSxDQUFDLENBQUMsT0FBTyxZQUFZLENBQUMsV0FBVyxFQUFFLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQTtvQkFDbkUsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLFVBQVUsQ0FDOUIsV0FBVyxFQUFFLFdBQVcsRUFDeEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsY0FBYyxFQUFFLEVBQzFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUMzQyxDQUFDLElBQUksQ0FBQTtpQkFDUDthQUNGO1lBRUQsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDLENBQUMsQ0FBQTtRQUVRLGNBQVMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ2xDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQTtZQUUzQyxJQUFJLE1BQU0sRUFBRTtnQkFDVixPQUFPLFFBQVEsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFBO2FBQ25EO1lBRUQsT0FBTyxFQUFFLENBQUE7UUFDWCxDQUFDLENBQUMsQ0FBQTtRQUVpQixpQkFBWSxHQUFHLG9CQUFvQixDQUFBO0tBVXZEO0lBUlcsVUFBVTtRQUNsQixPQUFPO1lBQ0wsU0FBUyxFQUFFO2dCQUNULElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtnQkFDZixNQUFNLEVBQUUsSUFBSSxDQUFDLFNBQVM7YUFDdkI7U0FDRixDQUFBO0lBQ0gsQ0FBQzsrR0FsRVUsbUJBQW1CO21HQUFuQixtQkFBbUIsdUdBbEJwQjs7Ozs7Ozs7Ozs7Ozs7O0dBZVQ7OzRGQUdVLG1CQUFtQjtrQkFwQi9CLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGVBQWU7b0JBQ3pCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7O0dBZVQ7b0JBQ0QsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07aUJBQ2hEOzhCQUdRLEtBQUs7c0JBRFgsS0FBSzt1QkFBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUU7Z0JBSWxCLFFBQVE7c0JBRGQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIElucHV0LCBUZW1wbGF0ZVJlZiwgY29tcHV0ZWQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRmxvd1N0YXR1c1NlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9mbG93LXN0YXR1cy5zZXJ2aWNlJztcbmltcG9ydCB7IHN0cmFpZ2h0UGF0aCB9IGZyb20gJy4uLy4uL21hdGgvZWRnZS1wYXRoL3N0cmFpZ2gtcGF0aCc7XG5pbXBvcnQgeyBTcGFjZVBvaW50Q29udGV4dERpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvc3BhY2UtcG9pbnQtY29udGV4dC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgQ29ubmVjdGlvbk1vZGVsIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2Nvbm5lY3Rpb24ubW9kZWwnO1xuaW1wb3J0IHsgYmV6aWVyUGF0aCB9IGZyb20gJy4uLy4uL21hdGgvZWRnZS1wYXRoL2Jlemllci1wYXRoJztcbmltcG9ydCB7IGhhc2hDb2RlIH0gZnJvbSAnLi4vLi4vdXRpbHMvaGFzaCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dbY29ubmVjdGlvbl0nLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtb2RlbC50eXBlID09PSAnZGVmYXVsdCdcIj5cbiAgICAgIDxzdmc6cGF0aFxuICAgICAgICAqbmdJZj1cInBhdGgoKSBhcyBwYXRoXCJcbiAgICAgICAgW2F0dHIuZF09XCJwYXRoXCJcbiAgICAgICAgW2F0dHIubWFya2VyLWVuZF09XCJtYXJrZXJVcmwoKVwiXG4gICAgICAgIFthdHRyLnN0cm9rZV09XCJkZWZhdWx0Q29sb3JcIlxuICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjJcIlxuICAgICAgLz5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtb2RlbC50eXBlID09PSAndGVtcGxhdGUnICYmIHRlbXBsYXRlXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGVtcGxhdGU7IGNvbnRleHQ6IGdldENvbnRleHQoKVwiIC8+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIGAsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIENvbm5lY3Rpb25Db21wb25lbnQge1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxuICBwdWJsaWMgbW9kZWwhOiBDb25uZWN0aW9uTW9kZWxcblxuICBASW5wdXQoKVxuICBwdWJsaWMgdGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxhbnk+XG5cbiAgcHJpdmF0ZSBmbG93U3RhdHVzU2VydmljZSA9IGluamVjdChGbG93U3RhdHVzU2VydmljZSlcbiAgcHJpdmF0ZSBzcGFjZVBvaW50Q29udGV4dCA9IGluamVjdChTcGFjZVBvaW50Q29udGV4dERpcmVjdGl2ZSlcblxuICBwcm90ZWN0ZWQgcGF0aCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBzdGF0dXMgPSB0aGlzLmZsb3dTdGF0dXNTZXJ2aWNlLnN0YXR1cygpXG5cbiAgICBpZiAoc3RhdHVzLnN0YXRlID09PSAnY29ubmVjdGlvbi1zdGFydCcpIHtcbiAgICAgIGNvbnN0IHNvdXJjZU5vZGUgPSBzdGF0dXMucGF5bG9hZC5zb3VyY2VOb2RlXG4gICAgICBjb25zdCBzb3VyY2VQb2ludCA9IHNvdXJjZU5vZGUuc291cmNlUG9pbnRBYnNvbHV0ZSgpXG4gICAgICBjb25zdCB0YXJnZXRQb2ludCA9IHRoaXMuc3BhY2VQb2ludENvbnRleHQuc3ZnQ3VycmVudFNwYWNlUG9pbnQoKVxuXG4gICAgICBzd2l0Y2ggKHRoaXMubW9kZWwuY3VydmUpIHtcbiAgICAgICAgY2FzZSAnc3RyYWlnaHQnOiByZXR1cm4gc3RyYWlnaHRQYXRoKHNvdXJjZVBvaW50LCB0YXJnZXRQb2ludCkucGF0aFxuICAgICAgICBjYXNlICdiZXppZXInOiByZXR1cm4gYmV6aWVyUGF0aChcbiAgICAgICAgICBzb3VyY2VQb2ludCwgdGFyZ2V0UG9pbnQsXG4gICAgICAgICAgc291cmNlTm9kZS5zb3VyY2VQb3NpdGlvbigpLCBzb3VyY2VOb2RlLnRhcmdldFBvc2l0aW9uKClcbiAgICAgICAgKS5wYXRoXG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN0YXR1cy5zdGF0ZSA9PT0gJ2Nvbm5lY3Rpb24tdmFsaWRhdGlvbicpIHtcbiAgICAgIGNvbnN0IHNvdXJjZVBvaW50ID0gc3RhdHVzLnBheWxvYWQuc291cmNlTm9kZS5zb3VyY2VQb2ludEFic29sdXRlKClcbiAgICAgIC8vIGlnbm9yZSBtYWduZXQgaWYgdmFsaWRhdGlvbiBmYWlsZWRcbiAgICAgIGNvbnN0IHRhcmdldFBvaW50ID0gc3RhdHVzLnBheWxvYWQudmFsaWRcbiAgICAgICAgPyBzdGF0dXMucGF5bG9hZC50YXJnZXROb2RlLnRhcmdldFBvaW50QWJzb2x1dGUoKVxuICAgICAgICA6IHRoaXMuc3BhY2VQb2ludENvbnRleHQuc3ZnQ3VycmVudFNwYWNlUG9pbnQoKVxuXG4gICAgICBzd2l0Y2ggKHRoaXMubW9kZWwuY3VydmUpIHtcbiAgICAgICAgY2FzZSAnc3RyYWlnaHQnOiByZXR1cm4gc3RyYWlnaHRQYXRoKHNvdXJjZVBvaW50LCB0YXJnZXRQb2ludCkucGF0aFxuICAgICAgICBjYXNlICdiZXppZXInOiByZXR1cm4gYmV6aWVyUGF0aChcbiAgICAgICAgICBzb3VyY2VQb2ludCwgdGFyZ2V0UG9pbnQsXG4gICAgICAgICAgc3RhdHVzLnBheWxvYWQuc291cmNlTm9kZS5zb3VyY2VQb3NpdGlvbigpLFxuICAgICAgICAgIHN0YXR1cy5wYXlsb2FkLnNvdXJjZU5vZGUudGFyZ2V0UG9zaXRpb24oKVxuICAgICAgICApLnBhdGhcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbFxuICB9KVxuXG4gIHByb3RlY3RlZCBtYXJrZXJVcmwgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgbWFya2VyID0gdGhpcy5tb2RlbC5jb25uZWN0aW9uLm1hcmtlclxuXG4gICAgaWYgKG1hcmtlcikge1xuICAgICAgcmV0dXJuIGB1cmwoIyR7aGFzaENvZGUoSlNPTi5zdHJpbmdpZnkobWFya2VyKSl9KWBcbiAgICB9XG5cbiAgICByZXR1cm4gJydcbiAgfSlcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVmYXVsdENvbG9yID0gJ3JnYigxNzcsIDE3NywgMTgzKSdcblxuICBwcm90ZWN0ZWQgZ2V0Q29udGV4dCgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgJGltcGxpY2l0OiB7XG4gICAgICAgIHBhdGg6IHRoaXMucGF0aCxcbiAgICAgICAgbWFya2VyOiB0aGlzLm1hcmtlclVybFxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,19 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "@angular/common";
4
+ export class DefsComponent {
5
+ constructor() {
6
+ this.markers = new Map();
7
+ this.defaultColor = 'rgb(177, 177, 183)';
8
+ }
9
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DefsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DefsComponent, selector: "defs[flowDefs]", inputs: { markers: "markers" }, ngImport: i0, template: "<svg:marker\n *ngFor=\"let marker of markers | keyvalue\"\n [attr.id]=\"marker.key\"\n [attr.markerWidth]=\"marker.value.width ?? 16.5\"\n [attr.markerHeight]=\"marker.value.height ?? 16.5\"\n [attr.orient]=\"marker.value.orient ?? 'auto-start-reverse'\"\n viewBox=\"-10 -10 20 20\"\n [attr.markerUnits]=\"marker.value.markerUnits ?? 'userSpaceOnUse'\"\n refX=\"0\"\n refY=\"0\"\n>\n <polyline\n *ngIf=\"marker.value.type === 'arrow-closed' || !marker.value.type\"\n class=\"marker__arrow_closed\"\n [style.stroke]=\"marker.value.color ?? defaultColor\"\n [style.stroke-width]=\"marker.value.strokeWidth ?? 2\"\n [style.fill]=\"marker.value.color ?? defaultColor\"\n points=\"-5,-4 1,0 -5,4 -5,-4\"\n />\n\n <polyline\n *ngIf=\"marker.value.type === 'arrow'\"\n class=\"marker__arrow_default\"\n [style.stroke]=\"marker.value.color ?? defaultColor\"\n [style.stroke-width]=\"marker.value.strokeWidth ?? 2\"\n points=\"-5,-4 0,0 -5,4\"\n />\n</svg:marker>\n", styles: [".marker__arrow_default{stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;fill:none}.marker__arrow_closed{stroke-linecap:round;stroke-linejoin:round}\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: "pipe", type: i1.KeyValuePipe, name: "keyvalue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
11
+ }
12
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DefsComponent, decorators: [{
13
+ type: Component,
14
+ args: [{ selector: 'defs[flowDefs]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:marker\n *ngFor=\"let marker of markers | keyvalue\"\n [attr.id]=\"marker.key\"\n [attr.markerWidth]=\"marker.value.width ?? 16.5\"\n [attr.markerHeight]=\"marker.value.height ?? 16.5\"\n [attr.orient]=\"marker.value.orient ?? 'auto-start-reverse'\"\n viewBox=\"-10 -10 20 20\"\n [attr.markerUnits]=\"marker.value.markerUnits ?? 'userSpaceOnUse'\"\n refX=\"0\"\n refY=\"0\"\n>\n <polyline\n *ngIf=\"marker.value.type === 'arrow-closed' || !marker.value.type\"\n class=\"marker__arrow_closed\"\n [style.stroke]=\"marker.value.color ?? defaultColor\"\n [style.stroke-width]=\"marker.value.strokeWidth ?? 2\"\n [style.fill]=\"marker.value.color ?? defaultColor\"\n points=\"-5,-4 1,0 -5,4 -5,-4\"\n />\n\n <polyline\n *ngIf=\"marker.value.type === 'arrow'\"\n class=\"marker__arrow_default\"\n [style.stroke]=\"marker.value.color ?? defaultColor\"\n [style.stroke-width]=\"marker.value.strokeWidth ?? 2\"\n points=\"-5,-4 0,0 -5,4\"\n />\n</svg:marker>\n", styles: [".marker__arrow_default{stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;fill:none}.marker__arrow_closed{stroke-linecap:round;stroke-linejoin:round}\n"] }]
15
+ }], propDecorators: { markers: [{
16
+ type: Input,
17
+ args: [{ required: true }]
18
+ }] } });
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvY29tcG9uZW50cy9kZWZzL2RlZnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXZmbG93LWxpYi9zcmMvbGliL3ZmbG93L2NvbXBvbmVudHMvZGVmcy9kZWZzLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDOzs7QUFTMUUsTUFBTSxPQUFPLGFBQWE7SUFOMUI7UUFRUyxZQUFPLEdBQXdCLElBQUksR0FBRyxFQUFFLENBQUE7UUFFNUIsaUJBQVksR0FBRyxvQkFBb0IsQ0FBQTtLQUN2RDsrR0FMWSxhQUFhO21HQUFiLGFBQWEsc0ZDVDFCLDQrQkE0QkE7OzRGRG5CYSxhQUFhO2tCQU56QixTQUFTOytCQUNFLGdCQUFnQixtQkFHVCx1QkFBdUIsQ0FBQyxNQUFNOzhCQUl4QyxPQUFPO3NCQURiLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE1hcmtlciB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvbWFya2VyLmludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RlZnNbZmxvd0RlZnNdJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2RlZnMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9kZWZzLmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIERlZnNDb21wb25lbnQge1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KVxuICBwdWJsaWMgbWFya2VyczogTWFwPG51bWJlciwgTWFya2VyPiA9IG5ldyBNYXAoKVxuXG4gIHByb3RlY3RlZCByZWFkb25seSBkZWZhdWx0Q29sb3IgPSAncmdiKDE3NywgMTc3LCAxODMpJ1xufVxuIiwiPHN2ZzptYXJrZXJcbiAgKm5nRm9yPVwibGV0IG1hcmtlciBvZiBtYXJrZXJzIHwga2V5dmFsdWVcIlxuICBbYXR0ci5pZF09XCJtYXJrZXIua2V5XCJcbiAgW2F0dHIubWFya2VyV2lkdGhdPVwibWFya2VyLnZhbHVlLndpZHRoID8/IDE2LjVcIlxuICBbYXR0ci5tYXJrZXJIZWlnaHRdPVwibWFya2VyLnZhbHVlLmhlaWdodCA/PyAxNi41XCJcbiAgW2F0dHIub3JpZW50XT1cIm1hcmtlci52YWx1ZS5vcmllbnQgPz8gJ2F1dG8tc3RhcnQtcmV2ZXJzZSdcIlxuICB2aWV3Qm94PVwiLTEwIC0xMCAyMCAyMFwiXG4gIFthdHRyLm1hcmtlclVuaXRzXT1cIm1hcmtlci52YWx1ZS5tYXJrZXJVbml0cyA/PyAndXNlclNwYWNlT25Vc2UnXCJcbiAgcmVmWD1cIjBcIlxuICByZWZZPVwiMFwiXG4+XG4gIDxwb2x5bGluZVxuICAgICpuZ0lmPVwibWFya2VyLnZhbHVlLnR5cGUgPT09ICdhcnJvdy1jbG9zZWQnIHx8ICFtYXJrZXIudmFsdWUudHlwZVwiXG4gICAgY2xhc3M9XCJtYXJrZXJfX2Fycm93X2Nsb3NlZFwiXG4gICAgW3N0eWxlLnN0cm9rZV09XCJtYXJrZXIudmFsdWUuY29sb3IgPz8gZGVmYXVsdENvbG9yXCJcbiAgICBbc3R5bGUuc3Ryb2tlLXdpZHRoXT1cIm1hcmtlci52YWx1ZS5zdHJva2VXaWR0aCA/PyAyXCJcbiAgICBbc3R5bGUuZmlsbF09XCJtYXJrZXIudmFsdWUuY29sb3IgPz8gZGVmYXVsdENvbG9yXCJcbiAgICBwb2ludHM9XCItNSwtNCAxLDAgLTUsNCAtNSwtNFwiXG4gIC8+XG5cbiAgPHBvbHlsaW5lXG4gICAgKm5nSWY9XCJtYXJrZXIudmFsdWUudHlwZSA9PT0gJ2Fycm93J1wiXG4gICAgY2xhc3M9XCJtYXJrZXJfX2Fycm93X2RlZmF1bHRcIlxuICAgIFtzdHlsZS5zdHJva2VdPVwibWFya2VyLnZhbHVlLmNvbG9yID8/IGRlZmF1bHRDb2xvclwiXG4gICAgW3N0eWxlLnN0cm9rZS13aWR0aF09XCJtYXJrZXIudmFsdWUuc3Ryb2tlV2lkdGggPz8gMlwiXG4gICAgcG9pbnRzPVwiLTUsLTQgMCwwIC01LDRcIlxuICAvPlxuPC9zdmc6bWFya2VyPlxuIl19
@@ -0,0 +1,42 @@
1
+ import { ChangeDetectionStrategy, Component, Input, computed } from '@angular/core';
2
+ import { hashCode } from '../../utils/hash';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ import * as i2 from "../edge-label/edge-label.component";
6
+ export class EdgeComponent {
7
+ constructor() {
8
+ this.markerStartUrl = computed(() => {
9
+ const marker = this.model.edge.markers?.start;
10
+ return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
11
+ });
12
+ this.markerEndUrl = computed(() => {
13
+ const marker = this.model.edge.markers?.end;
14
+ return marker ? `url(#${hashCode(JSON.stringify(marker))})` : '';
15
+ });
16
+ this.defaultColor = 'rgb(177, 177, 183)';
17
+ }
18
+ ngOnInit() {
19
+ this.edgeContext = {
20
+ $implicit: {
21
+ // TODO: check if edge could change
22
+ edge: this.model.edge,
23
+ path: computed(() => this.model.path().path),
24
+ markerStart: this.markerStartUrl,
25
+ markerEnd: this.markerEndUrl
26
+ }
27
+ };
28
+ }
29
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
30
+ 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 [attr.stroke]=\"defaultColor\"\n stroke-width=\"2\"\n fill=\"none\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container *ngTemplateOutlet=\"edgeTemplate; context: edgeContext\"></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", 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: i2.EdgeLabelComponent, selector: "g[edgeLabel]", inputs: ["model", "edgeModel", "point", "htmlTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
31
+ }
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeComponent, decorators: [{
33
+ type: Component,
34
+ args: [{ selector: 'g[edge]', changeDetection: ChangeDetectionStrategy.OnPush, 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 [attr.stroke]=\"defaultColor\"\n stroke-width=\"2\"\n fill=\"none\"\n/>\n\n<ng-container *ngIf=\"model.type === 'template' && edgeTemplate\">\n <ng-container *ngTemplateOutlet=\"edgeTemplate; context: edgeContext\"></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" }]
35
+ }], propDecorators: { model: [{
36
+ type: Input
37
+ }], edgeTemplate: [{
38
+ type: Input
39
+ }], edgeLabelHtmlTemplate: [{
40
+ type: Input
41
+ }] } });
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRnZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvY29tcG9uZW50cy9lZGdlL2VkZ2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXZmbG93LWxpYi9zcmMvbGliL3ZmbG93L2NvbXBvbmVudHMvZWRnZS9lZGdlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUErQixRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFakgsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGtCQUFrQixDQUFDOzs7O0FBUTVDLE1BQU0sT0FBTyxhQUFhO0lBTDFCO1FBZVksbUJBQWMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ3ZDLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUE7WUFFN0MsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7UUFDbEUsQ0FBQyxDQUFDLENBQUE7UUFFUSxpQkFBWSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDckMsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQTtZQUUzQyxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtRQUNsRSxDQUFDLENBQUMsQ0FBQTtRQUVpQixpQkFBWSxHQUFHLG9CQUFvQixDQUFBO0tBZXZEO0lBWFEsUUFBUTtRQUNiLElBQUksQ0FBQyxXQUFXLEdBQUc7WUFDakIsU0FBUyxFQUFFO2dCQUNULG1DQUFtQztnQkFDbkMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSTtnQkFDckIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQztnQkFDNUMsV0FBVyxFQUFFLElBQUksQ0FBQyxjQUFjO2dCQUNoQyxTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVk7YUFDN0I7U0FDRixDQUFBO0lBQ0gsQ0FBQzsrR0FwQ1UsYUFBYTttR0FBYixhQUFhLHlKQ1YxQiw4bkNBd0NBOzs0RkQ5QmEsYUFBYTtrQkFMekIsU0FBUzsrQkFDRSxTQUFTLG1CQUVGLHVCQUF1QixDQUFDLE1BQU07OEJBSXhDLEtBQUs7c0JBRFgsS0FBSztnQkFJQyxZQUFZO3NCQURsQixLQUFLO2dCQUlDLHFCQUFxQjtzQkFEM0IsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIFNpZ25hbCwgVGVtcGxhdGVSZWYsIGNvbXB1dGVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBFZGdlTW9kZWwgfSBmcm9tICcuLi8uLi9tb2RlbHMvZWRnZS5tb2RlbCc7XG5pbXBvcnQgeyBoYXNoQ29kZSB9IGZyb20gJy4uLy4uL3V0aWxzL2hhc2gnO1xuaW1wb3J0IHsgRWRnZUNvbnRleHQgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3RlbXBsYXRlLWNvbnRleHQuaW50ZXJmYWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZ1tlZGdlXScsXG4gIHRlbXBsYXRlVXJsOiAnLi9lZGdlLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgRWRnZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBtb2RlbCE6IEVkZ2VNb2RlbFxuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBlZGdlVGVtcGxhdGU/OiBUZW1wbGF0ZVJlZjxFZGdlQ29udGV4dD5cblxuICBASW5wdXQoKVxuICBwdWJsaWMgZWRnZUxhYmVsSHRtbFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PlxuXG4gIHByb3RlY3RlZCBtYXJrZXJTdGFydFVybCA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBtYXJrZXIgPSB0aGlzLm1vZGVsLmVkZ2UubWFya2Vycz8uc3RhcnRcblxuICAgIHJldHVybiBtYXJrZXIgPyBgdXJsKCMke2hhc2hDb2RlKEpTT04uc3RyaW5naWZ5KG1hcmtlcikpfSlgIDogJydcbiAgfSlcblxuICBwcm90ZWN0ZWQgbWFya2VyRW5kVXJsID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IG1hcmtlciA9IHRoaXMubW9kZWwuZWRnZS5tYXJrZXJzPy5lbmRcblxuICAgIHJldHVybiBtYXJrZXIgPyBgdXJsKCMke2hhc2hDb2RlKEpTT04uc3RyaW5naWZ5KG1hcmtlcikpfSlgIDogJydcbiAgfSlcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVmYXVsdENvbG9yID0gJ3JnYigxNzcsIDE3NywgMTgzKSdcblxuICBwcm90ZWN0ZWQgZWRnZUNvbnRleHQhOiBFZGdlQ29udGV4dFxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmVkZ2VDb250ZXh0ID0ge1xuICAgICAgJGltcGxpY2l0OiB7XG4gICAgICAgIC8vIFRPRE86IGNoZWNrIGlmIGVkZ2UgY291bGQgY2hhbmdlXG4gICAgICAgIGVkZ2U6IHRoaXMubW9kZWwuZWRnZSxcbiAgICAgICAgcGF0aDogY29tcHV0ZWQoKCkgPT4gdGhpcy5tb2RlbC5wYXRoKCkucGF0aCksXG4gICAgICAgIG1hcmtlclN0YXJ0OiB0aGlzLm1hcmtlclN0YXJ0VXJsLFxuICAgICAgICBtYXJrZXJFbmQ6IHRoaXMubWFya2VyRW5kVXJsXG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iLCI8c3ZnOnBhdGhcbiAgKm5nSWY9XCJtb2RlbC50eXBlID09PSAnZGVmYXVsdCdcIlxuICBbYXR0ci5kXT1cIm1vZGVsLnBhdGgoKS5wYXRoXCJcbiAgW2F0dHIubWFya2VyLXN0YXJ0XT1cIm1hcmtlclN0YXJ0VXJsKClcIlxuICBbYXR0ci5tYXJrZXItZW5kXT1cIm1hcmtlckVuZFVybCgpXCJcbiAgW2F0dHIuc3Ryb2tlXT1cImRlZmF1bHRDb2xvclwiXG4gIHN0cm9rZS13aWR0aD1cIjJcIlxuICBmaWxsPVwibm9uZVwiXG4vPlxuXG48bmctY29udGFpbmVyICpuZ0lmPVwibW9kZWwudHlwZSA9PT0gJ3RlbXBsYXRlJyAmJiBlZGdlVGVtcGxhdGVcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImVkZ2VUZW1wbGF0ZTsgY29udGV4dDogZWRnZUNvbnRleHRcIj48L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPlxuXG48bmctY29udGFpbmVyICpuZ0lmPVwibW9kZWwuZWRnZUxhYmVscz8uc3RhcnQgYXMgbGFiZWxcIj5cbiAgPHN2ZzpnIGVkZ2VMYWJlbFxuICAgIFttb2RlbF09XCJsYWJlbFwiXG4gICAgW3BvaW50XT1cIm1vZGVsLnBhdGgoKS5wb2ludHMuc3RhcnRcIlxuICAgIFtlZGdlTW9kZWxdPVwibW9kZWxcIlxuICAgIFtodG1sVGVtcGxhdGVdPVwiZWRnZUxhYmVsSHRtbFRlbXBsYXRlXCJcbiAgLz5cbjwvbmctY29udGFpbmVyPlxuXG48bmctY29udGFpbmVyICpuZ0lmPVwibW9kZWwuZWRnZUxhYmVscz8uY2VudGVyIGFzIGxhYmVsXCI+XG4gIDxzdmc6ZyBlZGdlTGFiZWxcbiAgICBbbW9kZWxdPVwibGFiZWxcIlxuICAgIFtwb2ludF09XCJtb2RlbC5wYXRoKCkucG9pbnRzLmNlbnRlclwiXG4gICAgW2VkZ2VNb2RlbF09XCJtb2RlbFwiXG4gICAgW2h0bWxUZW1wbGF0ZV09XCJlZGdlTGFiZWxIdG1sVGVtcGxhdGVcIlxuICAvPlxuPC9uZy1jb250YWluZXI+XG5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJtb2RlbC5lZGdlTGFiZWxzPy5lbmQgYXMgbGFiZWxcIj5cbiAgPHN2ZzpnIGVkZ2VMYWJlbFxuICAgIFttb2RlbF09XCJsYWJlbFwiXG4gICAgW3BvaW50XT1cIm1vZGVsLnBhdGgoKS5wb2ludHMuZW5kXCJcbiAgICBbZWRnZU1vZGVsXT1cIm1vZGVsXCJcbiAgICBbaHRtbFRlbXBsYXRlXT1cImVkZ2VMYWJlbEh0bWxUZW1wbGF0ZVwiXG4gIC8+XG48L25nLWNvbnRhaW5lcj5cbiJdfQ==
@@ -0,0 +1,58 @@
1
+ import { ChangeDetectionStrategy, Component, Input, ViewChild, computed, signal } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ import * as i1 from "@angular/common";
4
+ export class EdgeLabelComponent {
5
+ constructor() {
6
+ /**
7
+ * Centered point of label
8
+ *
9
+ * TODO: maybe put it into EdgeLabelModel
10
+ */
11
+ this.edgeLabelPoint = computed(() => {
12
+ const point = this.pointSignal();
13
+ const { width, height } = this.model.size();
14
+ return {
15
+ x: point.x - (width / 2),
16
+ y: point.y - (height / 2)
17
+ };
18
+ });
19
+ this.pointSignal = signal({ x: 0, y: 0 });
20
+ }
21
+ set point(point) { this.pointSignal.set(point); }
22
+ ngAfterViewInit() {
23
+ queueMicrotask(() => {
24
+ // this is a fix for visual artifact in chrome that for some reason adresses only for edge label.
25
+ // the bug reproduces if edgeLabelWrapperRef size fully matched the size of parent foreignObject
26
+ const MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME = 2;
27
+ const width = this.edgeLabelWrapperRef.nativeElement.clientWidth + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
28
+ const height = this.edgeLabelWrapperRef.nativeElement.clientHeight + MAGIC_VALUE_TO_FIX_GLITCH_IN_CHROME;
29
+ this.model.size.set({ width, height });
30
+ });
31
+ }
32
+ getLabelContext() {
33
+ return {
34
+ $implicit: {
35
+ edge: this.edgeModel.edge,
36
+ label: this.model.edgeLabel
37
+ }
38
+ };
39
+ }
40
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeLabelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
41
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: EdgeLabelComponent, selector: "g[edgeLabel]", inputs: { model: "model", edgeModel: "edgeModel", point: "point", htmlTemplate: "htmlTemplate" }, viewQueries: [{ propertyName: "edgeLabelWrapperRef", first: true, predicate: ["edgeLabelWrapper"], descendants: true }], ngImport: i0, template: "<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 *ngIf=\"model.edgeLabel.type === 'html-template' && htmlTemplate\"\n>\n <div #edgeLabelWrapper class=\"edge-label-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"htmlTemplate; context: getLabelContext()\"\n />\n </div>\n</svg:foreignObject>\n", styles: [".edge-label-wrapper{width:max-content;margin-top:1px;margin-left:1px}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
42
+ }
43
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: EdgeLabelComponent, decorators: [{
44
+ type: Component,
45
+ args: [{ selector: 'g[edgeLabel]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<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 *ngIf=\"model.edgeLabel.type === 'html-template' && htmlTemplate\"\n>\n <div #edgeLabelWrapper class=\"edge-label-wrapper\">\n <ng-container\n *ngTemplateOutlet=\"htmlTemplate; context: getLabelContext()\"\n />\n </div>\n</svg:foreignObject>\n", styles: [".edge-label-wrapper{width:max-content;margin-top:1px;margin-left:1px}\n"] }]
46
+ }], propDecorators: { model: [{
47
+ type: Input
48
+ }], edgeModel: [{
49
+ type: Input
50
+ }], point: [{
51
+ type: Input
52
+ }], htmlTemplate: [{
53
+ type: Input
54
+ }], edgeLabelWrapperRef: [{
55
+ type: ViewChild,
56
+ args: ['edgeLabelWrapper']
57
+ }] } });
58
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRnZS1sYWJlbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvY29tcG9uZW50cy9lZGdlLWxhYmVsL2VkZ2UtbGFiZWwuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXZmbG93LWxpYi9zcmMvbGliL3ZmbG93L2NvbXBvbmVudHMvZWRnZS1sYWJlbC9lZGdlLWxhYmVsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsU0FBUyxFQUFjLEtBQUssRUFBaUQsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7OztBQXNCakwsTUFBTSxPQUFPLGtCQUFrQjtJQWpCL0I7UUFrQ0U7Ozs7V0FJRztRQUNPLG1CQUFjLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUN2QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7WUFFaEMsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFBO1lBRTNDLE9BQU87Z0JBQ0wsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO2dCQUN4QixDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7YUFDMUIsQ0FBQTtRQUNILENBQUMsQ0FBQyxDQUFBO1FBRU0sZ0JBQVcsR0FBRyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0tBdUI3QztJQWhEQyxJQUNXLEtBQUssQ0FBQyxLQUFZLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUEsQ0FBQyxDQUFDO0lBMEJ2RCxlQUFlO1FBQ3BCLGNBQWMsQ0FBQyxHQUFHLEVBQUU7WUFDbEIsaUdBQWlHO1lBQ2pHLGdHQUFnRztZQUNoRyxNQUFNLG1DQUFtQyxHQUFHLENBQUMsQ0FBQTtZQUU3QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsYUFBYSxDQUFDLFdBQVcsR0FBRyxtQ0FBbUMsQ0FBQTtZQUN0RyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsYUFBYSxDQUFDLFlBQVksR0FBRyxtQ0FBbUMsQ0FBQTtZQUV4RyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQTtRQUN4QyxDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFFUyxlQUFlO1FBQ3ZCLE9BQU87WUFDTCxTQUFTLEVBQUU7Z0JBQ1QsSUFBSSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSTtnQkFDekIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUzthQUM1QjtTQUNGLENBQUE7SUFDSCxDQUFDOytHQXZEVSxrQkFBa0I7bUdBQWxCLGtCQUFrQiwrUUN0Qi9CLDhhQWFBOzs0RkRTYSxrQkFBa0I7a0JBakI5QixTQUFTOytCQUNFLGNBQWMsbUJBY1AsdUJBQXVCLENBQUMsTUFBTTs4QkFLeEMsS0FBSztzQkFEWCxLQUFLO2dCQUlDLFNBQVM7c0JBRGYsS0FBSztnQkFJSyxLQUFLO3NCQURmLEtBQUs7Z0JBSUMsWUFBWTtzQkFEbEIsS0FBSztnQkFJQyxtQkFBbUI7c0JBRHpCLFNBQVM7dUJBQUMsa0JBQWtCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSW5wdXQsIE9uQ2hhbmdlcywgT25Jbml0LCBTaW1wbGVDaGFuZ2VzLCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkLCBjb21wdXRlZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBFZGdlTGFiZWxNb2RlbCB9IGZyb20gJy4uLy4uL21vZGVscy9lZGdlLWxhYmVsLm1vZGVsJztcbmltcG9ydCB7IEVkZ2VNb2RlbCB9IGZyb20gJy4uLy4uL21vZGVscy9lZGdlLm1vZGVsJztcbmltcG9ydCB7IFBvaW50IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9wb2ludC5pbnRlcmZhY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdnW2VkZ2VMYWJlbF0nLFxuICB0ZW1wbGF0ZVVybDogJy4vZWRnZS1sYWJlbC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlczogW2BcbiAgICAuZWRnZS1sYWJlbC13cmFwcGVyIHtcbiAgICAgIHdpZHRoOiBtYXgtY29udGVudDtcblxuICAgICAgLypcbiAgICAgICAgdGhpcyBpcyBhIGZpeCBmb3IgYnVnIGluIGNocm9tZSwgZm9yIHNvbWUgcmVhc29uIGlmIHRoZSBkaXYgZnVsbHkgbWF0Y2hlcyB0aGUgc2l6ZVxuICAgICAgICBvZiBmb3JlaWduT2JqZWN0IHRoZXJlIGFyZSBvY2N1cnMgc29tZSB2aXN1YWwgYXJ0aWZhY3RzIGFyb3VuZCB0aGlzIGRpdlxuICAgICAgICovXG4gICAgICBtYXJnaW4tdG9wOiAxcHg7XG4gICAgICBtYXJnaW4tbGVmdDogMXB4O1xuICAgIH1cbiAgYF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXG59KVxuZXhwb3J0IGNsYXNzIEVkZ2VMYWJlbENvbXBvbmVudCBpbXBsZW1lbnRzIEFmdGVyVmlld0luaXQge1xuICAvLyBUT0RPOiB0b28gbWFueSBpbnB1dHNcbiAgQElucHV0KClcbiAgcHVibGljIG1vZGVsITogRWRnZUxhYmVsTW9kZWxcblxuICBASW5wdXQoKVxuICBwdWJsaWMgZWRnZU1vZGVsITogRWRnZU1vZGVsXG5cbiAgQElucHV0KClcbiAgcHVibGljIHNldCBwb2ludChwb2ludDogUG9pbnQpIHsgdGhpcy5wb2ludFNpZ25hbC5zZXQocG9pbnQpIH1cblxuICBASW5wdXQoKVxuICBwdWJsaWMgaHRtbFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PlxuXG4gIEBWaWV3Q2hpbGQoJ2VkZ2VMYWJlbFdyYXBwZXInKVxuICBwdWJsaWMgZWRnZUxhYmVsV3JhcHBlclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+XG5cbiAgLyoqXG4gICAqIENlbnRlcmVkIHBvaW50IG9mIGxhYmVsXG4gICAqXG4gICAqIFRPRE86IG1heWJlIHB1dCBpdCBpbnRvIEVkZ2VMYWJlbE1vZGVsXG4gICAqL1xuICBwcm90ZWN0ZWQgZWRnZUxhYmVsUG9pbnQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgcG9pbnQgPSB0aGlzLnBvaW50U2lnbmFsKClcblxuICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gdGhpcy5tb2RlbC5zaXplKClcblxuICAgIHJldHVybiB7XG4gICAgICB4OiBwb2ludC54IC0gKHdpZHRoIC8gMiksXG4gICAgICB5OiBwb2ludC55IC0gKGhlaWdodCAvIDIpXG4gICAgfVxuICB9KVxuXG4gIHByaXZhdGUgcG9pbnRTaWduYWwgPSBzaWduYWwoeyB4OiAwLCB5OiAwIH0pXG5cbiAgcHVibGljIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBxdWV1ZU1pY3JvdGFzaygoKSA9PiB7XG4gICAgICAvLyB0aGlzIGlzIGEgZml4IGZvciB2aXN1YWwgYXJ0aWZhY3QgaW4gY2hyb21lIHRoYXQgZm9yIHNvbWUgcmVhc29uIGFkcmVzc2VzIG9ubHkgZm9yIGVkZ2UgbGFiZWwuXG4gICAgICAvLyB0aGUgYnVnIHJlcHJvZHVjZXMgaWYgZWRnZUxhYmVsV3JhcHBlclJlZiBzaXplIGZ1bGx5IG1hdGNoZWQgdGhlIHNpemUgb2YgcGFyZW50IGZvcmVpZ25PYmplY3RcbiAgICAgIGNvbnN0IE1BR0lDX1ZBTFVFX1RPX0ZJWF9HTElUQ0hfSU5fQ0hST01FID0gMlxuXG4gICAgICBjb25zdCB3aWR0aCA9IHRoaXMuZWRnZUxhYmVsV3JhcHBlclJlZi5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoICsgTUFHSUNfVkFMVUVfVE9fRklYX0dMSVRDSF9JTl9DSFJPTUVcbiAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuZWRnZUxhYmVsV3JhcHBlclJlZi5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodCArIE1BR0lDX1ZBTFVFX1RPX0ZJWF9HTElUQ0hfSU5fQ0hST01FXG5cbiAgICAgIHRoaXMubW9kZWwuc2l6ZS5zZXQoeyB3aWR0aCwgaGVpZ2h0IH0pXG4gICAgfSlcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRMYWJlbENvbnRleHQoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICRpbXBsaWNpdDoge1xuICAgICAgICBlZGdlOiB0aGlzLmVkZ2VNb2RlbC5lZGdlLFxuICAgICAgICBsYWJlbDogdGhpcy5tb2RlbC5lZGdlTGFiZWxcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiIsIjxzdmc6Zm9yZWlnbk9iamVjdFxuICBbYXR0ci54XT1cImVkZ2VMYWJlbFBvaW50KCkueFwiXG4gIFthdHRyLnldPVwiZWRnZUxhYmVsUG9pbnQoKS55XCJcbiAgW2F0dHIud2lkdGhdPVwibW9kZWwuc2l6ZSgpLndpZHRoXCJcbiAgW2F0dHIuaGVpZ2h0XT1cIm1vZGVsLnNpemUoKS5oZWlnaHRcIlxuICAqbmdJZj1cIm1vZGVsLmVkZ2VMYWJlbC50eXBlID09PSAnaHRtbC10ZW1wbGF0ZScgJiYgaHRtbFRlbXBsYXRlXCJcbj5cbiAgPGRpdiAjZWRnZUxhYmVsV3JhcHBlciBjbGFzcz1cImVkZ2UtbGFiZWwtd3JhcHBlclwiPlxuICAgIDxuZy1jb250YWluZXJcbiAgICAgICpuZ1RlbXBsYXRlT3V0bGV0PVwiaHRtbFRlbXBsYXRlOyBjb250ZXh0OiBnZXRMYWJlbENvbnRleHQoKVwiXG4gICAgLz5cbiAgPC9kaXY+XG48L3N2Zzpmb3JlaWduT2JqZWN0PlxuIl19
@@ -0,0 +1,146 @@
1
+ import { ChangeDetectionStrategy, Component, ElementRef, Input, ViewChild, computed, inject, signal } from '@angular/core';
2
+ import { DraggableService } from '../../services/draggable.service';
3
+ import { FlowStatusService, batchStatusChanges } from '../../services/flow-status.service';
4
+ import { FlowEntitiesService } from '../../services/flow-entities.service';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/common";
7
+ export class NodeComponent {
8
+ constructor() {
9
+ this.draggableService = inject(DraggableService);
10
+ this.flowStatusService = inject(FlowStatusService);
11
+ this.flowEntitiesService = inject(FlowEntitiesService);
12
+ this.hostRef = inject(ElementRef);
13
+ this.showMagnet = computed(() => this.flowStatusService.status().state === 'connection-start' ||
14
+ this.flowStatusService.status().state === 'connection-validation');
15
+ this.defaultHandleStrokeWidth = 2;
16
+ this.sourceHanldeState = signal('idle');
17
+ this.targetHandleState = signal('idle');
18
+ this.sourceHanldeStateReadonly = this.sourceHanldeState.asReadonly();
19
+ this.targetHanldeStateReadonly = this.targetHandleState.asReadonly();
20
+ }
21
+ ngOnInit() {
22
+ this.draggableService.toggleDraggable(this.hostRef.nativeElement, this.nodeModel);
23
+ }
24
+ ngAfterViewInit() {
25
+ // TODO remove microtask
26
+ queueMicrotask(() => {
27
+ if (this.nodeModel.node.type === 'default') {
28
+ const { width, height } = this.nodeContentRef.nativeElement.getBBox();
29
+ this.nodeModel.size.set({ width, height });
30
+ }
31
+ if (this.nodeModel.node.type === 'html-template') {
32
+ const width = this.htmlWrapperRef.nativeElement.clientWidth;
33
+ const height = this.htmlWrapperRef.nativeElement.clientHeight;
34
+ this.nodeModel.size.set({ width, height });
35
+ }
36
+ this.setSourceHandleSize();
37
+ this.setTargetHandleSize();
38
+ });
39
+ }
40
+ ngOnDestroy() {
41
+ this.draggableService.destroy(this.hostRef.nativeElement);
42
+ }
43
+ startConnection(event) {
44
+ // ignore drag by stopping propagation
45
+ event.stopPropagation();
46
+ this.flowStatusService.setConnectionStartStatus(this.nodeModel);
47
+ }
48
+ endConnection() {
49
+ const status = this.flowStatusService.status();
50
+ if (status.state === 'connection-validation') {
51
+ const sourceNode = status.payload.sourceNode;
52
+ const targetNode = this.nodeModel;
53
+ batchStatusChanges(
54
+ // call to create connection
55
+ () => this.flowStatusService.setConnectionEndStatus(sourceNode, targetNode),
56
+ // when connection created, we need go back to idle status
57
+ () => this.flowStatusService.setIdleStatus());
58
+ }
59
+ }
60
+ /**
61
+ * TODO srp
62
+ */
63
+ validateTargetHandle() {
64
+ const status = this.flowStatusService.status();
65
+ if (status.state === 'connection-start') {
66
+ const sourceNode = status.payload.sourceNode;
67
+ const targetNode = this.nodeModel;
68
+ const source = sourceNode.node.id;
69
+ const target = targetNode.node.id;
70
+ const valid = this.flowEntitiesService.connection().validator({ source, target });
71
+ this.targetHandleState.set(valid ? 'valid' : 'invalid');
72
+ this.flowStatusService.setConnectionValidationStatus(sourceNode, targetNode, valid);
73
+ }
74
+ }
75
+ /**
76
+ * TODO srp
77
+ */
78
+ resetValidateTargetHandle() {
79
+ this.targetHandleState.set('idle');
80
+ // drop back to start status
81
+ const status = this.flowStatusService.status();
82
+ if (status.state === 'connection-validation') {
83
+ this.flowStatusService.setConnectionStartStatus(status.payload.sourceNode);
84
+ }
85
+ }
86
+ getHandleContext(type) {
87
+ if (type === 'source') {
88
+ return {
89
+ $implicit: {
90
+ point: this.nodeModel.sourceOffset,
91
+ alignedPoint: this.nodeModel.sourceOffsetAligned,
92
+ state: this.sourceHanldeStateReadonly
93
+ }
94
+ };
95
+ }
96
+ return {
97
+ $implicit: {
98
+ point: this.nodeModel.targetOffset,
99
+ alignedPoint: this.nodeModel.targetOffsetAligned,
100
+ state: this.targetHanldeStateReadonly
101
+ }
102
+ };
103
+ }
104
+ setSourceHandleSize() {
105
+ // if handle template provided, we don't know its stroke so it's 0
106
+ const strokeWidth = this.handleTemplate ? 0 : (2 * this.defaultHandleStrokeWidth);
107
+ const sourceBox = this.sourceHandleRef.nativeElement.getBBox({ stroke: true });
108
+ this.nodeModel.sourceHandleSize.set({
109
+ width: sourceBox.width + strokeWidth,
110
+ height: sourceBox.height + strokeWidth
111
+ });
112
+ }
113
+ setTargetHandleSize() {
114
+ const strokeWidth = this.handleTemplate ? 0 : (2 * this.defaultHandleStrokeWidth);
115
+ const targetBox = this.targetHandleRef.nativeElement.getBBox({ stroke: true });
116
+ this.nodeModel.targetHandleSize.set({
117
+ width: targetBox.width + strokeWidth,
118
+ height: targetBox.height + strokeWidth
119
+ });
120
+ }
121
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
122
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: NodeComponent, selector: "g[node]", inputs: { nodeModel: "nodeModel", nodeHtmlTemplate: "nodeHtmlTemplate", handleTemplate: "handleTemplate" }, viewQueries: [{ propertyName: "nodeContentRef", first: true, predicate: ["nodeContent"], descendants: true }, { propertyName: "htmlWrapperRef", first: true, predicate: ["htmlWrapper"], descendants: true }, { propertyName: "sourceHandleRef", first: true, predicate: ["sourceHandle"], descendants: true }, { propertyName: "targetHandleRef", first: true, predicate: ["targetHandle"], descendants: true }], ngImport: i0, template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n>\n <div class=\"default-node\" [innerHTML]=\"nodeModel.node.text ?? ''\"></div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n *ngTemplateOutlet=\"nodeHtmlTemplate; context: { $implicit: { node: nodeModel.node } }\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngIf=\"handleTemplate\">\n <svg:g #sourceHandle (mousedown)=\"startConnection($event)\">\n <ng-container *ngTemplateOutlet=\"handleTemplate; context: getHandleContext('source')\" />\n </svg:g>\n\n <svg:g #targetHandle>\n <ng-container *ngTemplateOutlet=\"handleTemplate; context: getHandleContext('target')\" />\n </svg:g>\n</ng-container>\n\n<ng-container *ngIf=\"!handleTemplate\">\n <svg:circle\n #sourceHandle\n [attr.cx]=\"nodeModel.sourceOffset().x\"\n [attr.cy]=\"nodeModel.sourceOffset().y\"\n [attr.stroke-width]=\"defaultHandleStrokeWidth\"\n r=\"5\"\n stroke=\"white\"\n fill=\"black\"\n (mousedown)=\"startConnection($event)\"\n />\n\n <svg:circle\n #targetHandle\n [attr.cx]=\"nodeModel.targetOffset().x\"\n [attr.cy]=\"nodeModel.targetOffset().y\"\n [attr.stroke-width]=\"defaultHandleStrokeWidth\"\n r=\"5\"\n stroke=\"white\"\n fill=\"black\"\n (mouseup)=\"endConnection()\"\n />\n</ng-container>\n\n<svg:circle\n *ngIf=\"showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"nodeModel.targetOffset().x\"\n [attr.cy]=\"nodeModel.targetOffset().y\"\n (mouseup)=\"endConnection(); resetValidateTargetHandle()\"\n (mouseover)=\"validateTargetHandle()\"\n (mouseout)=\"resetValidateTargetHandle()\"\n/>\n\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;border:2px solid black;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
123
+ }
124
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: NodeComponent, decorators: [{
125
+ type: Component,
126
+ args: [{ selector: 'g[node]', changeDetection: ChangeDetectionStrategy.OnPush, template: "<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'default'\"\n #nodeContent\n width=\"100\"\n height=\"50\"\n>\n <div class=\"default-node\" [innerHTML]=\"nodeModel.node.text ?? ''\"></div>\n</svg:foreignObject>\n\n<svg:foreignObject\n *ngIf=\"nodeModel.node.type === 'html-template' && nodeHtmlTemplate\"\n [attr.width]=\"nodeModel.size().width\"\n [attr.height]=\"nodeModel.size().height\"\n>\n <div #htmlWrapper class=\"wrapper\">\n <ng-container\n *ngTemplateOutlet=\"nodeHtmlTemplate; context: { $implicit: { node: nodeModel.node } }\"\n />\n </div>\n</svg:foreignObject>\n\n<ng-container *ngIf=\"handleTemplate\">\n <svg:g #sourceHandle (mousedown)=\"startConnection($event)\">\n <ng-container *ngTemplateOutlet=\"handleTemplate; context: getHandleContext('source')\" />\n </svg:g>\n\n <svg:g #targetHandle>\n <ng-container *ngTemplateOutlet=\"handleTemplate; context: getHandleContext('target')\" />\n </svg:g>\n</ng-container>\n\n<ng-container *ngIf=\"!handleTemplate\">\n <svg:circle\n #sourceHandle\n [attr.cx]=\"nodeModel.sourceOffset().x\"\n [attr.cy]=\"nodeModel.sourceOffset().y\"\n [attr.stroke-width]=\"defaultHandleStrokeWidth\"\n r=\"5\"\n stroke=\"white\"\n fill=\"black\"\n (mousedown)=\"startConnection($event)\"\n />\n\n <svg:circle\n #targetHandle\n [attr.cx]=\"nodeModel.targetOffset().x\"\n [attr.cy]=\"nodeModel.targetOffset().y\"\n [attr.stroke-width]=\"defaultHandleStrokeWidth\"\n r=\"5\"\n stroke=\"white\"\n fill=\"black\"\n (mouseup)=\"endConnection()\"\n />\n</ng-container>\n\n<svg:circle\n *ngIf=\"showMagnet()\"\n class=\"magnet\"\n [attr.r]=\"nodeModel.magnetRadius\"\n [attr.cx]=\"nodeModel.targetOffset().x\"\n [attr.cy]=\"nodeModel.targetOffset().y\"\n (mouseup)=\"endConnection(); resetValidateTargetHandle()\"\n (mouseover)=\"validateTargetHandle()\"\n (mouseout)=\"resetValidateTargetHandle()\"\n/>\n\n\n", styles: [".wrapper{width:max-content}.magnet{opacity:0}.default-node{max-width:100px;max-height:100px;width:100px;height:50px;border:2px solid black;border-radius:5px;display:flex;align-items:center;justify-content:center;color:#000;background-color:#fff}\n"] }]
127
+ }], propDecorators: { nodeModel: [{
128
+ type: Input
129
+ }], nodeHtmlTemplate: [{
130
+ type: Input
131
+ }], handleTemplate: [{
132
+ type: Input
133
+ }], nodeContentRef: [{
134
+ type: ViewChild,
135
+ args: ['nodeContent']
136
+ }], htmlWrapperRef: [{
137
+ type: ViewChild,
138
+ args: ['htmlWrapper']
139
+ }], sourceHandleRef: [{
140
+ type: ViewChild,
141
+ args: ['sourceHandle']
142
+ }], targetHandleRef: [{
143
+ type: ViewChild,
144
+ args: ['targetHandle']
145
+ }] } });
146
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdmZsb3ctbGliL3NyYy9saWIvdmZsb3cvY29tcG9uZW50cy9ub2RlL25vZGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXZmbG93LWxpYi9zcmMvbGliL3ZmbG93L2NvbXBvbmVudHMvbm9kZS9ub2RlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBaUIsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBZSxLQUFLLEVBQTBDLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvTCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVwRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUMzRixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQzs7O0FBVTNFLE1BQU0sT0FBTyxhQUFhO0lBTjFCO1FBNEJVLHFCQUFnQixHQUFHLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO1FBQzNDLHNCQUFpQixHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1FBQzdDLHdCQUFtQixHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFBO1FBQ2pELFlBQU8sR0FBRyxNQUFNLENBQXlCLFVBQVUsQ0FBQyxDQUFBO1FBRWxELGVBQVUsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQ25DLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEtBQUssa0JBQWtCO1lBQzVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLEtBQUssdUJB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UyxDQUFDLEtBQUssR0FBRyxXQUFXO1lBQ3BDLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTSxHQUFHLFdBQVc7U0FDdkMsQ0FBQyxDQUFBO0lBQ0osQ0FBQzsrR0FuS1UsYUFBYTttR0FBYixhQUFhLDhpQkNkMUIseTVEQW1FQTs7NEZEckRhLGFBQWE7a0JBTnpCLFNBQVM7K0JBQ0UsU0FBUyxtQkFHRix1QkFBdUIsQ0FBQyxNQUFNOzhCQUl4QyxTQUFTO3NCQURmLEtBQUs7Z0JBSUMsZ0JBQWdCO3NCQUR0QixLQUFLO2dCQUlDLGNBQWM7c0JBRHBCLEtBQUs7Z0JBSUMsY0FBYztzQkFEcEIsU0FBUzt1QkFBQyxhQUFhO2dCQUlqQixjQUFjO3NCQURwQixTQUFTO3VCQUFDLGFBQWE7Z0JBSWpCLGVBQWU7c0JBRHJCLFNBQVM7dUJBQUMsY0FBYztnQkFJbEIsZUFBZTtzQkFEckIsU0FBUzt1QkFBQyxjQUFjIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsIElucHV0LCBOZ1pvbmUsIE9uRGVzdHJveSwgT25Jbml0LCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkLCBjb21wdXRlZCwgaW5qZWN0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERyYWdnYWJsZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9kcmFnZ2FibGUuc2VydmljZSc7XG5pbXBvcnQgeyBOb2RlTW9kZWwgfSBmcm9tICcuLi8uLi9tb2RlbHMvbm9kZS5tb2RlbCc7XG5pbXBvcnQgeyBGbG93U3RhdHVzU2VydmljZSwgYmF0Y2hTdGF0dXNDaGFuZ2VzIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZmxvdy1zdGF0dXMuc2VydmljZSc7XG5pbXBvcnQgeyBGbG93RW50aXRpZXNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZmxvdy1lbnRpdGllcy5zZXJ2aWNlJztcblxuZXhwb3J0IHR5cGUgSGFuZGxlU3RhdGUgPSAndmFsaWQnIHwgJ2ludmFsaWQnIHwgJ2lkbGUnXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dbbm9kZV0nLFxuICB0ZW1wbGF0ZVVybDogJy4vbm9kZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL25vZGUuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgTm9kZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KClcbiAgcHVibGljIG5vZGVNb2RlbCE6IE5vZGVNb2RlbFxuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBub2RlSHRtbFRlbXBsYXRlPzogVGVtcGxhdGVSZWY8YW55PlxuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBoYW5kbGVUZW1wbGF0ZT86IFRlbXBsYXRlUmVmPGFueT5cblxuICBAVmlld0NoaWxkKCdub2RlQ29udGVudCcpXG4gIHB1YmxpYyBub2RlQ29udGVudFJlZiE6IEVsZW1lbnRSZWY8U1ZHR3JhcGhpY3NFbGVtZW50PlxuXG4gIEBWaWV3Q2hpbGQoJ2h0bWxXcmFwcGVyJylcbiAgcHVibGljIGh0bWxXcmFwcGVyUmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD5cblxuICBAVmlld0NoaWxkKCdzb3VyY2VIYW5kbGUnKVxuICBwdWJsaWMgc291cmNlSGFuZGxlUmVmITogRWxlbWVudFJlZjxTVkdHRWxlbWVudCB8IFNWR0NpcmNsZUVsZW1lbnQ+XG5cbiAgQFZpZXdDaGlsZCgndGFyZ2V0SGFuZGxlJylcbiAgcHVibGljIHRhcmdldEhhbmRsZVJlZiE6IEVsZW1lbnRSZWY8U1ZHR0VsZW1lbnQgfCBTVkdDaXJjbGVFbGVtZW50PlxuXG4gIHByaXZhdGUgZHJhZ2dhYmxlU2VydmljZSA9IGluamVjdChEcmFnZ2FibGVTZXJ2aWNlKVxuICBwcml2YXRlIGZsb3dTdGF0dXNTZXJ2aWNlID0gaW5qZWN0KEZsb3dTdGF0dXNTZXJ2aWNlKVxuICBwcml2YXRlIGZsb3dFbnRpdGllc1NlcnZpY2UgPSBpbmplY3QoRmxvd0VudGl0aWVzU2VydmljZSlcbiAgcHJpdmF0ZSBob3N0UmVmID0gaW5qZWN0PEVsZW1lbnRSZWY8U1ZHRWxlbWVudD4+KEVsZW1lbnRSZWYpXG5cbiAgcHJvdGVjdGVkIHNob3dNYWduZXQgPSBjb21wdXRlZCgoKSA9PlxuICAgIHRoaXMuZmxvd1N0YXR1c1NlcnZpY2Uuc3RhdHVzKCkuc3RhdGUgPT09ICdjb25uZWN0aW9uLXN0YXJ0JyB8fFxuICAgIHRoaXMuZmxvd1N0YXR1c1NlcnZpY2Uuc3RhdHVzKCkuc3RhdGUgPT09ICdjb25uZWN0aW9uLXZhbGlkYXRpb24nXG4gIClcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVmYXVsdEhhbmRsZVN0cm9rZVdpZHRoID0gMjtcblxuICBwcml2YXRlIHNvdXJjZUhhbmxkZVN0YXRlID0gc2lnbmFsPEhhbmRsZVN0YXRlPignaWRsZScpXG4gIHByaXZhdGUgdGFyZ2V0SGFuZGxlU3RhdGUgPSBzaWduYWw8SGFuZGxlU3RhdGU+KCdpZGxlJylcblxuICBwcml2YXRlIHNvdXJjZUhhbmxkZVN0YXRlUmVhZG9ubHkgPSB0aGlzLnNvdXJjZUhhbmxkZVN0YXRlLmFzUmVhZG9ubHkoKVxuICBwcml2YXRlIHRhcmdldEhhbmxkZVN0YXRlUmVhZG9ubHkgPSB0aGlzLnRhcmdldEhhbmRsZVN0YXRlLmFzUmVhZG9ubHkoKVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmRyYWdnYWJsZVNlcnZpY2UudG9nZ2xlRHJhZ2dhYmxlKHRoaXMuaG9zdFJlZi5uYXRpdmVFbGVtZW50LCB0aGlzLm5vZGVNb2RlbClcbiAgfVxuXG4gIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgLy8gVE9ETyByZW1vdmUgbWljcm90YXNrXG4gICAgcXVldWVNaWNyb3Rhc2soKCkgPT4ge1xuICAgICAgaWYgKHRoaXMubm9kZU1vZGVsLm5vZGUudHlwZSA9PT0gJ2RlZmF1bHQnKSB7XG4gICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCB9ID0gdGhpcy5ub2RlQ29udGVudFJlZi5uYXRpdmVFbGVtZW50LmdldEJCb3goKVxuICAgICAgICB0aGlzLm5vZGVNb2RlbC5zaXplLnNldCh7IHdpZHRoLCBoZWlnaHQgfSlcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMubm9kZU1vZGVsLm5vZGUudHlwZSA9PT0gJ2h0bWwtdGVtcGxhdGUnKSB7XG4gICAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5odG1sV3JhcHBlclJlZi5uYXRpdmVFbGVtZW50LmNsaWVudFdpZHRoXG4gICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMuaHRtbFdyYXBwZXJSZWYubmF0aXZlRWxlbWVudC5jbGllbnRIZWlnaHRcblxuICAgICAgICB0aGlzLm5vZGVNb2RlbC5zaXplLnNldCh7IHdpZHRoLCBoZWlnaHQgfSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRTb3VyY2VIYW5kbGVTaXplKClcbiAgICAgIHRoaXMuc2V0VGFyZ2V0SGFuZGxlU2l6ZSgpXG4gICAgfSlcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRyYWdnYWJsZVNlcnZpY2UuZGVzdHJveSh0aGlzLmhvc3RSZWYubmF0aXZlRWxlbWVudClcbiAgfVxuXG4gIHByb3RlY3RlZCBzdGFydENvbm5lY3Rpb24oZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAvLyBpZ25vcmUgZHJhZyBieSBzdG9wcGluZyBwcm9wYWdhdGlvblxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXG5cbiAgICB0aGlzLmZsb3dTdGF0dXNTZXJ2aWNlLnNldENvbm5lY3Rpb25TdGFydFN0YXR1cyh0aGlzLm5vZGVNb2RlbClcbiAgfVxuXG4gIHByb3RlY3RlZCBlbmRDb25uZWN0aW9uKCkge1xuICAgIGNvbnN0IHN0YXR1cyA9IHRoaXMuZmxvd1N0YXR1c1NlcnZpY2Uuc3RhdHVzKClcblxuICAgIGlmIChzdGF0dXMuc3RhdGUgPT09ICdjb25uZWN0aW9uLXZhbGlkYXRpb24nKSB7XG4gICAgICBjb25zdCBzb3VyY2VOb2RlID0gc3RhdHVzLnBheWxvYWQuc291cmNlTm9kZVxuICAgICAgY29uc3QgdGFyZ2V0Tm9kZSA9IHRoaXMubm9kZU1vZGVsXG5cbiAgICAgIGJhdGNoU3RhdHVzQ2hhbmdlcyhcbiAgICAgICAgLy8gY2FsbCB0byBjcmVhdGUgY29ubmVjdGlvblxuICAgICAgICAoKSA9PiB0aGlzLmZsb3dTdGF0dXNTZXJ2aWNlLnNldENvbm5lY3Rpb25FbmRTdGF0dXMoc291cmNlTm9kZSwgdGFyZ2V0Tm9kZSksXG4gICAgICAgIC8vIHdoZW4gY29ubmVjdGlvbiBjcmVhdGVkLCB3ZSBuZWVkIGdvIGJhY2sgdG8gaWRsZSBzdGF0dXNcbiAgICAgICAgKCkgPT4gdGhpcy5mbG93U3RhdHVzU2VydmljZS5zZXRJZGxlU3RhdHVzKClcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVE9ETyBzcnBcbiAgICovXG4gIHByb3RlY3RlZCB2YWxpZGF0ZVRhcmdldEhhbmRsZSgpIHtcbiAgICBjb25zdCBzdGF0dXMgPSB0aGlzLmZsb3dTdGF0dXNTZXJ2aWNlLnN0YXR1cygpXG5cbiAgICBpZiAoc3RhdHVzLnN0YXRlID09PSAnY29ubmVjdGlvbi1zdGFydCcpIHtcbiAgICAgIGNvbnN0IHNvdXJjZU5vZGUgPSBzdGF0dXMucGF5bG9hZC5zb3VyY2VOb2RlXG4gICAgICBjb25zdCB0YXJnZXROb2RlID0gdGhpcy5ub2RlTW9kZWxcblxuICAgICAgY29uc3Qgc291cmNlID0gc291cmNlTm9kZS5ub2RlLmlkXG4gICAgICBjb25zdCB0YXJnZXQgPSB0YXJnZXROb2RlLm5vZGUuaWRcblxuICAgICAgY29uc3QgdmFsaWQgPSB0aGlzLmZsb3dFbnRpdGllc1NlcnZpY2UuY29ubmVjdGlvbigpLnZhbGlkYXRvcih7IHNvdXJjZSwgdGFyZ2V0IH0pXG4gICAgICB0aGlzLnRhcmdldEhhbmRsZVN0YXRlLnNldCh2YWxpZCA/ICd2YWxpZCcgOiAnaW52YWxpZCcpXG5cbiAgICAgIHRoaXMuZmxvd1N0YXR1c1NlcnZpY2Uuc2V0Q29ubmVjdGlvblZhbGlkYXRpb25TdGF0dXMoc291cmNlTm9kZSwgdGFyZ2V0Tm9kZSwgdmFsaWQpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRPRE8gc3JwXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzZXRWYWxpZGF0ZVRhcmdldEhhbmRsZSgpIHtcbiAgICB0aGlzLnRhcmdldEhhbmRsZVN0YXRlLnNldCgnaWRsZScpXG5cbiAgICAvLyBkcm9wIGJhY2sgdG8gc3RhcnQgc3RhdHVzXG4gICAgY29uc3Qgc3RhdHVzID0gdGhpcy5mbG93U3RhdHVzU2VydmljZS5zdGF0dXMoKVxuICAgIGlmIChzdGF0dXMuc3RhdGUgPT09ICdjb25uZWN0aW9uLXZhbGlkYXRpb24nKSB7XG4gICAgICB0aGlzLmZsb3dTdGF0dXNTZXJ2aWNlLnNldENvbm5lY3Rpb25TdGFydFN0YXR1cyhzdGF0dXMucGF5bG9hZC5zb3VyY2VOb2RlKVxuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRIYW5kbGVDb250ZXh0KHR5cGU6ICdzb3VyY2UnIHwgJ3RhcmdldCcpIHtcbiAgICBpZiAodHlwZSA9PT0gJ3NvdXJjZScpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgICRpbXBsaWNpdDoge1xuICAgICAgICAgIHBvaW50OiB0aGlzLm5vZGVNb2RlbC5zb3VyY2VPZmZzZXQsXG4gICAgICAgICAgYWxpZ25lZFBvaW50OiB0aGlzLm5vZGVNb2RlbC5zb3VyY2VPZmZzZXRBbGlnbmVkLFxuICAgICAgICAgIHN0YXRlOiB0aGlzLnNvdXJjZUhhbmxkZVN0YXRlUmVhZG9ubHlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAkaW1wbGljaXQ6IHtcbiAgICAgICAgcG9pbnQ6IHRoaXMubm9kZU1vZGVsLnRhcmdldE9mZnNldCxcbiAgICAgICAgYWxpZ25lZFBvaW50OiB0aGlzLm5vZGVNb2RlbC50YXJnZXRPZmZzZXRBbGlnbmVkLFxuICAgICAgICBzdGF0ZTogdGhpcy50YXJnZXRIYW5sZGVTdGF0ZVJlYWRvbmx5XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzZXRTb3VyY2VIYW5kbGVTaXplKCkge1xuICAgIC8vIGlmIGhhbmRsZSB0ZW1wbGF0ZSBwcm92aWRlZCwgd2UgZG9uJ3Qga25vdyBpdHMgc3Ryb2tlIHNvIGl0J3MgMFxuICAgIGNvbnN0IHN0cm9rZVdpZHRoID0gdGhpcy5oYW5kbGVUZW1wbGF0ZSA/IDAgOiAoMiAqIHRoaXMuZGVmYXVsdEhhbmRsZVN0cm9rZVdpZHRoKTtcblxuICAgIGNvbnN0IHNvdXJjZUJveCA9IHRoaXMuc291cmNlSGFuZGxlUmVmLm5hdGl2ZUVsZW1lbnQuZ2V0QkJveCh7IHN0cm9rZTogdHJ1ZSB9KVxuICAgIHRoaXMubm9kZU1vZGVsLnNvdXJjZUhhbmRsZVNpemUuc2V0KHtcbiAgICAgIHdpZHRoOiBzb3VyY2VCb3gud2lkdGggKyBzdHJva2VXaWR0aCxcbiAgICAgIGhlaWdodDogc291cmNlQm94LmhlaWdodCArIHN0cm9rZVdpZHRoXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgc2V0VGFyZ2V0SGFuZGxlU2l6ZSgpIHtcbiAgICBjb25zdCBzdHJva2VXaWR0aCA9IHRoaXMuaGFuZGxlVGVtcGxhdGUgPyAwIDogKDIgKiB0aGlzLmRlZmF1bHRIYW5kbGVTdHJva2VXaWR0aCk7XG5cbiAgICBjb25zdCB0YXJnZXRCb3ggPSB0aGlzLnRhcmdldEhhbmRsZVJlZi5uYXRpdmVFbGVtZW50LmdldEJCb3goeyBzdHJva2U6IHRydWUgfSlcbiAgICB0aGlzLm5vZGVNb2RlbC50YXJnZXRIYW5kbGVTaXplLnNldCh7XG4gICAgICB3aWR0aDogdGFyZ2V0Qm94LndpZHRoICsgc3Ryb2tlV2lkdGgsXG4gICAgICBoZWlnaHQ6IHRhcmdldEJveC5oZWlnaHQgKyBzdHJva2VXaWR0aFxuICAgIH0pXG4gIH1cbn1cbiIsIjxzdmc6Zm9yZWlnbk9iamVjdFxuICAqbmdJZj1cIm5vZGVNb2RlbC5ub2RlLnR5cGUgPT09ICdkZWZhdWx0J1wiXG4gICNub2RlQ29udGVudFxuICB3aWR0aD1cIjEwMFwiXG4gIGhlaWdodD1cIjUwXCJcbj5cbiAgPGRpdiBjbGFzcz1cImRlZmF1bHQtbm9kZVwiIFtpbm5lckhUTUxdPVwibm9kZU1vZGVsLm5vZGUudGV4dCA/PyAnJ1wiPjwvZGl2PlxuPC9zdmc6Zm9yZWlnbk9iamVjdD5cblxuPHN2Zzpmb3JlaWduT2JqZWN0XG4gICpuZ0lmPVwibm9kZU1vZGVsLm5vZGUudHlwZSA9PT0gJ2h0bWwtdGVtcGxhdGUnICYmIG5vZGVIdG1sVGVtcGxhdGVcIlxuICBbYXR0ci53aWR0aF09XCJub2RlTW9kZWwuc2l6ZSgpLndpZHRoXCJcbiAgW2F0dHIuaGVpZ2h0XT1cIm5vZGVNb2RlbC5zaXplKCkuaGVpZ2h0XCJcbj5cbiAgPGRpdiAjaHRtbFdyYXBwZXIgY2xhc3M9XCJ3cmFwcGVyXCI+XG4gICAgPG5nLWNvbnRhaW5lclxuICAgICAgKm5nVGVtcGxhdGVPdXRsZXQ9XCJub2RlSHRtbFRlbXBsYXRlOyBjb250ZXh0OiB7ICRpbXBsaWNpdDogeyBub2RlOiBub2RlTW9kZWwubm9kZSB9ICB9XCJcbiAgICAvPlxuICA8L2Rpdj5cbjwvc3ZnOmZvcmVpZ25PYmplY3Q+XG5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJoYW5kbGVUZW1wbGF0ZVwiPlxuICA8c3ZnOmcgI3NvdXJjZUhhbmRsZSAobW91c2Vkb3duKT1cInN0YXJ0Q29ubmVjdGlvbigkZXZlbnQpXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImhhbmRsZVRlbXBsYXRlOyBjb250ZXh0OiBnZXRIYW5kbGVDb250ZXh0KCdzb3VyY2UnKVwiIC8+XG4gIDwvc3ZnOmc+XG5cbiAgPHN2ZzpnICN0YXJnZXRIYW5kbGU+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImhhbmRsZVRlbXBsYXRlOyBjb250ZXh0OiBnZXRIYW5kbGVDb250ZXh0KCd0YXJnZXQnKVwiIC8+XG4gIDwvc3ZnOmc+XG48L25nLWNvbnRhaW5lcj5cblxuPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFoYW5kbGVUZW1wbGF0ZVwiPlxuICA8c3ZnOmNpcmNsZVxuICAgICNzb3VyY2VIYW5kbGVcbiAgICBbYXR0ci5jeF09XCJub2RlTW9kZWwuc291cmNlT2Zmc2V0KCkueFwiXG4gICAgW2F0dHIuY3ldPVwibm9kZU1vZGVsLnNvdXJjZU9mZnNldCgpLnlcIlxuICAgIFthdHRyLnN0cm9rZS13aWR0aF09XCJkZWZhdWx0SGFuZGxlU3Ryb2tlV2lkdGhcIlxuICAgIHI9XCI1XCJcbiAgICBzdHJva2U9XCJ3aGl0ZVwiXG4gICAgZmlsbD1cImJsYWNrXCJcbiAgICAobW91c2Vkb3duKT1cInN0YXJ0Q29ubmVjdGlvbigkZXZlbnQpXCJcbiAgLz5cblxuICA8c3ZnOmNpcmNsZVxuICAgICN0YXJnZXRIYW5kbGVcbiAgICBbYXR0ci5jeF09XCJub2RlTW9kZWwudGFyZ2V0T2Zmc2V0KCkueFwiXG4gICAgW2F0dHIuY3ldPVwibm9kZU1vZGVsLnRhcmdldE9mZnNldCgpLnlcIlxuICAgIFthdHRyLnN0cm9rZS13aWR0aF09XCJkZWZhdWx0SGFuZGxlU3Ryb2tlV2lkdGhcIlxuICAgIHI9XCI1XCJcbiAgICBzdHJva2U9XCJ3aGl0ZVwiXG4gICAgZmlsbD1cImJsYWNrXCJcbiAgICAobW91c2V1cCk9XCJlbmRDb25uZWN0aW9uKClcIlxuICAvPlxuPC9uZy1jb250YWluZXI+XG5cbjxzdmc6Y2lyY2xlXG4gICpuZ0lmPVwic2hvd01hZ25ldCgpXCJcbiAgY2xhc3M9XCJtYWduZXRcIlxuICBbYXR0ci5yXT1cIm5vZGVNb2RlbC5tYWduZXRSYWRpdXNcIlxuICBbYXR0ci5jeF09XCJub2RlTW9kZWwudGFyZ2V0T2Zmc2V0KCkueFwiXG4gIFthdHRyLmN5XT1cIm5vZGVNb2RlbC50YXJnZXRPZmZzZXQoKS55XCJcbiAgKG1vdXNldXApPVwiZW5kQ29ubmVjdGlvbigpOyByZXNldFZhbGlkYXRlVGFyZ2V0SGFuZGxlKClcIlxuICAobW91c2VvdmVyKT1cInZhbGlkYXRlVGFyZ2V0SGFuZGxlKClcIlxuICAobW91c2VvdXQpPVwicmVzZXRWYWxpZGF0ZVRhcmdldEhhbmRsZSgpXCJcbi8+XG5cblxuIl19