@visuallyjs/browser-ui-angular 1.2.0 → 1.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.
Files changed (55) hide show
  1. package/esm2022/index.mjs +6 -0
  2. package/esm2022/lib/background.component.mjs +38 -0
  3. package/esm2022/lib/base.group.component.mjs +3 -3
  4. package/esm2022/lib/base.node.component.mjs +3 -3
  5. package/esm2022/lib/base.port.component.mjs +4 -4
  6. package/esm2022/lib/base.vertex.component.mjs +33 -12
  7. package/esm2022/lib/browser-ui-angular.module.mjs +38 -8
  8. package/esm2022/lib/charts/area.chart.component.mjs +3 -3
  9. package/esm2022/lib/charts/bar.chart.component.mjs +3 -3
  10. package/esm2022/lib/charts/bubble.chart.component.mjs +3 -3
  11. package/esm2022/lib/charts/column.chart.component.mjs +3 -3
  12. package/esm2022/lib/charts/line.chart.component.mjs +3 -3
  13. package/esm2022/lib/charts/pie.chart.component.mjs +3 -3
  14. package/esm2022/lib/charts/sankey.chart.component.mjs +4 -4
  15. package/esm2022/lib/charts/scatter.chart.component.mjs +3 -3
  16. package/esm2022/lib/charts/series.based.chart.component.mjs +4 -4
  17. package/esm2022/lib/charts/xy.chart.component.mjs +3 -3
  18. package/esm2022/lib/color.tag.component.mjs +6 -6
  19. package/esm2022/lib/controls-component.mjs +4 -4
  20. package/esm2022/lib/decorator-component.mjs +3 -3
  21. package/esm2022/lib/default-group-component.mjs +3 -3
  22. package/esm2022/lib/default-node-component.mjs +3 -3
  23. package/esm2022/lib/diagram-component.mjs +34 -12
  24. package/esm2022/lib/diagram-palette-component.mjs +4 -4
  25. package/esm2022/lib/edge.type.picker.component.mjs +5 -5
  26. package/esm2022/lib/export-controls-component.mjs +3 -3
  27. package/esm2022/lib/grid-background.component.mjs +77 -0
  28. package/esm2022/lib/image-background.component.mjs +38 -0
  29. package/esm2022/lib/inspector.component.mjs +4 -4
  30. package/esm2022/lib/miniview-component.mjs +4 -4
  31. package/esm2022/lib/overlay-component.mjs +52 -1
  32. package/esm2022/lib/palette.component.mjs +4 -4
  33. package/esm2022/lib/paper-component.mjs +354 -0
  34. package/esm2022/lib/shape.component.mjs +4 -4
  35. package/esm2022/lib/shape.palette.component.mjs +4 -4
  36. package/esm2022/lib/surface-component.mjs +87 -16
  37. package/esm2022/lib/surface-popup-component.mjs +62 -0
  38. package/esm2022/lib/tiled-image-background.component.mjs +62 -0
  39. package/esm2022/lib/vjs-service.mjs +3 -3
  40. package/fesm2022/visuallyjs-browser-ui-angular.mjs +938 -144
  41. package/fesm2022/visuallyjs-browser-ui-angular.mjs.map +1 -1
  42. package/index.d.ts +6 -0
  43. package/lib/background.component.d.ts +13 -0
  44. package/lib/base.vertex.component.d.ts +29 -3
  45. package/lib/browser-ui-angular.module.d.ts +27 -21
  46. package/lib/diagram-component.d.ts +7 -5
  47. package/lib/grid-background.component.d.ts +81 -0
  48. package/lib/image-background.component.d.ts +18 -0
  49. package/lib/overlay-component.d.ts +32 -8
  50. package/lib/paper-component.d.ts +162 -0
  51. package/lib/surface-component.d.ts +25 -11
  52. package/lib/surface-popup-component.d.ts +62 -0
  53. package/lib/tiled-image-background.component.d.ts +72 -0
  54. package/package.json +2 -2
  55. package/visuallyjs-browser-ui-angular.tgz +0 -0
@@ -0,0 +1,354 @@
1
+ import { Component, ElementRef, EventEmitter, Input, NgZone, Output, ViewContainerRef, inject, reflectComponentType, input, effect } from "@angular/core";
2
+ import { EVENT_EDGE_UPDATED, EVENT_GROUP_UPDATED, EVENT_NODE_UPDATED, EVENT_PORT_ADDED, EVENT_PORT_UPDATED, extend, renderPaper, OVERLAY_TYPE_CUSTOM, isGroup, EVENT_INTERNAL_CONNECTION, EVENT_DATA_LOAD_END, ELEMENT_DIV, EVENT_EDGE_REMOVED, EVENT_EDGE_ADDED } from "@visuallyjs/browser-ui";
3
+ import { AngularComponentOverlayType, } from "./overlay-component";
4
+ import { DefaultGroupComponent } from "./default-group-component";
5
+ import { DefaultNodeComponent } from "./default-node-component";
6
+ import { BasePortComponent } from "./base.port.component";
7
+ import { VisuallyJsService } from "./vjs-service";
8
+ import { BrowserUIAngularModel } from "./model";
9
+ import * as i0 from "@angular/core";
10
+
11
+ export class PaperComponent {
12
+ constructor() {
13
+
14
+ this.data = input();
15
+
16
+ this.url = input();
17
+
18
+ this.vertexEvent = new EventEmitter();
19
+ this.$el = inject(ElementRef);
20
+ this.$viewContainerRef = inject(ViewContainerRef);
21
+ this.$ngZone = inject(NgZone);
22
+ this.$vjs = inject(VisuallyJsService);
23
+ this._dataEffect = effect(() => {
24
+ const currentData = this.data();
25
+ if (currentData) {
26
+ if (this.model) {
27
+ this.model.clear();
28
+ this.model.load({ data: currentData });
29
+ }
30
+ }
31
+ });
32
+ this._urlEffect = effect(() => {
33
+ const currentUrl = this.url();
34
+ if (currentUrl) {
35
+ // Respond to changes in the url here.
36
+ // For example, if you need to reload the model with new data:
37
+ if (this.model) {
38
+ this.model.clear();
39
+ this.model.load({ url: currentUrl });
40
+ }
41
+ }
42
+ });
43
+ }
44
+
45
+ getNativeElement(component) {
46
+ return component.location.nativeElement.childNodes[0];
47
+ }
48
+ _getComponent(el, tryParent) {
49
+ if (el == null) {
50
+ return null;
51
+ }
52
+ else {
53
+ let vjc = el._visuallyJsNgComponent;
54
+ if (vjc == null && tryParent && el.parentNode != null) {
55
+ vjc = el.parentNode._visuallyJsNgComponent;
56
+ }
57
+ return vjc;
58
+ }
59
+ }
60
+ _getComponentThen(el, then, tryParent) {
61
+ const c = this._getComponent(el, tryParent);
62
+ if (c != null) {
63
+ then(c);
64
+ }
65
+ }
66
+
67
+ nodeOrGroupUpdated(params) {
68
+ const info = this.paper.getObjectInfo(params.vertex, false);
69
+ this._getComponentThen(info.el, (component) => {
70
+ component.data = params.vertex.data;
71
+ component.$data?.set(component.data);
72
+ if (component.changeDetectorRef) {
73
+ component.changeDetectorRef.detectChanges();
74
+ }
75
+ }, false);
76
+ this._maybeUpdateEdgeOverlays(params.vertex);
77
+ }
78
+ portUpdated(params) {
79
+ const info = this.paper.getObjectInfo(params.port, false);
80
+ this._getComponentThen(info.el, (component) => {
81
+ if (component instanceof BasePortComponent) {
82
+ component.data = params.port.data;
83
+ if (component.changeDetectorRef) {
84
+ component.changeDetectorRef.detectChanges();
85
+ }
86
+ }
87
+ }, true);
88
+ this._maybeUpdateEdgeOverlays(params.port);
89
+ }
90
+ _maybeUpdateEdgeOverlays(vertex) {
91
+ vertex.getAllEdges().forEach(e => this._handleEdgeUpdate(e.id));
92
+ }
93
+
94
+ _handleEdgeUpdate(edgeId) {
95
+ const connection = this.paper.getRenderedConnection(edgeId);
96
+ if (connection) {
97
+ for (let id in connection.overlays) {
98
+ const canvas = connection.overlays[id].contentElement;
99
+ this._getComponentThen(canvas, (component) => {
100
+ if (component.changeDetectorRef != null) {
101
+ component.changeDetectorRef.detectChanges();
102
+ }
103
+ }, false);
104
+ }
105
+ }
106
+ }
107
+
108
+ edgeUpdated(params) {
109
+ this._handleEdgeUpdate(params.edge.id);
110
+ }
111
+ edgeAddedRemoved(params) {
112
+ const info = this.paper.getObjectInfo(params.edge.source, false);
113
+ if (info.el) {
114
+ this._getComponentThen(info.el, (component) => {
115
+ try {
116
+ ;
117
+ component.$updateEdges();
118
+ if (component.changeDetectorRef) {
119
+ component.changeDetectorRef.detectChanges();
120
+ }
121
+ }
122
+ catch (e) { }
123
+ }, false);
124
+ }
125
+ const info2 = this.paper.getObjectInfo(params.edge.target, false);
126
+ if (info2.el && info.obj.getFullId() !== info2.obj.getFullId()) {
127
+ this._getComponentThen(info2.el, (component) => {
128
+ try {
129
+ ;
130
+ component.$updateEdges();
131
+ // tslint:disable-next-line:align
132
+ if (component.changeDetectorRef) {
133
+ component.changeDetectorRef.detectChanges();
134
+ }
135
+ }
136
+ catch (e) { }
137
+ }, false);
138
+ }
139
+ }
140
+
141
+ _processAngularOverlays(view) {
142
+ const self = this;
143
+ const edgeTypes = view.edges || {};
144
+ for (let edgeTypeId in edgeTypes) {
145
+ const edgeType = edgeTypes[edgeTypeId];
146
+ if (edgeType.overlays != null) {
147
+ edgeType.overlays = edgeType.overlays.map((o) => {
148
+ if (typeof o === "string") {
149
+ return o;
150
+ }
151
+ else {
152
+ const fo = o;
153
+ if (fo.type === AngularComponentOverlayType) {
154
+ const newSpec = Object.assign(fo, {
155
+ type: OVERLAY_TYPE_CUSTOM,
156
+ });
157
+ newSpec.options = (newSpec.options || {});
158
+ newSpec.options.create = (connection) => {
159
+ const el = document.createElement(ELEMENT_DIV);
160
+ let createdComponent = self.$viewContainerRef.createComponent(newSpec.options.component);
161
+ let angularOverlayComponent = createdComponent.instance;
162
+ let nativeEl = createdComponent.location.nativeElement.childNodes[0];
163
+ el.appendChild(nativeEl);
164
+ el._visuallyJsNgComponent = angularOverlayComponent;
165
+
166
+ if (connection != null) {
167
+ const edge = connection.edge;
168
+ angularOverlayComponent.edge = edge;
169
+ angularOverlayComponent.data = edge.data;
170
+ }
171
+ angularOverlayComponent.model = self.model;
172
+ angularOverlayComponent.ui = self.paper;
173
+ createdComponent.changeDetectorRef.detectChanges();
174
+ return el;
175
+ };
176
+ return newSpec;
177
+ }
178
+ else {
179
+ return fo;
180
+ }
181
+ }
182
+ });
183
+ }
184
+ }
185
+ return view;
186
+ }
187
+
188
+ save(options) {
189
+ this.paper.save(options);
190
+ }
191
+
192
+ exportData(options) {
193
+ return this.paper.model.exportData(options);
194
+ }
195
+
196
+ dataLoadEnd() {
197
+ setTimeout(() => {
198
+ if (this.paper != null) {
199
+ this.paper.repaintEverything();
200
+ }
201
+ }, 0);
202
+ }
203
+ $removeNgElement(el) {
204
+ if (el._ref != null) {
205
+ el._ref.destroy();
206
+ }
207
+ if (el.parentNode != null) {
208
+ el.parentNode.removeChild(el);
209
+ }
210
+ }
211
+
212
+ ngAfterViewInit() {
213
+ this.$ngZone.runOutsideAngular(() => {
214
+ const view = this._processAngularOverlays(this.viewOptions || {});
215
+ const self = this;
216
+ this.renderOptions = this.renderOptions || {};
217
+ const render = (directiveId, data, instance, objectType, paper, def, modelObject, eventInfo) => {
218
+ let component;
219
+ if (def.component == null) {
220
+ if (isGroup(modelObject)) {
221
+ component = DefaultGroupComponent;
222
+ }
223
+ else {
224
+ component = DefaultNodeComponent;
225
+ }
226
+ }
227
+ else {
228
+ component = def.component;
229
+ }
230
+ let createdComponent = self.$viewContainerRef.createComponent(component);
231
+ let _componentRef = createdComponent.instance;
232
+ _componentRef.data = data || {};
233
+ _componentRef.model = model;
234
+ _componentRef.paper = paper;
235
+ _componentRef.ui = paper;
236
+ _componentRef.modelObject = modelObject;
237
+ // get the reflection data for the component
238
+ const componentInfo = reflectComponentType(component);
239
+ // ..and populate any declared inputs from data
240
+ componentInfo.inputs.forEach((pt) => {
241
+ const pv = _componentRef.data[pt.propName];
242
+ if (pv != null) {
243
+ _componentRef[pt.propName] = pv;
244
+ }
245
+ });
246
+ // map to any outputs
247
+ componentInfo.outputs.forEach((pt) => {
248
+ _componentRef[pt.propName].subscribe((d) => self.vertexEvent.emit({
249
+ vertex: modelObject,
250
+ event: pt.propName,
251
+ payload: d,
252
+ component: createdComponent,
253
+ }));
254
+ });
255
+ // if angular def has 'inputs' set, set them on the component. this is different to the mechanism above, in which values are extracted from
256
+ // each node's backing data. here we inject values either as a string or from some arbitrary function.
257
+ if (def.inputs != null) {
258
+ for (let k in def.inputs) {
259
+ const v = def.inputs[k];
260
+ const value = typeof v === "string" ? v : v(modelObject);
261
+ _componentRef[k] = value;
262
+ }
263
+ }
264
+ createdComponent.changeDetectorRef.detectChanges();
265
+ // TODO this should not be necessary
266
+ const nativeElement = self.getNativeElement(createdComponent);
267
+ _componentRef._el = nativeElement;
268
+ _componentRef._el._visuallyJsNgComponent = _componentRef;
269
+ _componentRef._el._ref = createdComponent; // we store _ref so we can call `destroy` on it later if the node is removed.
270
+ paper.$vertexRendered(modelObject, nativeElement, def, eventInfo);
271
+ };
272
+ const templateRenderer = {
273
+ asynchronous: false,
274
+ reactive: true,
275
+ usesWrapperElement: false,
276
+ update: (el, data, v, renderer) => { },
277
+ render,
278
+ rerender: (directiveId, data, instance, objectType, paper, def, modelObject, eventInfo, originalElement) => {
279
+ this.$removeNgElement(originalElement);
280
+ render(directiveId, data, instance, objectType, paper, def, modelObject, eventInfo);
281
+ },
282
+ cleanupVertex: (objId, el) => {
283
+ this.$removeNgElement(el);
284
+ },
285
+ cleanupPort: (objId, el) => {
286
+ this.$removeNgElement(el);
287
+ },
288
+ };
289
+ const renderParams = extend(this.renderOptions || {}, {
290
+ view: view,
291
+ });
292
+ let model = this.inputModel || new BrowserUIAngularModel(this.modelOptions);
293
+ this.model = model;
294
+ this.paper = renderPaper(model, self.$el.nativeElement, templateRenderer, renderParams);
295
+ this.$vjs.$setPaper(this.paper);
296
+ // ----------------
297
+ this.nodeUpdateFn = this.nodeOrGroupUpdated.bind(this);
298
+ model.bind(EVENT_NODE_UPDATED, this.nodeUpdateFn);
299
+ model.bind(EVENT_PORT_ADDED, this.nodeUpdateFn);
300
+ model.bind(EVENT_GROUP_UPDATED, this.nodeUpdateFn);
301
+ this.dataLoadEndFn = this.dataLoadEnd.bind(this);
302
+ model.bind(EVENT_DATA_LOAD_END, this.dataLoadEndFn);
303
+ this.portUpdateFn = this.portUpdated.bind(this);
304
+ model.bind(EVENT_PORT_UPDATED, this.portUpdateFn);
305
+ this.edgeUpdateFn = this.edgeUpdated.bind(this);
306
+ model.bind(EVENT_EDGE_UPDATED, this.edgeUpdateFn);
307
+ this.edgeAddFn = this.edgeAddedRemoved.bind(this);
308
+ this.edgeRemoveFn = this.edgeAddedRemoved.bind(this);
309
+ model.bind(EVENT_EDGE_ADDED, this.edgeAddFn);
310
+ model.bind(EVENT_EDGE_REMOVED, this.edgeRemoveFn);
311
+ const initialData = this.data();
312
+ const initialUrl = this.url();
313
+ if (initialData) {
314
+ this.model.load({ data: initialData });
315
+ }
316
+ else if (initialUrl) {
317
+ this.model.load({ url: initialUrl });
318
+ }
319
+ });
320
+ }
321
+
322
+ ngOnDestroy() {
323
+ this.paper.destroy();
324
+ this.model.unbind(EVENT_NODE_UPDATED, this.nodeUpdateFn);
325
+ this.model.unbind(EVENT_GROUP_UPDATED, this.nodeUpdateFn);
326
+ this.model.unbind(EVENT_PORT_ADDED, this.nodeUpdateFn);
327
+ this.model.unbind(EVENT_PORT_UPDATED, this.portUpdateFn);
328
+ this.model.unbind(EVENT_EDGE_UPDATED, this.edgeUpdateFn);
329
+ this.model.unbind(EVENT_EDGE_ADDED, this.edgeAddFn);
330
+ this.model.unbind(EVENT_EDGE_REMOVED, this.edgeRemoveFn);
331
+ this.model.unbind(EVENT_DATA_LOAD_END, this.dataLoadEndFn);
332
+ this.paper.unbind(EVENT_INTERNAL_CONNECTION, this.edgeAddFn);
333
+ }
334
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PaperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
335
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: PaperComponent, selector: "vjs-paper", inputs: { inputModel: { classPropertyName: "inputModel", publicName: "model", isSignal: false, isRequired: false, transformFunction: null }, viewOptions: { classPropertyName: "viewOptions", publicName: "viewOptions", isSignal: false, isRequired: false, transformFunction: null }, renderOptions: { classPropertyName: "renderOptions", publicName: "renderOptions", isSignal: false, isRequired: false, transformFunction: null }, modelOptions: { classPropertyName: "modelOptions", publicName: "modelOptions", isSignal: false, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { vertexEvent: "vertexEvent" }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
336
+ }
337
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PaperComponent, decorators: [{
338
+ type: Component,
339
+ args: [{
340
+ selector: "vjs-paper",
341
+ template: `<ng-content></ng-content>`
342
+ }]
343
+ }], propDecorators: { inputModel: [{
344
+ type: Input,
345
+ args: [{ alias: "model" }]
346
+ }], viewOptions: [{
347
+ type: Input
348
+ }], renderOptions: [{
349
+ type: Input
350
+ }], modelOptions: [{
351
+ type: Input
352
+ }], vertexEvent: [{
353
+ type: Output
354
+ }] } });
@@ -41,8 +41,8 @@ export class ShapeComponent {
41
41
  ngOnChanges(changes) {
42
42
  this._render();
43
43
  }
44
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShapeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
45
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ShapeComponent, selector: "vjs-shape", inputs: { obj: "obj", width: "width", height: "height", showLabels: "showLabels", labelProperty: "labelProperty", labelStrokeWidth: "labelStrokeWidth", label: "label", multilineLabels: "multilineLabels", labelFillRatio: "labelFillRatio", font: "font" }, usesOnChanges: true, ngImport: i0, template: `<svg:svg
44
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShapeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
45
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ShapeComponent, selector: "vjs-shape", inputs: { obj: "obj", width: "width", height: "height", showLabels: "showLabels", labelProperty: "labelProperty", labelStrokeWidth: "labelStrokeWidth", label: "label", multilineLabels: "multilineLabels", labelFillRatio: "labelFillRatio", font: "font" }, usesOnChanges: true, ngImport: i0, template: `<svg:svg
46
46
  [attr.stroke-width]="obj.outlineWidth || 2"
47
47
  attr.fill="{{ obj.fill }}"
48
48
  attr.stroke="{{ obj.outline }}"
@@ -51,7 +51,7 @@ export class ShapeComponent {
51
51
  attr.viewBox="0 0 {{ width }} {{ height }}"
52
52
  ></svg:svg>`, isInline: true }); }
53
53
  }
54
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShapeComponent, decorators: [{
54
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShapeComponent, decorators: [{
55
55
  type: Component,
56
56
  args: [{
57
57
  template: `<svg:svg
@@ -64,7 +64,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
64
64
  ></svg:svg>`,
65
65
  selector: `vjs-shape`,
66
66
  }]
67
- }], ctorParameters: function () { return []; }, propDecorators: { obj: [{
67
+ }], ctorParameters: () => [], propDecorators: { obj: [{
68
68
  type: Input
69
69
  }], width: [{
70
70
  type: Input
@@ -48,16 +48,16 @@ export class ShapePaletteComponent {
48
48
  }
49
49
  });
50
50
  }
51
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShapePaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
52
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ShapePaletteComponent, selector: "vjs-shape-palette", inputs: { initialSet: "initialSet", dragSize: "dragSize", iconSize: "iconSize", fill: "fill", outline: "outline", showAllMessage: "showAllMessage", selectAfterDrop: "selectAfterDrop", paletteStrokeWidth: "paletteStrokeWidth", onVertexAdded: "onVertexAdded", dataGenerator: "dataGenerator", preparedShapes: "preparedShapes" }, ngImport: i0, template: `<div></div>`, isInline: true }); }
51
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShapePaletteComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
52
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ShapePaletteComponent, selector: "vjs-shape-palette", inputs: { initialSet: "initialSet", dragSize: "dragSize", iconSize: "iconSize", fill: "fill", outline: "outline", showAllMessage: "showAllMessage", selectAfterDrop: "selectAfterDrop", paletteStrokeWidth: "paletteStrokeWidth", onVertexAdded: "onVertexAdded", dataGenerator: "dataGenerator", preparedShapes: "preparedShapes" }, ngImport: i0, template: `<div></div>`, isInline: true }); }
53
53
  }
54
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ShapePaletteComponent, decorators: [{
54
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ShapePaletteComponent, decorators: [{
55
55
  type: Component,
56
56
  args: [{
57
57
  template: `<div></div>`,
58
58
  selector: `vjs-shape-palette`
59
59
  }]
60
- }], ctorParameters: function () { return []; }, propDecorators: { initialSet: [{
60
+ }], ctorParameters: () => [], propDecorators: { initialSet: [{
61
61
  type: Input
62
62
  }], dragSize: [{
63
63
  type: Input
@@ -1,5 +1,5 @@
1
- import { Component, ElementRef, EventEmitter, Input, NgZone, Output, ViewContainerRef, inject, reflectComponentType } from "@angular/core";
2
- import { EVENT_EDGE_UPDATED, EVENT_GROUP_UPDATED, EVENT_NODE_UPDATED, EVENT_PORT_ADDED, EVENT_PORT_UPDATED, extend, renderSurface, OVERLAY_TYPE_CUSTOM, isGroup, EVENT_INTERNAL_CONNECTION, EVENT_DATA_LOAD_END, ELEMENT_DIV } from "@visuallyjs/browser-ui";
1
+ import { Component, ElementRef, EventEmitter, Input, NgZone, Output, ViewContainerRef, inject, reflectComponentType, input, effect } from "@angular/core";
2
+ import { EVENT_EDGE_UPDATED, EVENT_GROUP_UPDATED, EVENT_NODE_UPDATED, EVENT_PORT_ADDED, EVENT_PORT_UPDATED, extend, renderSurface, OVERLAY_TYPE_CUSTOM, isGroup, EVENT_INTERNAL_CONNECTION, EVENT_DATA_LOAD_END, ELEMENT_DIV, EVENT_EDGE_REMOVED, EVENT_EDGE_ADDED } from "@visuallyjs/browser-ui";
3
3
  import { AngularComponentOverlayType, } from "./overlay-component";
4
4
  import { DefaultGroupComponent } from "./default-group-component";
5
5
  import { DefaultNodeComponent } from "./default-node-component";
@@ -11,13 +11,36 @@ import * as i0 from "@angular/core";
11
11
  export class SurfaceComponent {
12
12
  constructor() {
13
13
 
14
+ this.data = input();
15
+
16
+ this.url = input();
17
+
14
18
  this.vertexEvent = new EventEmitter();
15
19
  this.$el = inject(ElementRef);
16
20
  this.$viewContainerRef = inject(ViewContainerRef);
17
21
  this.$ngZone = inject(NgZone);
18
22
  this.$vjs = inject(VisuallyJsService);
23
+ this._dataEffect = effect(() => {
24
+ const currentData = this.data();
25
+ if (currentData) {
26
+ if (this.model) {
27
+ this.model.clear();
28
+ this.model.load({ data: currentData });
29
+ }
30
+ }
31
+ });
32
+ this._urlEffect = effect(() => {
33
+ const currentUrl = this.url();
34
+ if (currentUrl) {
35
+ // Respond to changes in the url here.
36
+ // For example, if you need to reload the model with new data:
37
+ if (this.model) {
38
+ this.model.clear();
39
+ this.model.load({ url: currentUrl });
40
+ }
41
+ }
42
+ });
19
43
  }
20
- // $vjsSignals = inject(VisuallyJsSignalService)
21
44
 
22
45
  getNativeElement(component) {
23
46
  return component.location.nativeElement.childNodes[0];
@@ -46,10 +69,16 @@ export class SurfaceComponent {
46
69
  this._getComponentThen(info.el, (component) => {
47
70
  component.data = params.vertex.data;
48
71
  component.$data?.set(component.data);
72
+ try {
73
+ ;
74
+ component.$updateEdges();
75
+ }
76
+ catch (e) { }
49
77
  if (component.changeDetectorRef) {
50
78
  component.changeDetectorRef.detectChanges();
51
79
  }
52
80
  }, false);
81
+ this._maybeUpdateEdgeOverlays(params.vertex);
53
82
  }
54
83
  portUpdated(params) {
55
84
  const info = this.surface.getObjectInfo(params.port, false);
@@ -61,10 +90,14 @@ export class SurfaceComponent {
61
90
  }
62
91
  }
63
92
  }, true);
93
+ this._maybeUpdateEdgeOverlays(params.port);
94
+ }
95
+ _maybeUpdateEdgeOverlays(vertex) {
96
+ vertex.getAllEdges().forEach(e => this._handleEdgeUpdate(e.id));
64
97
  }
65
98
 
66
- edgeUpdated(params) {
67
- const connection = this.surface.getRenderedConnection(params.edge.id);
99
+ _handleEdgeUpdate(edgeId) {
100
+ const connection = this.surface.getRenderedConnection(edgeId);
68
101
  if (connection) {
69
102
  for (let id in connection.overlays) {
70
103
  const canvas = connection.overlays[id].contentElement;
@@ -77,6 +110,36 @@ export class SurfaceComponent {
77
110
  }
78
111
  }
79
112
 
113
+ edgeUpdated(params) {
114
+ this._handleEdgeUpdate(params.edge.id);
115
+ }
116
+ edgeAddedRemoved(params) {
117
+ const info = this.surface.getObjectInfo(params.edge.source, false);
118
+ if (info.el) {
119
+ this._getComponentThen(info.el, (component) => {
120
+ try {
121
+ component.$updateEdges();
122
+ if (component.changeDetectorRef) {
123
+ component.changeDetectorRef.detectChanges();
124
+ }
125
+ }
126
+ catch (e) { }
127
+ }, false);
128
+ }
129
+ const info2 = this.surface.getObjectInfo(params.edge.target, false);
130
+ if (info2.el && info.obj.getFullId() !== info2.obj.getFullId()) {
131
+ this._getComponentThen(info2.el, (component) => {
132
+ try {
133
+ component.$updateEdges();
134
+ if (component.changeDetectorRef) {
135
+ component.changeDetectorRef.detectChanges();
136
+ }
137
+ }
138
+ catch (e) { }
139
+ }, false);
140
+ }
141
+ }
142
+
80
143
  _processAngularOverlays(view) {
81
144
  const self = this;
82
145
  const edgeTypes = view.edges || {};
@@ -108,7 +171,10 @@ export class SurfaceComponent {
108
171
  angularOverlayComponent.data = edge.data;
109
172
  }
110
173
  angularOverlayComponent.model = self.model;
174
+ // backwards compat: remove at some point
175
+ ;
111
176
  angularOverlayComponent.surface = self.surface;
177
+ angularOverlayComponent.ui = self.surface;
112
178
  createdComponent.changeDetectorRef.detectChanges();
113
179
  return el;
114
180
  };
@@ -171,6 +237,7 @@ export class SurfaceComponent {
171
237
  _componentRef.data = data || {};
172
238
  _componentRef.model = model;
173
239
  _componentRef.surface = surface;
240
+ _componentRef.ui = surface;
174
241
  _componentRef.modelObject = modelObject;
175
242
  // get the reflection data for the component
176
243
  const componentInfo = reflectComponentType(component);
@@ -242,11 +309,17 @@ export class SurfaceComponent {
242
309
  model.bind(EVENT_PORT_UPDATED, this.portUpdateFn);
243
310
  this.edgeUpdateFn = this.edgeUpdated.bind(this);
244
311
  model.bind(EVENT_EDGE_UPDATED, this.edgeUpdateFn);
245
- if (this.data) {
246
- this.model.load({ data: this.data });
312
+ this.edgeAddFn = this.edgeAddedRemoved.bind(this);
313
+ this.edgeRemoveFn = this.edgeAddedRemoved.bind(this);
314
+ model.bind(EVENT_EDGE_ADDED, this.edgeAddFn);
315
+ model.bind(EVENT_EDGE_REMOVED, this.edgeRemoveFn);
316
+ const initialData = this.data();
317
+ const initialUrl = this.url();
318
+ if (initialData) {
319
+ this.model.load({ data: initialData });
247
320
  }
248
- else if (this.url) {
249
- this.model.load({ url: this.url });
321
+ else if (initialUrl) {
322
+ this.model.load({ url: initialUrl });
250
323
  }
251
324
  });
252
325
  }
@@ -258,13 +331,15 @@ export class SurfaceComponent {
258
331
  this.model.unbind(EVENT_PORT_ADDED, this.nodeUpdateFn);
259
332
  this.model.unbind(EVENT_PORT_UPDATED, this.portUpdateFn);
260
333
  this.model.unbind(EVENT_EDGE_UPDATED, this.edgeUpdateFn);
334
+ this.model.unbind(EVENT_EDGE_ADDED, this.edgeAddFn);
335
+ this.model.unbind(EVENT_EDGE_REMOVED, this.edgeRemoveFn);
261
336
  this.model.unbind(EVENT_DATA_LOAD_END, this.dataLoadEndFn);
262
337
  this.surface.unbind(EVENT_INTERNAL_CONNECTION, this.edgeAddFn);
263
338
  }
264
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SurfaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
265
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: SurfaceComponent, selector: "vjs-surface", inputs: { inputModel: ["model", "inputModel"], viewOptions: "viewOptions", renderOptions: "renderOptions", modelOptions: "modelOptions", data: "data", url: "url" }, outputs: { vertexEvent: "vertexEvent" }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
339
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SurfaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
340
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "17.3.12", type: SurfaceComponent, selector: "vjs-surface", inputs: { inputModel: { classPropertyName: "inputModel", publicName: "model", isSignal: false, isRequired: false, transformFunction: null }, viewOptions: { classPropertyName: "viewOptions", publicName: "viewOptions", isSignal: false, isRequired: false, transformFunction: null }, renderOptions: { classPropertyName: "renderOptions", publicName: "renderOptions", isSignal: false, isRequired: false, transformFunction: null }, modelOptions: { classPropertyName: "modelOptions", publicName: "modelOptions", isSignal: false, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, url: { classPropertyName: "url", publicName: "url", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { vertexEvent: "vertexEvent" }, ngImport: i0, template: `<ng-content></ng-content>`, isInline: true }); }
266
341
  }
267
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: SurfaceComponent, decorators: [{
342
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SurfaceComponent, decorators: [{
268
343
  type: Component,
269
344
  args: [{
270
345
  selector: "vjs-surface",
@@ -279,10 +354,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
279
354
  type: Input
280
355
  }], modelOptions: [{
281
356
  type: Input
282
- }], data: [{
283
- type: Input
284
- }], url: [{
285
- type: Input
286
357
  }], vertexEvent: [{
287
358
  type: Output
288
359
  }] } });
@@ -0,0 +1,62 @@
1
+ import { Component, Input, ContentChild, TemplateRef, ViewChild, inject, signal, computed, ChangeDetectorRef } from "@angular/core";
2
+ import { PopupHandler, CLASS_SURFACE_POPUP } from "@visuallyjs/browser-ui";
3
+ import { VisuallyJsService } from "./vjs-service";
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "@angular/common";
6
+
7
+ export class SurfacePopupComponent {
8
+ constructor() {
9
+ this.cdr = inject(ChangeDetectorRef);
10
+ this.vjs = inject(VisuallyJsService);
11
+ this.initialized = false;
12
+ this.current = signal(null);
13
+ this.model = this.vjs.model;
14
+ this.ui = this.vjs.ui;
15
+ this.display = computed(() => (this.current() == null ? "none" : "block"));
16
+ }
17
+ ngAfterViewInit() {
18
+ this._hideFunction = function () {
19
+ this.popupHandler?.$hide();
20
+ }.bind(this);
21
+ this.vjs.getSurface((surface) => {
22
+ if (!this.initialized) {
23
+ this.initialized = true;
24
+ this.popupHandler = new PopupHandler(this.selector, this.container.nativeElement, surface, (v) => {
25
+ this.current.set(v);
26
+ requestAnimationFrame(() => this.cdr.detectChanges());
27
+ }, this.anchor);
28
+ }
29
+ });
30
+ }
31
+ ngOnDestroy() {
32
+ if (this.popupHandler) {
33
+ this.popupHandler.$destroy();
34
+ }
35
+ }
36
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SurfacePopupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
37
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: SurfacePopupComponent, selector: "vjs-surface-popup", inputs: { selector: "selector", anchor: "anchor" }, queries: [{ propertyName: "template", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: "\n <div #container class=\"vjs-surface-popup\" [style.display]=\"display()\" style=\"position:absolute\">\n <ng-container *ngIf=\"current()\">\n <ng-container *ngTemplateOutlet=\"template; context: { vertex: current(), model: model(), ui: ui(), hide:_hideFunction }\"></ng-container>\n </ng-container>\n </div>\n ", 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"] }] }); }
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: SurfacePopupComponent, decorators: [{
40
+ type: Component,
41
+ args: [{
42
+ selector: "vjs-surface-popup",
43
+ template: `
44
+ <div #container class="${CLASS_SURFACE_POPUP}" [style.display]="display()" style="position:absolute">
45
+ <ng-container *ngIf="current()">
46
+ <ng-container *ngTemplateOutlet="template; context: { vertex: current(), model: model(), ui: ui(), hide:_hideFunction }"></ng-container>
47
+ </ng-container>
48
+ </div>
49
+ `
50
+ }]
51
+ }], propDecorators: { selector: [{
52
+ type: Input,
53
+ args: [{ required: true }]
54
+ }], anchor: [{
55
+ type: Input
56
+ }], template: [{
57
+ type: ContentChild,
58
+ args: [TemplateRef]
59
+ }], container: [{
60
+ type: ViewChild,
61
+ args: ["container"]
62
+ }] } });