@stocksharp/diagram 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/canvas-renderer.js +51 -6
- package/dist/esm/canvas-renderer.js.map +1 -1
- package/dist/esm/core/document.js +49 -0
- package/dist/esm/core/document.js.map +1 -1
- package/dist/esm/core/model.js +4 -0
- package/dist/esm/core/model.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/ssdiagram.js +83 -5
- package/dist/ssdiagram.js.map +2 -2
- package/dist/types/canvas-renderer.d.ts +9 -2
- package/dist/types/canvas-renderer.d.ts.map +1 -1
- package/dist/types/core/document.d.ts +1 -1
- package/dist/types/core/document.d.ts.map +1 -1
- package/dist/types/core/model.d.ts +35 -1
- package/dist/types/core/model.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/canvas-renderer.ts +58 -5
- package/src/core/document.ts +56 -0
- package/src/core/model.ts +41 -1
- package/src/index.ts +3 -0
|
@@ -143,11 +143,12 @@ export class NodeModel {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
export class LinkModel {
|
|
146
|
-
constructor(from, fromPort, to, toPort, id = '', metadata) {
|
|
146
|
+
constructor(from, fromPort, to, toPort, id = '', metadata, style = 'solid') {
|
|
147
147
|
this.from = from;
|
|
148
148
|
this.fromPort = fromPort;
|
|
149
149
|
this.to = to;
|
|
150
150
|
this.toPort = toPort;
|
|
151
|
+
this.style = style;
|
|
151
152
|
this.id = id;
|
|
152
153
|
this.metadata = copyJsonObject(metadata);
|
|
153
154
|
}
|
|
@@ -159,6 +160,7 @@ export class LinkModel {
|
|
|
159
160
|
fromPort: this.fromPort,
|
|
160
161
|
to: this.to,
|
|
161
162
|
toPort: this.toPort,
|
|
163
|
+
style: this.style,
|
|
162
164
|
metadata: copyJsonObject(this.metadata),
|
|
163
165
|
};
|
|
164
166
|
}
|
|
@@ -219,6 +221,7 @@ export class Diagram {
|
|
|
219
221
|
constructor(opts) {
|
|
220
222
|
this.nodes = [];
|
|
221
223
|
this.links = [];
|
|
224
|
+
this.zones = [];
|
|
222
225
|
this.idSeq = 1;
|
|
223
226
|
this.linkSeq = 1;
|
|
224
227
|
this.documentMetadata = {};
|
|
@@ -565,7 +568,7 @@ export class Diagram {
|
|
|
565
568
|
if (!validation.allowed)
|
|
566
569
|
return false;
|
|
567
570
|
}
|
|
568
|
-
const link = new LinkModel(init.from, init.fromPort, init.to, init.toPort, init.id ?? this.nextLinkId(), init.metadata);
|
|
571
|
+
const link = new LinkModel(init.from, init.fromPort, init.to, init.toPort, init.id ?? this.nextLinkId(), init.metadata, init.style ?? 'solid');
|
|
569
572
|
if (this.links.some((l) => l.id === link.id))
|
|
570
573
|
return false;
|
|
571
574
|
this.links.splice(clamp(Math.trunc(index), 0, this.links.length), 0, link);
|
|
@@ -975,7 +978,7 @@ export class Diagram {
|
|
|
975
978
|
if (this.links.some((existing) => existing.id === id)) {
|
|
976
979
|
throw new Error(`ssdiagram: duplicate link id "${id}"`);
|
|
977
980
|
}
|
|
978
|
-
const model = new LinkModel(link.from, link.fromPort, link.to, link.toPort, id, link.metadata);
|
|
981
|
+
const model = new LinkModel(link.from, link.fromPort, link.to, link.toPort, id, link.metadata, link.style ?? 'solid');
|
|
979
982
|
if (!this.links.some((existing) => existing.key() === model.key()))
|
|
980
983
|
this.links.push(model);
|
|
981
984
|
}
|
|
@@ -1007,8 +1010,10 @@ export class Diagram {
|
|
|
1007
1010
|
fromPort: link.from.portId,
|
|
1008
1011
|
to: link.to.nodeId,
|
|
1009
1012
|
toPort: link.to.portId,
|
|
1013
|
+
style: link.style,
|
|
1010
1014
|
metadata: link.metadata,
|
|
1011
1015
|
})));
|
|
1016
|
+
this.zones = document.zones.map((zone) => ({ ...zone, metadata: copyJsonObject(zone.metadata) }));
|
|
1012
1017
|
this.documentMetadata = copyJsonObject(document.metadata);
|
|
1013
1018
|
}
|
|
1014
1019
|
saveDocument() {
|
|
@@ -1018,8 +1023,10 @@ export class Diagram {
|
|
|
1018
1023
|
id: link.id,
|
|
1019
1024
|
from: { nodeId: link.from, portId: link.fromPort },
|
|
1020
1025
|
to: { nodeId: link.to, portId: link.toPort },
|
|
1026
|
+
style: link.style,
|
|
1021
1027
|
metadata: link.metadata,
|
|
1022
1028
|
})),
|
|
1029
|
+
zones: this.zones.map((zone) => ({ ...zone, metadata: copyJsonObject(zone.metadata) })),
|
|
1023
1030
|
metadata: this.documentMetadata,
|
|
1024
1031
|
});
|
|
1025
1032
|
}
|
|
@@ -2388,7 +2395,10 @@ export class Diagram {
|
|
|
2388
2395
|
if (options.grid)
|
|
2389
2396
|
this.drawGrid();
|
|
2390
2397
|
ctx.setTransform(this.dpr * this.scale, 0, 0, this.dpr * this.scale, this.dpr * this.offX, this.dpr * (this.offY + introDy));
|
|
2391
|
-
//
|
|
2398
|
+
// Zones sit under everything: they say where things are, and a place that painted over
|
|
2399
|
+
// its occupants would be worse than no place at all.
|
|
2400
|
+
this.drawZones();
|
|
2401
|
+
// Links next. Each link jumps over the verticals of the links
|
|
2392
2402
|
// drawn before it (deterministic bridge — Link.JumpOver parity).
|
|
2393
2403
|
const prior = []; // segments of links already drawn
|
|
2394
2404
|
const hoveredNode = this.hoverPort?.node ?? this.hoverNode;
|
|
@@ -2410,7 +2420,7 @@ export class Diagram {
|
|
|
2410
2420
|
const color = state === 'sel' ? this.selectionColor() : state === 'hov' ? this.linkHoverColor() : baseColor;
|
|
2411
2421
|
const width = state === 'sel' ? 3 : state === 'hov' ? 2.6 : 2;
|
|
2412
2422
|
const pts = this.routeLink(a, b, new Set([l.from, l.to]));
|
|
2413
|
-
this.strokeRoute(pts, color, width, prior);
|
|
2423
|
+
this.strokeRoute(pts, color, width, prior, l.style);
|
|
2414
2424
|
this.drawArrow(pts, color);
|
|
2415
2425
|
for (let k = 1; k < pts.length; k += 1) {
|
|
2416
2426
|
const [x1, y1] = pts[k - 1];
|
|
@@ -2577,6 +2587,37 @@ export class Diagram {
|
|
|
2577
2587
|
}
|
|
2578
2588
|
return lines.length > 0 ? lines : [''];
|
|
2579
2589
|
}
|
|
2590
|
+
drawZones() {
|
|
2591
|
+
if (this.zones.length === 0)
|
|
2592
|
+
return;
|
|
2593
|
+
const ctx = this.ctx;
|
|
2594
|
+
for (const zone of this.zones) {
|
|
2595
|
+
const tint = zone.color.length > 0 ? zone.color : (this.opts.zoneColor ?? '#8a8f98');
|
|
2596
|
+
ctx.save();
|
|
2597
|
+
roundRect(ctx, zone.x, zone.y, zone.width, zone.height, 10);
|
|
2598
|
+
ctx.globalAlpha = 0.12;
|
|
2599
|
+
ctx.fillStyle = tint;
|
|
2600
|
+
ctx.fill();
|
|
2601
|
+
ctx.globalAlpha = 0.5;
|
|
2602
|
+
ctx.setLineDash([10, 6]);
|
|
2603
|
+
ctx.lineWidth = 1.5;
|
|
2604
|
+
ctx.strokeStyle = tint;
|
|
2605
|
+
ctx.stroke();
|
|
2606
|
+
ctx.restore();
|
|
2607
|
+
if (zone.name.length === 0)
|
|
2608
|
+
continue;
|
|
2609
|
+
ctx.save();
|
|
2610
|
+
ctx.globalAlpha = 0.75;
|
|
2611
|
+
ctx.fillStyle = tint;
|
|
2612
|
+
ctx.font = '600 12px Segoe UI, Tahoma, sans-serif';
|
|
2613
|
+
ctx.textAlign = 'left';
|
|
2614
|
+
ctx.textBaseline = 'top';
|
|
2615
|
+
// Inside the top-left corner: a caption outside the box would collide with whatever
|
|
2616
|
+
// sits above it, and the corner is the one spot a rectangle always has to spare.
|
|
2617
|
+
ctx.fillText(zone.name, zone.x + 12, zone.y + 9, Math.max(0, zone.width - 24));
|
|
2618
|
+
ctx.restore();
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2580
2621
|
drawGrid() {
|
|
2581
2622
|
const ctx = this.ctx;
|
|
2582
2623
|
const step = this.gridSize * this.scale;
|
|
@@ -2718,10 +2759,13 @@ export class Diagram {
|
|
|
2718
2759
|
// Symmetric jump-over: any segment of THIS link hops the perpendicular
|
|
2719
2760
|
// segments of links drawn before it (H over earlier V, V over earlier
|
|
2720
2761
|
// H). Exactly one bridge per real crossing, consistent everywhere.
|
|
2721
|
-
strokeRoute(pts, color, width, prior) {
|
|
2762
|
+
strokeRoute(pts, color, width, prior, style = 'solid') {
|
|
2722
2763
|
const ctx = this.ctx;
|
|
2723
2764
|
ctx.strokeStyle = color;
|
|
2724
2765
|
ctx.lineWidth = width;
|
|
2766
|
+
// The dash is measured in world units, so it keeps its rhythm as the canvas is zoomed.
|
|
2767
|
+
if (style === 'dashed')
|
|
2768
|
+
ctx.setLineDash([9, 6]);
|
|
2725
2769
|
ctx.lineJoin = 'miter';
|
|
2726
2770
|
ctx.lineCap = 'butt';
|
|
2727
2771
|
ctx.beginPath();
|
|
@@ -2781,6 +2825,7 @@ export class Diagram {
|
|
|
2781
2825
|
}
|
|
2782
2826
|
}
|
|
2783
2827
|
ctx.stroke();
|
|
2828
|
+
ctx.setLineDash([]);
|
|
2784
2829
|
}
|
|
2785
2830
|
drawArrow(pts, color) {
|
|
2786
2831
|
const n = pts.length;
|