@spectratools/graphic-designer-cli 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +158 -116
- package/dist/index.d.ts +44 -4
- package/dist/index.js +162 -66
- package/dist/qa.d.ts +1 -1
- package/dist/qa.js +29 -7
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +158 -116
- package/dist/{spec.schema-B6sXTTou.d.ts → spec.schema-CYlOLxmK.d.ts} +1395 -1221
- package/dist/spec.schema.d.ts +1 -1
- package/dist/spec.schema.js +29 -7
- package/package.json +1 -1
package/dist/renderer.js
CHANGED
|
@@ -1366,12 +1366,12 @@ var MACOS_DOTS = [
|
|
|
1366
1366
|
{ fill: "#27C93F", stroke: "#1AAB29" }
|
|
1367
1367
|
];
|
|
1368
1368
|
function drawMacosDots(ctx, x, y) {
|
|
1369
|
-
for (const [index,
|
|
1369
|
+
for (const [index, dot] of MACOS_DOTS.entries()) {
|
|
1370
1370
|
ctx.beginPath();
|
|
1371
1371
|
ctx.arc(x + index * DOT_SPACING, y, DOT_RADIUS, 0, Math.PI * 2);
|
|
1372
1372
|
ctx.closePath();
|
|
1373
|
-
ctx.fillStyle =
|
|
1374
|
-
ctx.strokeStyle =
|
|
1373
|
+
ctx.fillStyle = dot.fill;
|
|
1374
|
+
ctx.strokeStyle = dot.stroke;
|
|
1375
1375
|
ctx.lineWidth = DOT_STROKE_WIDTH;
|
|
1376
1376
|
ctx.fill();
|
|
1377
1377
|
ctx.stroke();
|
|
@@ -2090,56 +2090,71 @@ function curveRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, to
|
|
|
2090
2090
|
const cp2 = { x: p3.x + n3.x * offset, y: p3.y + n3.y * offset };
|
|
2091
2091
|
return [p0, cp1, cp2, p3];
|
|
2092
2092
|
}
|
|
2093
|
-
function
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2093
|
+
function inferEllipseParams(nodeBounds, explicitCenter, explicitRx, explicitRy) {
|
|
2094
|
+
if (nodeBounds.length === 0) {
|
|
2095
|
+
return {
|
|
2096
|
+
cx: explicitCenter?.x ?? 0,
|
|
2097
|
+
cy: explicitCenter?.y ?? 0,
|
|
2098
|
+
rx: explicitRx ?? 1,
|
|
2099
|
+
ry: explicitRy ?? 1
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
const centers = nodeBounds.map(rectCenter);
|
|
2103
|
+
const cx = explicitCenter?.x ?? centers.reduce((sum, c) => sum + c.x, 0) / centers.length;
|
|
2104
|
+
const cy = explicitCenter?.y ?? centers.reduce((sum, c) => sum + c.y, 0) / centers.length;
|
|
2105
|
+
const rx = explicitRx ?? Math.max(1, ...centers.map((c) => Math.abs(c.x - cx)));
|
|
2106
|
+
const ry = explicitRy ?? Math.max(1, ...centers.map((c) => Math.abs(c.y - cy)));
|
|
2107
|
+
return { cx, cy, rx, ry };
|
|
2101
2108
|
}
|
|
2102
|
-
function
|
|
2109
|
+
function ellipseRoute(fromBounds, toBounds, ellipse, fromAnchor, toAnchor) {
|
|
2103
2110
|
const fromCenter = rectCenter(fromBounds);
|
|
2104
2111
|
const toCenter = rectCenter(toBounds);
|
|
2105
|
-
const
|
|
2106
|
-
const
|
|
2107
|
-
const
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
const
|
|
2119
|
-
const
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
const
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
const
|
|
2129
|
-
const
|
|
2130
|
-
const
|
|
2131
|
-
const
|
|
2132
|
-
const
|
|
2133
|
-
const
|
|
2134
|
-
const
|
|
2135
|
-
const
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2112
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
2113
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
2114
|
+
const theta1 = Math.atan2(
|
|
2115
|
+
(fromCenter.y - ellipse.cy) / ellipse.ry,
|
|
2116
|
+
(fromCenter.x - ellipse.cx) / ellipse.rx
|
|
2117
|
+
);
|
|
2118
|
+
const theta2 = Math.atan2(
|
|
2119
|
+
(toCenter.y - ellipse.cy) / ellipse.ry,
|
|
2120
|
+
(toCenter.x - ellipse.cx) / ellipse.rx
|
|
2121
|
+
);
|
|
2122
|
+
let angularSpan = theta2 - theta1;
|
|
2123
|
+
while (angularSpan > Math.PI) angularSpan -= 2 * Math.PI;
|
|
2124
|
+
while (angularSpan <= -Math.PI) angularSpan += 2 * Math.PI;
|
|
2125
|
+
const absSpan = Math.abs(angularSpan);
|
|
2126
|
+
const kappa = absSpan < 1e-6 ? 0 : 4 / 3 * Math.tan(absSpan / 4);
|
|
2127
|
+
const tangent1 = {
|
|
2128
|
+
x: -ellipse.rx * Math.sin(theta1),
|
|
2129
|
+
y: ellipse.ry * Math.cos(theta1)
|
|
2130
|
+
};
|
|
2131
|
+
const tangent2 = {
|
|
2132
|
+
x: -ellipse.rx * Math.sin(theta2),
|
|
2133
|
+
y: ellipse.ry * Math.cos(theta2)
|
|
2134
|
+
};
|
|
2135
|
+
const len1 = Math.hypot(tangent1.x, tangent1.y) || 1;
|
|
2136
|
+
const len2 = Math.hypot(tangent2.x, tangent2.y) || 1;
|
|
2137
|
+
const norm1 = { x: tangent1.x / len1, y: tangent1.y / len1 };
|
|
2138
|
+
const norm2 = { x: tangent2.x / len2, y: tangent2.y / len2 };
|
|
2139
|
+
const chordLength = Math.hypot(p3.x - p0.x, p3.y - p0.y);
|
|
2140
|
+
const cpDistance = chordLength * kappa * 0.5;
|
|
2141
|
+
const sign = angularSpan >= 0 ? 1 : -1;
|
|
2142
|
+
const cp1 = {
|
|
2143
|
+
x: p0.x + norm1.x * cpDistance * sign,
|
|
2144
|
+
y: p0.y + norm1.y * cpDistance * sign
|
|
2145
|
+
};
|
|
2146
|
+
const cp2 = {
|
|
2147
|
+
x: p3.x - norm2.x * cpDistance * sign,
|
|
2148
|
+
y: p3.y - norm2.y * cpDistance * sign
|
|
2149
|
+
};
|
|
2150
|
+
return [p0, cp1, cp2, p3];
|
|
2151
|
+
}
|
|
2152
|
+
function straightRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
2153
|
+
const fromC = rectCenter(fromBounds);
|
|
2154
|
+
const toC = rectCenter(toBounds);
|
|
2155
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toC);
|
|
2156
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromC);
|
|
2157
|
+
return [p0, p3];
|
|
2143
2158
|
}
|
|
2144
2159
|
function orthogonalRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
2145
2160
|
const fromC = rectCenter(fromBounds);
|
|
@@ -2185,15 +2200,6 @@ function findBoundaryIntersection(p0, cp1, cp2, p3, targetRect, searchFromEnd) {
|
|
|
2185
2200
|
}
|
|
2186
2201
|
return void 0;
|
|
2187
2202
|
}
|
|
2188
|
-
function pointAlongArc(route, t) {
|
|
2189
|
-
const [first, second] = route;
|
|
2190
|
-
if (t <= 0.5) {
|
|
2191
|
-
const localT2 = Math.max(0, Math.min(1, t * 2));
|
|
2192
|
-
return bezierPointAt(first[0], first[1], first[2], first[3], localT2);
|
|
2193
|
-
}
|
|
2194
|
-
const localT = Math.max(0, Math.min(1, (t - 0.5) * 2));
|
|
2195
|
-
return bezierPointAt(second[0], second[1], second[2], second[3], localT);
|
|
2196
|
-
}
|
|
2197
2203
|
function computeDiagramCenter(nodeBounds, canvasCenter) {
|
|
2198
2204
|
if (nodeBounds.length === 0) {
|
|
2199
2205
|
return canvasCenter ?? { x: 0, y: 0 };
|
|
@@ -2316,8 +2322,19 @@ function polylineBounds(points) {
|
|
|
2316
2322
|
};
|
|
2317
2323
|
}
|
|
2318
2324
|
function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, options) {
|
|
2319
|
-
|
|
2320
|
-
|
|
2325
|
+
let routing = conn.routing ?? "auto";
|
|
2326
|
+
let curveMode = conn.curveMode ?? "normal";
|
|
2327
|
+
if (conn.strokeStyle !== void 0) {
|
|
2328
|
+
console.warn("connection.strokeStyle is deprecated, use style instead");
|
|
2329
|
+
}
|
|
2330
|
+
if (routing === "arc") {
|
|
2331
|
+
console.warn(
|
|
2332
|
+
"connection routing: 'arc' is deprecated. Use routing: 'curve' with curveMode: 'ellipse' instead."
|
|
2333
|
+
);
|
|
2334
|
+
routing = "curve";
|
|
2335
|
+
curveMode = "ellipse";
|
|
2336
|
+
}
|
|
2337
|
+
const strokeStyle = conn.style ?? conn.strokeStyle ?? "solid";
|
|
2321
2338
|
const strokeWidth = conn.width ?? conn.strokeWidth ?? 2;
|
|
2322
2339
|
const tension = conn.tension ?? 0.35;
|
|
2323
2340
|
const dash = dashFromStyle(strokeStyle);
|
|
@@ -2339,14 +2356,29 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
2339
2356
|
ctx.globalAlpha = conn.opacity;
|
|
2340
2357
|
const arrowPlacement = conn.arrowPlacement ?? "endpoint";
|
|
2341
2358
|
if (routing === "curve") {
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2359
|
+
let p0;
|
|
2360
|
+
let cp1;
|
|
2361
|
+
let cp2;
|
|
2362
|
+
let p3;
|
|
2363
|
+
if (curveMode === "ellipse") {
|
|
2364
|
+
const ellipse = options?.ellipseParams ?? inferEllipseParams([fromBounds, toBounds]);
|
|
2365
|
+
[p0, cp1, cp2, p3] = ellipseRoute(
|
|
2366
|
+
fromBounds,
|
|
2367
|
+
toBounds,
|
|
2368
|
+
ellipse,
|
|
2369
|
+
conn.fromAnchor,
|
|
2370
|
+
conn.toAnchor
|
|
2371
|
+
);
|
|
2372
|
+
} else {
|
|
2373
|
+
[p0, cp1, cp2, p3] = curveRoute(
|
|
2374
|
+
fromBounds,
|
|
2375
|
+
toBounds,
|
|
2376
|
+
diagramCenter,
|
|
2377
|
+
tension,
|
|
2378
|
+
conn.fromAnchor,
|
|
2379
|
+
conn.toAnchor
|
|
2380
|
+
);
|
|
2381
|
+
}
|
|
2350
2382
|
const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
|
|
2351
2383
|
ctx.strokeStyle = stroke;
|
|
2352
2384
|
ctx.lineWidth = style.width;
|
|
@@ -2379,51 +2411,22 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
2379
2411
|
}
|
|
2380
2412
|
}
|
|
2381
2413
|
}
|
|
2382
|
-
} else if (routing === "
|
|
2383
|
-
const [
|
|
2384
|
-
fromBounds,
|
|
2385
|
-
toBounds,
|
|
2386
|
-
diagramCenter,
|
|
2387
|
-
tension,
|
|
2388
|
-
conn.fromAnchor,
|
|
2389
|
-
conn.toAnchor
|
|
2390
|
-
);
|
|
2391
|
-
const [p0, cp1, cp2, pMid] = first;
|
|
2392
|
-
const [, cp3, cp4, p3] = second;
|
|
2414
|
+
} else if (routing === "straight") {
|
|
2415
|
+
const [p0, p3] = straightRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor);
|
|
2393
2416
|
const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
|
|
2394
2417
|
ctx.strokeStyle = stroke;
|
|
2395
2418
|
ctx.lineWidth = style.width;
|
|
2396
2419
|
ctx.setLineDash(style.dash ?? []);
|
|
2397
2420
|
ctx.beginPath();
|
|
2398
2421
|
ctx.moveTo(p0.x, p0.y);
|
|
2399
|
-
ctx.
|
|
2400
|
-
ctx.bezierCurveTo(cp3.x, cp3.y, cp4.x, cp4.y, p3.x, p3.y);
|
|
2422
|
+
ctx.lineTo(p3.x, p3.y);
|
|
2401
2423
|
ctx.stroke();
|
|
2402
|
-
linePoints = [p0,
|
|
2424
|
+
linePoints = [p0, p3];
|
|
2403
2425
|
startPoint = p0;
|
|
2404
2426
|
endPoint = p3;
|
|
2405
|
-
startAngle = Math.atan2(p0.y -
|
|
2406
|
-
endAngle = Math.atan2(p3.y -
|
|
2407
|
-
labelPoint =
|
|
2408
|
-
if (arrowPlacement === "boundary") {
|
|
2409
|
-
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
2410
|
-
const [, s_cp3, s_cp4, s_p3] = second;
|
|
2411
|
-
const tEnd = findBoundaryIntersection(pMid, s_cp3, s_cp4, s_p3, toBounds, true);
|
|
2412
|
-
if (tEnd !== void 0) {
|
|
2413
|
-
endPoint = bezierPointAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
2414
|
-
const tangent = bezierTangentAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
2415
|
-
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
2416
|
-
}
|
|
2417
|
-
}
|
|
2418
|
-
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
2419
|
-
const tStart = findBoundaryIntersection(p0, cp1, cp2, pMid, fromBounds, false);
|
|
2420
|
-
if (tStart !== void 0) {
|
|
2421
|
-
startPoint = bezierPointAt(p0, cp1, cp2, pMid, tStart);
|
|
2422
|
-
const tangent = bezierTangentAt(p0, cp1, cp2, pMid, tStart);
|
|
2423
|
-
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
2424
|
-
}
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
+
startAngle = Math.atan2(p0.y - p3.y, p0.x - p3.x);
|
|
2428
|
+
endAngle = Math.atan2(p3.y - p0.y, p3.x - p0.x);
|
|
2429
|
+
labelPoint = pointAlongPolyline(linePoints, labelT);
|
|
2427
2430
|
} else {
|
|
2428
2431
|
const hasAnchorHints = conn.fromAnchor !== void 0 || conn.toAnchor !== void 0;
|
|
2429
2432
|
const useElkRoute = routing === "auto" && !hasAnchorHints && (edgeRoute?.points.length ?? 0) >= 2;
|
|
@@ -3831,7 +3834,8 @@ var connectionElementSchema = z2.object({
|
|
|
3831
3834
|
from: z2.string().min(1).max(120),
|
|
3832
3835
|
to: z2.string().min(1).max(120),
|
|
3833
3836
|
style: z2.enum(["solid", "dashed", "dotted"]).default("solid"),
|
|
3834
|
-
|
|
3837
|
+
/** @deprecated Use `style` instead. */
|
|
3838
|
+
strokeStyle: z2.enum(["solid", "dashed", "dotted"]).optional(),
|
|
3835
3839
|
arrow: z2.enum(["end", "start", "both", "none"]).default("end"),
|
|
3836
3840
|
label: z2.string().min(1).max(200).optional(),
|
|
3837
3841
|
labelPosition: z2.enum(["start", "middle", "end"]).default("middle"),
|
|
@@ -3843,7 +3847,8 @@ var connectionElementSchema = z2.object({
|
|
|
3843
3847
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
3844
3848
|
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
3845
3849
|
opacity: z2.number().min(0).max(1).default(1),
|
|
3846
|
-
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
3850
|
+
routing: z2.enum(["auto", "orthogonal", "curve", "arc", "straight"]).default("auto"),
|
|
3851
|
+
curveMode: z2.enum(["normal", "ellipse"]).default("normal"),
|
|
3847
3852
|
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
3848
3853
|
fromAnchor: anchorHintSchema.optional(),
|
|
3849
3854
|
toAnchor: anchorHintSchema.optional()
|
|
@@ -3936,7 +3941,11 @@ var autoLayoutConfigSchema = z2.object({
|
|
|
3936
3941
|
/** Sort strategy for radial layout node ordering. Only relevant when algorithm is 'radial'. */
|
|
3937
3942
|
radialSortBy: z2.enum(["id", "connections"]).optional(),
|
|
3938
3943
|
/** Explicit center used by curve/arc connection routing. */
|
|
3939
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
3944
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
3945
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3946
|
+
ellipseRx: z2.number().positive().optional(),
|
|
3947
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3948
|
+
ellipseRy: z2.number().positive().optional()
|
|
3940
3949
|
}).strict();
|
|
3941
3950
|
var gridLayoutConfigSchema = z2.object({
|
|
3942
3951
|
mode: z2.literal("grid"),
|
|
@@ -3946,7 +3955,11 @@ var gridLayoutConfigSchema = z2.object({
|
|
|
3946
3955
|
cardMaxHeight: z2.number().int().min(32).max(4096).optional(),
|
|
3947
3956
|
equalHeight: z2.boolean().default(false),
|
|
3948
3957
|
/** Explicit center used by curve/arc connection routing. */
|
|
3949
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
3958
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
3959
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3960
|
+
ellipseRx: z2.number().positive().optional(),
|
|
3961
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3962
|
+
ellipseRy: z2.number().positive().optional()
|
|
3950
3963
|
}).strict();
|
|
3951
3964
|
var stackLayoutConfigSchema = z2.object({
|
|
3952
3965
|
mode: z2.literal("stack"),
|
|
@@ -3954,7 +3967,11 @@ var stackLayoutConfigSchema = z2.object({
|
|
|
3954
3967
|
gap: z2.number().int().min(0).max(256).default(24),
|
|
3955
3968
|
alignment: z2.enum(["start", "center", "end", "stretch"]).default("stretch"),
|
|
3956
3969
|
/** Explicit center used by curve/arc connection routing. */
|
|
3957
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
3970
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
3971
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3972
|
+
ellipseRx: z2.number().positive().optional(),
|
|
3973
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3974
|
+
ellipseRy: z2.number().positive().optional()
|
|
3958
3975
|
}).strict();
|
|
3959
3976
|
var manualPositionSchema = z2.object({
|
|
3960
3977
|
x: z2.number().int(),
|
|
@@ -3966,7 +3983,11 @@ var manualLayoutConfigSchema = z2.object({
|
|
|
3966
3983
|
mode: z2.literal("manual"),
|
|
3967
3984
|
positions: z2.record(z2.string().min(1), manualPositionSchema).default({}),
|
|
3968
3985
|
/** Explicit center used by curve/arc connection routing. */
|
|
3969
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
3986
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
3987
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3988
|
+
ellipseRx: z2.number().positive().optional(),
|
|
3989
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
3990
|
+
ellipseRy: z2.number().positive().optional()
|
|
3970
3991
|
}).strict();
|
|
3971
3992
|
var layoutConfigSchema = z2.discriminatedUnion("mode", [
|
|
3972
3993
|
autoLayoutConfigSchema,
|
|
@@ -4031,7 +4052,11 @@ var diagramElementSchema = z2.discriminatedUnion("type", [
|
|
|
4031
4052
|
var diagramLayoutSchema = z2.object({
|
|
4032
4053
|
mode: z2.enum(["manual", "auto"]).default("manual"),
|
|
4033
4054
|
positions: z2.record(z2.string(), diagramPositionSchema).optional(),
|
|
4034
|
-
diagramCenter: diagramCenterSchema.optional()
|
|
4055
|
+
diagramCenter: diagramCenterSchema.optional(),
|
|
4056
|
+
/** Horizontal radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
4057
|
+
ellipseRx: z2.number().positive().optional(),
|
|
4058
|
+
/** Vertical radius for shared ellipse used by curveMode: 'ellipse'. */
|
|
4059
|
+
ellipseRy: z2.number().positive().optional()
|
|
4035
4060
|
}).strict();
|
|
4036
4061
|
var diagramSpecSchema = z2.object({
|
|
4037
4062
|
version: z2.literal(1),
|
|
@@ -4414,10 +4439,19 @@ async function renderDesign(input, options = {}) {
|
|
|
4414
4439
|
break;
|
|
4415
4440
|
}
|
|
4416
4441
|
}
|
|
4417
|
-
const
|
|
4418
|
-
|
|
4419
|
-
|
|
4442
|
+
const nodeBounds = spec.elements.filter((element) => element.type !== "connection").map((element) => elementRects.get(element.id)).filter((rect) => rect != null);
|
|
4443
|
+
const diagramCenter = spec.layout.diagramCenter ?? computeDiagramCenter(nodeBounds, { x: spec.canvas.width / 2, y: spec.canvas.height / 2 });
|
|
4444
|
+
const layoutEllipseRx = "ellipseRx" in spec.layout ? spec.layout.ellipseRx : void 0;
|
|
4445
|
+
const layoutEllipseRy = "ellipseRy" in spec.layout ? spec.layout.ellipseRy : void 0;
|
|
4446
|
+
const hasEllipseConnections = spec.elements.some(
|
|
4447
|
+
(el) => el.type === "connection" && (el.curveMode === "ellipse" || el.routing === "arc")
|
|
4420
4448
|
);
|
|
4449
|
+
const ellipseParams = hasEllipseConnections ? inferEllipseParams(
|
|
4450
|
+
nodeBounds,
|
|
4451
|
+
spec.layout.diagramCenter ?? diagramCenter,
|
|
4452
|
+
layoutEllipseRx,
|
|
4453
|
+
layoutEllipseRy
|
|
4454
|
+
) : void 0;
|
|
4421
4455
|
for (const element of spec.elements) {
|
|
4422
4456
|
if (element.type !== "connection") {
|
|
4423
4457
|
continue;
|
|
@@ -4431,7 +4465,15 @@ async function renderDesign(input, options = {}) {
|
|
|
4431
4465
|
}
|
|
4432
4466
|
const edgeRoute = edgeRoutes?.get(`${element.from}-${element.to}`);
|
|
4433
4467
|
elements.push(
|
|
4434
|
-
...renderConnection(
|
|
4468
|
+
...renderConnection(
|
|
4469
|
+
ctx,
|
|
4470
|
+
element,
|
|
4471
|
+
fromRect,
|
|
4472
|
+
toRect,
|
|
4473
|
+
theme,
|
|
4474
|
+
edgeRoute,
|
|
4475
|
+
ellipseParams ? { diagramCenter, ellipseParams } : { diagramCenter }
|
|
4476
|
+
)
|
|
4435
4477
|
);
|
|
4436
4478
|
}
|
|
4437
4479
|
if (footerRect && spec.footer) {
|