@spectratools/graphic-designer-cli 0.6.0 → 0.7.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/cli.js +242 -31
- package/dist/index.d.ts +15 -5
- package/dist/index.js +242 -31
- package/dist/qa.d.ts +1 -1
- package/dist/qa.js +48 -10
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +242 -31
- package/dist/{spec.schema-Dm_wOLTd.d.ts → spec.schema-BDvtn_mJ.d.ts} +1456 -21
- package/dist/spec.schema.d.ts +1 -1
- package/dist/spec.schema.js +48 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -761,9 +761,19 @@ var linearGradientSchema = z2.object({
|
|
|
761
761
|
}).strict();
|
|
762
762
|
var radialGradientSchema = z2.object({
|
|
763
763
|
type: z2.literal("radial"),
|
|
764
|
+
cx: z2.number().optional(),
|
|
765
|
+
cy: z2.number().optional(),
|
|
766
|
+
innerRadius: z2.number().min(0).optional(),
|
|
767
|
+
outerRadius: z2.number().min(0).optional(),
|
|
764
768
|
stops: z2.array(gradientStopSchema).min(2)
|
|
765
769
|
}).strict();
|
|
766
770
|
var gradientSchema = z2.discriminatedUnion("type", [linearGradientSchema, radialGradientSchema]);
|
|
771
|
+
var drawShadowSchema = z2.object({
|
|
772
|
+
color: colorHexSchema2.default("rgba(0,0,0,0.5)"),
|
|
773
|
+
blur: z2.number().min(0).max(64).default(10),
|
|
774
|
+
offsetX: z2.number().default(0),
|
|
775
|
+
offsetY: z2.number().default(4)
|
|
776
|
+
}).strict();
|
|
767
777
|
var drawFontFamilySchema = z2.enum(["heading", "body", "mono"]);
|
|
768
778
|
var drawRectSchema = z2.object({
|
|
769
779
|
type: z2.literal("rect"),
|
|
@@ -775,7 +785,8 @@ var drawRectSchema = z2.object({
|
|
|
775
785
|
stroke: colorHexSchema2.optional(),
|
|
776
786
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
777
787
|
radius: z2.number().min(0).max(256).default(0),
|
|
778
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
788
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
789
|
+
shadow: drawShadowSchema.optional()
|
|
779
790
|
}).strict();
|
|
780
791
|
var drawCircleSchema = z2.object({
|
|
781
792
|
type: z2.literal("circle"),
|
|
@@ -785,7 +796,8 @@ var drawCircleSchema = z2.object({
|
|
|
785
796
|
fill: colorHexSchema2.optional(),
|
|
786
797
|
stroke: colorHexSchema2.optional(),
|
|
787
798
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
788
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
799
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
800
|
+
shadow: drawShadowSchema.optional()
|
|
789
801
|
}).strict();
|
|
790
802
|
var drawTextSchema = z2.object({
|
|
791
803
|
type: z2.literal("text"),
|
|
@@ -800,7 +812,8 @@ var drawTextSchema = z2.object({
|
|
|
800
812
|
baseline: z2.enum(["top", "middle", "alphabetic", "bottom"]).default("alphabetic"),
|
|
801
813
|
letterSpacing: z2.number().min(-10).max(50).default(0),
|
|
802
814
|
maxWidth: z2.number().positive().optional(),
|
|
803
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
815
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
816
|
+
shadow: drawShadowSchema.optional()
|
|
804
817
|
}).strict();
|
|
805
818
|
var drawLineSchema = z2.object({
|
|
806
819
|
type: z2.literal("line"),
|
|
@@ -813,7 +826,8 @@ var drawLineSchema = z2.object({
|
|
|
813
826
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
814
827
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
815
828
|
arrowSize: z2.number().min(4).max(32).default(10),
|
|
816
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
829
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
830
|
+
shadow: drawShadowSchema.optional()
|
|
817
831
|
}).strict();
|
|
818
832
|
var drawPointSchema = z2.object({
|
|
819
833
|
x: z2.number(),
|
|
@@ -827,7 +841,8 @@ var drawBezierSchema = z2.object({
|
|
|
827
841
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
828
842
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
829
843
|
arrowSize: z2.number().min(4).max(32).default(10),
|
|
830
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
844
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
845
|
+
shadow: drawShadowSchema.optional()
|
|
831
846
|
}).strict();
|
|
832
847
|
var drawPathSchema = z2.object({
|
|
833
848
|
type: z2.literal("path"),
|
|
@@ -835,7 +850,8 @@ var drawPathSchema = z2.object({
|
|
|
835
850
|
fill: colorHexSchema2.optional(),
|
|
836
851
|
stroke: colorHexSchema2.optional(),
|
|
837
852
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
838
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
853
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
854
|
+
shadow: drawShadowSchema.optional()
|
|
839
855
|
}).strict();
|
|
840
856
|
var drawBadgeSchema = z2.object({
|
|
841
857
|
type: z2.literal("badge"),
|
|
@@ -849,7 +865,8 @@ var drawBadgeSchema = z2.object({
|
|
|
849
865
|
paddingX: z2.number().min(0).max(64).default(10),
|
|
850
866
|
paddingY: z2.number().min(0).max(32).default(4),
|
|
851
867
|
borderRadius: z2.number().min(0).max(64).default(12),
|
|
852
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
868
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
869
|
+
shadow: drawShadowSchema.optional()
|
|
853
870
|
}).strict();
|
|
854
871
|
var drawGradientRectSchema = z2.object({
|
|
855
872
|
type: z2.literal("gradient-rect"),
|
|
@@ -859,7 +876,17 @@ var drawGradientRectSchema = z2.object({
|
|
|
859
876
|
height: z2.number().positive(),
|
|
860
877
|
gradient: gradientSchema,
|
|
861
878
|
radius: z2.number().min(0).max(256).default(0),
|
|
862
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
879
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
880
|
+
shadow: drawShadowSchema.optional()
|
|
881
|
+
}).strict();
|
|
882
|
+
var drawGridSchema = z2.object({
|
|
883
|
+
type: z2.literal("grid"),
|
|
884
|
+
spacing: z2.number().min(5).max(200).default(40),
|
|
885
|
+
color: colorHexSchema2.default("#1E2D4A"),
|
|
886
|
+
width: z2.number().min(0.1).max(4).default(0.5),
|
|
887
|
+
opacity: z2.number().min(0).max(1).default(0.2),
|
|
888
|
+
offsetX: z2.number().default(0),
|
|
889
|
+
offsetY: z2.number().default(0)
|
|
863
890
|
}).strict();
|
|
864
891
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
865
892
|
drawRectSchema,
|
|
@@ -869,7 +896,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
869
896
|
drawBezierSchema,
|
|
870
897
|
drawPathSchema,
|
|
871
898
|
drawBadgeSchema,
|
|
872
|
-
drawGradientRectSchema
|
|
899
|
+
drawGradientRectSchema,
|
|
900
|
+
drawGridSchema
|
|
873
901
|
]);
|
|
874
902
|
var defaultCanvas = {
|
|
875
903
|
width: 1200,
|
|
@@ -976,6 +1004,13 @@ var flowNodeElementSchema = z2.object({
|
|
|
976
1004
|
badgePosition: z2.enum(["top", "inside-top"]).default("inside-top"),
|
|
977
1005
|
shadow: flowNodeShadowSchema.optional()
|
|
978
1006
|
}).strict();
|
|
1007
|
+
var anchorHintSchema = z2.union([
|
|
1008
|
+
z2.enum(["top", "bottom", "left", "right", "center"]),
|
|
1009
|
+
z2.object({
|
|
1010
|
+
x: z2.number().min(-1).max(1),
|
|
1011
|
+
y: z2.number().min(-1).max(1)
|
|
1012
|
+
}).strict()
|
|
1013
|
+
]);
|
|
979
1014
|
var connectionElementSchema = z2.object({
|
|
980
1015
|
type: z2.literal("connection"),
|
|
981
1016
|
from: z2.string().min(1).max(120),
|
|
@@ -989,9 +1024,12 @@ var connectionElementSchema = z2.object({
|
|
|
989
1024
|
width: z2.number().min(0.5).max(10).optional(),
|
|
990
1025
|
strokeWidth: z2.number().min(0.5).max(10).default(2),
|
|
991
1026
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
1027
|
+
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
992
1028
|
opacity: z2.number().min(0).max(1).default(1),
|
|
993
1029
|
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
994
|
-
tension: z2.number().min(0.1).max(0.8).default(0.35)
|
|
1030
|
+
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
1031
|
+
fromAnchor: anchorHintSchema.optional(),
|
|
1032
|
+
toAnchor: anchorHintSchema.optional()
|
|
995
1033
|
}).strict();
|
|
996
1034
|
var codeBlockStyleSchema = z2.object({
|
|
997
1035
|
paddingVertical: z2.number().min(0).max(128).default(56),
|
|
@@ -2492,12 +2530,12 @@ function withAlpha2(color, alpha) {
|
|
|
2492
2530
|
}
|
|
2493
2531
|
function drawGradientRect(ctx, rect, gradient, borderRadius = 0) {
|
|
2494
2532
|
const fill = gradient.type === "linear" ? createLinearRectGradient(ctx, rect, gradient.angle ?? 180) : ctx.createRadialGradient(
|
|
2495
|
-
rect.x + rect.width / 2,
|
|
2496
|
-
rect.y + rect.height / 2,
|
|
2497
|
-
0,
|
|
2498
|
-
rect.x + rect.width / 2,
|
|
2499
|
-
rect.y + rect.height / 2,
|
|
2500
|
-
Math.max(rect.width, rect.height) / 2
|
|
2533
|
+
gradient.cx ?? rect.x + rect.width / 2,
|
|
2534
|
+
gradient.cy ?? rect.y + rect.height / 2,
|
|
2535
|
+
gradient.innerRadius ?? 0,
|
|
2536
|
+
gradient.cx ?? rect.x + rect.width / 2,
|
|
2537
|
+
gradient.cy ?? rect.y + rect.height / 2,
|
|
2538
|
+
gradient.outerRadius ?? Math.max(rect.width, rect.height) / 2
|
|
2501
2539
|
);
|
|
2502
2540
|
addGradientStops(fill, gradient.stops);
|
|
2503
2541
|
ctx.save();
|
|
@@ -3122,21 +3160,61 @@ function edgeAnchor(bounds, target) {
|
|
|
3122
3160
|
const t = absDx * hh > absDy * hw ? hw / absDx : hh / absDy;
|
|
3123
3161
|
return { x: c.x + dx * t, y: c.y + dy * t };
|
|
3124
3162
|
}
|
|
3163
|
+
function resolveAnchor(bounds, anchor, fallbackTarget) {
|
|
3164
|
+
if (!anchor) return edgeAnchor(bounds, fallbackTarget);
|
|
3165
|
+
if (typeof anchor === "string") {
|
|
3166
|
+
const c2 = rectCenter(bounds);
|
|
3167
|
+
switch (anchor) {
|
|
3168
|
+
case "top":
|
|
3169
|
+
return { x: c2.x, y: bounds.y };
|
|
3170
|
+
case "bottom":
|
|
3171
|
+
return { x: c2.x, y: bounds.y + bounds.height };
|
|
3172
|
+
case "left":
|
|
3173
|
+
return { x: bounds.x, y: c2.y };
|
|
3174
|
+
case "right":
|
|
3175
|
+
return { x: bounds.x + bounds.width, y: c2.y };
|
|
3176
|
+
case "center":
|
|
3177
|
+
return c2;
|
|
3178
|
+
}
|
|
3179
|
+
}
|
|
3180
|
+
const c = rectCenter(bounds);
|
|
3181
|
+
return {
|
|
3182
|
+
x: c.x + anchor.x * (bounds.width / 2),
|
|
3183
|
+
y: c.y + anchor.y * (bounds.height / 2)
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
function anchorNormal(anchor, point, diagramCenter) {
|
|
3187
|
+
if (typeof anchor === "string") {
|
|
3188
|
+
switch (anchor) {
|
|
3189
|
+
case "top":
|
|
3190
|
+
return { x: 0, y: -1 };
|
|
3191
|
+
case "bottom":
|
|
3192
|
+
return { x: 0, y: 1 };
|
|
3193
|
+
case "left":
|
|
3194
|
+
return { x: -1, y: 0 };
|
|
3195
|
+
case "right":
|
|
3196
|
+
return { x: 1, y: 0 };
|
|
3197
|
+
case "center":
|
|
3198
|
+
return outwardNormal(point, diagramCenter);
|
|
3199
|
+
}
|
|
3200
|
+
}
|
|
3201
|
+
return outwardNormal(point, diagramCenter);
|
|
3202
|
+
}
|
|
3125
3203
|
function outwardNormal(point, diagramCenter) {
|
|
3126
3204
|
const dx = point.x - diagramCenter.x;
|
|
3127
3205
|
const dy = point.y - diagramCenter.y;
|
|
3128
3206
|
const len = Math.hypot(dx, dy) || 1;
|
|
3129
3207
|
return { x: dx / len, y: dy / len };
|
|
3130
3208
|
}
|
|
3131
|
-
function curveRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3209
|
+
function curveRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3132
3210
|
const fromCenter = rectCenter(fromBounds);
|
|
3133
3211
|
const toCenter = rectCenter(toBounds);
|
|
3134
|
-
const p0 =
|
|
3135
|
-
const p3 =
|
|
3212
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3213
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3136
3214
|
const dist = Math.hypot(p3.x - p0.x, p3.y - p0.y);
|
|
3137
3215
|
const offset = dist * tension;
|
|
3138
|
-
const n0 =
|
|
3139
|
-
const n3 =
|
|
3216
|
+
const n0 = anchorNormal(fromAnchor, p0, diagramCenter);
|
|
3217
|
+
const n3 = anchorNormal(toAnchor, p3, diagramCenter);
|
|
3140
3218
|
const cp1 = { x: p0.x + n0.x * offset, y: p0.y + n0.y * offset };
|
|
3141
3219
|
const cp2 = { x: p3.x + n3.x * offset, y: p3.y + n3.y * offset };
|
|
3142
3220
|
return [p0, cp1, cp2, p3];
|
|
@@ -3150,11 +3228,11 @@ function localToWorld(origin, axisX, axisY, local) {
|
|
|
3150
3228
|
y: origin.y + axisX.y * local.x + axisY.y * local.y
|
|
3151
3229
|
};
|
|
3152
3230
|
}
|
|
3153
|
-
function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
3231
|
+
function arcRoute(fromBounds, toBounds, diagramCenter, tension, fromAnchor, toAnchor) {
|
|
3154
3232
|
const fromCenter = rectCenter(fromBounds);
|
|
3155
3233
|
const toCenter = rectCenter(toBounds);
|
|
3156
|
-
const start =
|
|
3157
|
-
const end =
|
|
3234
|
+
const start = resolveAnchor(fromBounds, fromAnchor, toCenter);
|
|
3235
|
+
const end = resolveAnchor(toBounds, toAnchor, fromCenter);
|
|
3158
3236
|
const chord = { x: end.x - start.x, y: end.y - start.y };
|
|
3159
3237
|
const chordLength = Math.hypot(chord.x, chord.y);
|
|
3160
3238
|
if (chordLength < 1e-6) {
|
|
@@ -3192,11 +3270,11 @@ function arcRoute(fromBounds, toBounds, diagramCenter, tension) {
|
|
|
3192
3270
|
[pMid, cp3, cp4, p3]
|
|
3193
3271
|
];
|
|
3194
3272
|
}
|
|
3195
|
-
function orthogonalRoute(fromBounds, toBounds) {
|
|
3273
|
+
function orthogonalRoute(fromBounds, toBounds, fromAnchor, toAnchor) {
|
|
3196
3274
|
const fromC = rectCenter(fromBounds);
|
|
3197
3275
|
const toC = rectCenter(toBounds);
|
|
3198
|
-
const p0 =
|
|
3199
|
-
const p3 =
|
|
3276
|
+
const p0 = resolveAnchor(fromBounds, fromAnchor, toC);
|
|
3277
|
+
const p3 = resolveAnchor(toBounds, toAnchor, fromC);
|
|
3200
3278
|
const midX = (p0.x + p3.x) / 2;
|
|
3201
3279
|
return [p0, { x: midX, y: p0.y }, { x: midX, y: p3.y }, p3];
|
|
3202
3280
|
}
|
|
@@ -3207,6 +3285,35 @@ function bezierPointAt(p0, cp1, cp2, p3, t) {
|
|
|
3207
3285
|
y: mt * mt * mt * p0.y + 3 * mt * mt * t * cp1.y + 3 * mt * t * t * cp2.y + t * t * t * p3.y
|
|
3208
3286
|
};
|
|
3209
3287
|
}
|
|
3288
|
+
function bezierTangentAt(p0, cp1, cp2, p3, t) {
|
|
3289
|
+
const mt = 1 - t;
|
|
3290
|
+
return {
|
|
3291
|
+
x: 3 * mt * mt * (cp1.x - p0.x) + 6 * mt * t * (cp2.x - cp1.x) + 3 * t * t * (p3.x - cp2.x),
|
|
3292
|
+
y: 3 * mt * mt * (cp1.y - p0.y) + 6 * mt * t * (cp2.y - cp1.y) + 3 * t * t * (p3.y - cp2.y)
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
function isInsideRect(point, rect) {
|
|
3296
|
+
return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
3297
|
+
}
|
|
3298
|
+
function findBoundaryIntersection(p0, cp1, cp2, p3, targetRect, searchFromEnd) {
|
|
3299
|
+
const step = 5e-3;
|
|
3300
|
+
if (searchFromEnd) {
|
|
3301
|
+
for (let t = 0.95; t >= 0.5; t -= step) {
|
|
3302
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3303
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3304
|
+
return t;
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
} else {
|
|
3308
|
+
for (let t = 0.05; t <= 0.5; t += step) {
|
|
3309
|
+
const pt = bezierPointAt(p0, cp1, cp2, p3, t);
|
|
3310
|
+
if (!isInsideRect(pt, targetRect)) {
|
|
3311
|
+
return t;
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
return void 0;
|
|
3316
|
+
}
|
|
3210
3317
|
function pointAlongArc(route, t) {
|
|
3211
3318
|
const [first, second] = route;
|
|
3212
3319
|
if (t <= 0.5) {
|
|
@@ -3334,8 +3441,16 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3334
3441
|
let labelPoint;
|
|
3335
3442
|
ctx.save();
|
|
3336
3443
|
ctx.globalAlpha = conn.opacity;
|
|
3444
|
+
const arrowPlacement = conn.arrowPlacement ?? "endpoint";
|
|
3337
3445
|
if (routing === "curve") {
|
|
3338
|
-
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3446
|
+
const [p0, cp1, cp2, p3] = curveRoute(
|
|
3447
|
+
fromBounds,
|
|
3448
|
+
toBounds,
|
|
3449
|
+
diagramCenter,
|
|
3450
|
+
tension,
|
|
3451
|
+
conn.fromAnchor,
|
|
3452
|
+
conn.toAnchor
|
|
3453
|
+
);
|
|
3339
3454
|
ctx.strokeStyle = style.color;
|
|
3340
3455
|
ctx.lineWidth = style.width;
|
|
3341
3456
|
ctx.setLineDash(style.dash ?? []);
|
|
@@ -3349,8 +3464,33 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3349
3464
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3350
3465
|
endAngle = Math.atan2(p3.y - cp2.y, p3.x - cp2.x);
|
|
3351
3466
|
labelPoint = bezierPointAt(p0, cp1, cp2, p3, labelT);
|
|
3467
|
+
if (arrowPlacement === "boundary") {
|
|
3468
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3469
|
+
const tEnd = findBoundaryIntersection(p0, cp1, cp2, p3, toBounds, true);
|
|
3470
|
+
if (tEnd !== void 0) {
|
|
3471
|
+
endPoint = bezierPointAt(p0, cp1, cp2, p3, tEnd);
|
|
3472
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tEnd);
|
|
3473
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3477
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, p3, fromBounds, false);
|
|
3478
|
+
if (tStart !== void 0) {
|
|
3479
|
+
startPoint = bezierPointAt(p0, cp1, cp2, p3, tStart);
|
|
3480
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, p3, tStart);
|
|
3481
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3482
|
+
}
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3352
3485
|
} else if (routing === "arc") {
|
|
3353
|
-
const [first, second] = arcRoute(
|
|
3486
|
+
const [first, second] = arcRoute(
|
|
3487
|
+
fromBounds,
|
|
3488
|
+
toBounds,
|
|
3489
|
+
diagramCenter,
|
|
3490
|
+
tension,
|
|
3491
|
+
conn.fromAnchor,
|
|
3492
|
+
conn.toAnchor
|
|
3493
|
+
);
|
|
3354
3494
|
const [p0, cp1, cp2, pMid] = first;
|
|
3355
3495
|
const [, cp3, cp4, p3] = second;
|
|
3356
3496
|
ctx.strokeStyle = style.color;
|
|
@@ -3367,9 +3507,29 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
|
|
|
3367
3507
|
startAngle = Math.atan2(p0.y - cp1.y, p0.x - cp1.x);
|
|
3368
3508
|
endAngle = Math.atan2(p3.y - cp4.y, p3.x - cp4.x);
|
|
3369
3509
|
labelPoint = pointAlongArc([first, second], labelT);
|
|
3510
|
+
if (arrowPlacement === "boundary") {
|
|
3511
|
+
if (conn.arrow === "end" || conn.arrow === "both") {
|
|
3512
|
+
const [, s_cp3, s_cp4, s_p3] = second;
|
|
3513
|
+
const tEnd = findBoundaryIntersection(pMid, s_cp3, s_cp4, s_p3, toBounds, true);
|
|
3514
|
+
if (tEnd !== void 0) {
|
|
3515
|
+
endPoint = bezierPointAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3516
|
+
const tangent = bezierTangentAt(pMid, s_cp3, s_cp4, s_p3, tEnd);
|
|
3517
|
+
endAngle = Math.atan2(tangent.y, tangent.x);
|
|
3518
|
+
}
|
|
3519
|
+
}
|
|
3520
|
+
if (conn.arrow === "start" || conn.arrow === "both") {
|
|
3521
|
+
const tStart = findBoundaryIntersection(p0, cp1, cp2, pMid, fromBounds, false);
|
|
3522
|
+
if (tStart !== void 0) {
|
|
3523
|
+
startPoint = bezierPointAt(p0, cp1, cp2, pMid, tStart);
|
|
3524
|
+
const tangent = bezierTangentAt(p0, cp1, cp2, pMid, tStart);
|
|
3525
|
+
startAngle = Math.atan2(tangent.y, tangent.x) + Math.PI;
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3370
3529
|
} else {
|
|
3371
|
-
const
|
|
3372
|
-
|
|
3530
|
+
const hasAnchorHints = conn.fromAnchor !== void 0 || conn.toAnchor !== void 0;
|
|
3531
|
+
const useElkRoute = routing === "auto" && !hasAnchorHints && (edgeRoute?.points.length ?? 0) >= 2;
|
|
3532
|
+
linePoints = useElkRoute ? edgeRoute?.points ?? orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor) : orthogonalRoute(fromBounds, toBounds, conn.fromAnchor, conn.toAnchor);
|
|
3373
3533
|
startPoint = linePoints[0];
|
|
3374
3534
|
const startSegment = linePoints[1] ?? linePoints[0];
|
|
3375
3535
|
const endStart = linePoints[linePoints.length - 2] ?? linePoints[0];
|
|
@@ -3601,6 +3761,13 @@ function expandRect(rect, amount) {
|
|
|
3601
3761
|
height: rect.height + amount * 2
|
|
3602
3762
|
};
|
|
3603
3763
|
}
|
|
3764
|
+
function applyDrawShadow(ctx, shadow) {
|
|
3765
|
+
if (!shadow) return;
|
|
3766
|
+
ctx.shadowColor = shadow.color;
|
|
3767
|
+
ctx.shadowBlur = shadow.blur;
|
|
3768
|
+
ctx.shadowOffsetX = shadow.offsetX;
|
|
3769
|
+
ctx.shadowOffsetY = shadow.offsetY;
|
|
3770
|
+
}
|
|
3604
3771
|
function fromPoints(points) {
|
|
3605
3772
|
const minX = Math.min(...points.map((point) => point.x));
|
|
3606
3773
|
const minY = Math.min(...points.map((point) => point.y));
|
|
@@ -3782,6 +3949,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3782
3949
|
height: command.height
|
|
3783
3950
|
};
|
|
3784
3951
|
withOpacity(ctx, command.opacity, () => {
|
|
3952
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3785
3953
|
roundRectPath(ctx, rect, command.radius);
|
|
3786
3954
|
if (command.fill) {
|
|
3787
3955
|
ctx.fillStyle = command.fill;
|
|
@@ -3805,6 +3973,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3805
3973
|
}
|
|
3806
3974
|
case "circle": {
|
|
3807
3975
|
withOpacity(ctx, command.opacity, () => {
|
|
3976
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3808
3977
|
ctx.beginPath();
|
|
3809
3978
|
ctx.arc(command.cx, command.cy, command.radius, 0, Math.PI * 2);
|
|
3810
3979
|
ctx.closePath();
|
|
@@ -3839,6 +4008,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3839
4008
|
case "text": {
|
|
3840
4009
|
const fontFamily = resolveDrawFont(theme, command.fontFamily);
|
|
3841
4010
|
withOpacity(ctx, command.opacity, () => {
|
|
4011
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3842
4012
|
applyFont(ctx, {
|
|
3843
4013
|
size: command.fontSize,
|
|
3844
4014
|
weight: command.fontWeight,
|
|
@@ -3889,6 +4059,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3889
4059
|
const to = { x: command.x2, y: command.y2 };
|
|
3890
4060
|
const lineAngle = angleBetween(from, to);
|
|
3891
4061
|
withOpacity(ctx, command.opacity, () => {
|
|
4062
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3892
4063
|
drawLine(ctx, from, to, {
|
|
3893
4064
|
color: command.color,
|
|
3894
4065
|
width: command.width,
|
|
@@ -3913,6 +4084,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3913
4084
|
case "bezier": {
|
|
3914
4085
|
const points = command.points;
|
|
3915
4086
|
withOpacity(ctx, command.opacity, () => {
|
|
4087
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3916
4088
|
drawBezier(ctx, points, {
|
|
3917
4089
|
color: command.color,
|
|
3918
4090
|
width: command.width,
|
|
@@ -3946,6 +4118,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3946
4118
|
const operations = parseSvgPath(command.d);
|
|
3947
4119
|
const baseBounds = pathBounds(operations);
|
|
3948
4120
|
withOpacity(ctx, command.opacity, () => {
|
|
4121
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3949
4122
|
applySvgOperations(ctx, operations);
|
|
3950
4123
|
if (command.fill) {
|
|
3951
4124
|
ctx.fillStyle = command.fill;
|
|
@@ -3986,9 +4159,16 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
3986
4159
|
height: textHeight + command.paddingY * 2
|
|
3987
4160
|
};
|
|
3988
4161
|
withOpacity(ctx, command.opacity, () => {
|
|
4162
|
+
applyDrawShadow(ctx, command.shadow);
|
|
3989
4163
|
roundRectPath(ctx, rect, command.borderRadius);
|
|
3990
4164
|
ctx.fillStyle = command.background;
|
|
3991
4165
|
ctx.fill();
|
|
4166
|
+
if (command.shadow) {
|
|
4167
|
+
ctx.shadowColor = "transparent";
|
|
4168
|
+
ctx.shadowBlur = 0;
|
|
4169
|
+
ctx.shadowOffsetX = 0;
|
|
4170
|
+
ctx.shadowOffsetY = 0;
|
|
4171
|
+
}
|
|
3992
4172
|
applyFont(ctx, {
|
|
3993
4173
|
size: command.fontSize,
|
|
3994
4174
|
weight: 600,
|
|
@@ -4016,6 +4196,7 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4016
4196
|
height: command.height
|
|
4017
4197
|
};
|
|
4018
4198
|
withOpacity(ctx, command.opacity, () => {
|
|
4199
|
+
applyDrawShadow(ctx, command.shadow);
|
|
4019
4200
|
drawGradientRect(ctx, rect, command.gradient, command.radius);
|
|
4020
4201
|
});
|
|
4021
4202
|
rendered.push({
|
|
@@ -4026,6 +4207,36 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4026
4207
|
});
|
|
4027
4208
|
break;
|
|
4028
4209
|
}
|
|
4210
|
+
case "grid": {
|
|
4211
|
+
const canvasWidth = ctx.canvas.width;
|
|
4212
|
+
const canvasHeight = ctx.canvas.height;
|
|
4213
|
+
withOpacity(ctx, command.opacity, () => {
|
|
4214
|
+
ctx.strokeStyle = command.color;
|
|
4215
|
+
ctx.lineWidth = command.width;
|
|
4216
|
+
const startX = command.offsetX % command.spacing;
|
|
4217
|
+
for (let x = startX; x <= canvasWidth; x += command.spacing) {
|
|
4218
|
+
ctx.beginPath();
|
|
4219
|
+
ctx.moveTo(x, 0);
|
|
4220
|
+
ctx.lineTo(x, canvasHeight);
|
|
4221
|
+
ctx.stroke();
|
|
4222
|
+
}
|
|
4223
|
+
const startY = command.offsetY % command.spacing;
|
|
4224
|
+
for (let y = startY; y <= canvasHeight; y += command.spacing) {
|
|
4225
|
+
ctx.beginPath();
|
|
4226
|
+
ctx.moveTo(0, y);
|
|
4227
|
+
ctx.lineTo(canvasWidth, y);
|
|
4228
|
+
ctx.stroke();
|
|
4229
|
+
}
|
|
4230
|
+
});
|
|
4231
|
+
rendered.push({
|
|
4232
|
+
id,
|
|
4233
|
+
kind: "draw",
|
|
4234
|
+
bounds: { x: 0, y: 0, width: canvasWidth, height: canvasHeight },
|
|
4235
|
+
foregroundColor: command.color,
|
|
4236
|
+
allowOverlap: true
|
|
4237
|
+
});
|
|
4238
|
+
break;
|
|
4239
|
+
}
|
|
4029
4240
|
}
|
|
4030
4241
|
}
|
|
4031
4242
|
return rendered;
|
package/dist/qa.d.ts
CHANGED
package/dist/qa.js
CHANGED
|
@@ -495,9 +495,19 @@ var linearGradientSchema = z2.object({
|
|
|
495
495
|
}).strict();
|
|
496
496
|
var radialGradientSchema = z2.object({
|
|
497
497
|
type: z2.literal("radial"),
|
|
498
|
+
cx: z2.number().optional(),
|
|
499
|
+
cy: z2.number().optional(),
|
|
500
|
+
innerRadius: z2.number().min(0).optional(),
|
|
501
|
+
outerRadius: z2.number().min(0).optional(),
|
|
498
502
|
stops: z2.array(gradientStopSchema).min(2)
|
|
499
503
|
}).strict();
|
|
500
504
|
var gradientSchema = z2.discriminatedUnion("type", [linearGradientSchema, radialGradientSchema]);
|
|
505
|
+
var drawShadowSchema = z2.object({
|
|
506
|
+
color: colorHexSchema2.default("rgba(0,0,0,0.5)"),
|
|
507
|
+
blur: z2.number().min(0).max(64).default(10),
|
|
508
|
+
offsetX: z2.number().default(0),
|
|
509
|
+
offsetY: z2.number().default(4)
|
|
510
|
+
}).strict();
|
|
501
511
|
var drawFontFamilySchema = z2.enum(["heading", "body", "mono"]);
|
|
502
512
|
var drawRectSchema = z2.object({
|
|
503
513
|
type: z2.literal("rect"),
|
|
@@ -509,7 +519,8 @@ var drawRectSchema = z2.object({
|
|
|
509
519
|
stroke: colorHexSchema2.optional(),
|
|
510
520
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
511
521
|
radius: z2.number().min(0).max(256).default(0),
|
|
512
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
522
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
523
|
+
shadow: drawShadowSchema.optional()
|
|
513
524
|
}).strict();
|
|
514
525
|
var drawCircleSchema = z2.object({
|
|
515
526
|
type: z2.literal("circle"),
|
|
@@ -519,7 +530,8 @@ var drawCircleSchema = z2.object({
|
|
|
519
530
|
fill: colorHexSchema2.optional(),
|
|
520
531
|
stroke: colorHexSchema2.optional(),
|
|
521
532
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
522
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
533
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
534
|
+
shadow: drawShadowSchema.optional()
|
|
523
535
|
}).strict();
|
|
524
536
|
var drawTextSchema = z2.object({
|
|
525
537
|
type: z2.literal("text"),
|
|
@@ -534,7 +546,8 @@ var drawTextSchema = z2.object({
|
|
|
534
546
|
baseline: z2.enum(["top", "middle", "alphabetic", "bottom"]).default("alphabetic"),
|
|
535
547
|
letterSpacing: z2.number().min(-10).max(50).default(0),
|
|
536
548
|
maxWidth: z2.number().positive().optional(),
|
|
537
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
549
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
550
|
+
shadow: drawShadowSchema.optional()
|
|
538
551
|
}).strict();
|
|
539
552
|
var drawLineSchema = z2.object({
|
|
540
553
|
type: z2.literal("line"),
|
|
@@ -547,7 +560,8 @@ var drawLineSchema = z2.object({
|
|
|
547
560
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
548
561
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
549
562
|
arrowSize: z2.number().min(4).max(32).default(10),
|
|
550
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
563
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
564
|
+
shadow: drawShadowSchema.optional()
|
|
551
565
|
}).strict();
|
|
552
566
|
var drawPointSchema = z2.object({
|
|
553
567
|
x: z2.number(),
|
|
@@ -561,7 +575,8 @@ var drawBezierSchema = z2.object({
|
|
|
561
575
|
dash: z2.array(z2.number()).max(6).optional(),
|
|
562
576
|
arrow: z2.enum(["none", "end", "start", "both"]).default("none"),
|
|
563
577
|
arrowSize: z2.number().min(4).max(32).default(10),
|
|
564
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
578
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
579
|
+
shadow: drawShadowSchema.optional()
|
|
565
580
|
}).strict();
|
|
566
581
|
var drawPathSchema = z2.object({
|
|
567
582
|
type: z2.literal("path"),
|
|
@@ -569,7 +584,8 @@ var drawPathSchema = z2.object({
|
|
|
569
584
|
fill: colorHexSchema2.optional(),
|
|
570
585
|
stroke: colorHexSchema2.optional(),
|
|
571
586
|
strokeWidth: z2.number().min(0).max(32).default(0),
|
|
572
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
587
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
588
|
+
shadow: drawShadowSchema.optional()
|
|
573
589
|
}).strict();
|
|
574
590
|
var drawBadgeSchema = z2.object({
|
|
575
591
|
type: z2.literal("badge"),
|
|
@@ -583,7 +599,8 @@ var drawBadgeSchema = z2.object({
|
|
|
583
599
|
paddingX: z2.number().min(0).max(64).default(10),
|
|
584
600
|
paddingY: z2.number().min(0).max(32).default(4),
|
|
585
601
|
borderRadius: z2.number().min(0).max(64).default(12),
|
|
586
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
602
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
603
|
+
shadow: drawShadowSchema.optional()
|
|
587
604
|
}).strict();
|
|
588
605
|
var drawGradientRectSchema = z2.object({
|
|
589
606
|
type: z2.literal("gradient-rect"),
|
|
@@ -593,7 +610,17 @@ var drawGradientRectSchema = z2.object({
|
|
|
593
610
|
height: z2.number().positive(),
|
|
594
611
|
gradient: gradientSchema,
|
|
595
612
|
radius: z2.number().min(0).max(256).default(0),
|
|
596
|
-
opacity: z2.number().min(0).max(1).default(1)
|
|
613
|
+
opacity: z2.number().min(0).max(1).default(1),
|
|
614
|
+
shadow: drawShadowSchema.optional()
|
|
615
|
+
}).strict();
|
|
616
|
+
var drawGridSchema = z2.object({
|
|
617
|
+
type: z2.literal("grid"),
|
|
618
|
+
spacing: z2.number().min(5).max(200).default(40),
|
|
619
|
+
color: colorHexSchema2.default("#1E2D4A"),
|
|
620
|
+
width: z2.number().min(0.1).max(4).default(0.5),
|
|
621
|
+
opacity: z2.number().min(0).max(1).default(0.2),
|
|
622
|
+
offsetX: z2.number().default(0),
|
|
623
|
+
offsetY: z2.number().default(0)
|
|
597
624
|
}).strict();
|
|
598
625
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
599
626
|
drawRectSchema,
|
|
@@ -603,7 +630,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
603
630
|
drawBezierSchema,
|
|
604
631
|
drawPathSchema,
|
|
605
632
|
drawBadgeSchema,
|
|
606
|
-
drawGradientRectSchema
|
|
633
|
+
drawGradientRectSchema,
|
|
634
|
+
drawGridSchema
|
|
607
635
|
]);
|
|
608
636
|
var defaultCanvas = {
|
|
609
637
|
width: 1200,
|
|
@@ -709,6 +737,13 @@ var flowNodeElementSchema = z2.object({
|
|
|
709
737
|
badgePosition: z2.enum(["top", "inside-top"]).default("inside-top"),
|
|
710
738
|
shadow: flowNodeShadowSchema.optional()
|
|
711
739
|
}).strict();
|
|
740
|
+
var anchorHintSchema = z2.union([
|
|
741
|
+
z2.enum(["top", "bottom", "left", "right", "center"]),
|
|
742
|
+
z2.object({
|
|
743
|
+
x: z2.number().min(-1).max(1),
|
|
744
|
+
y: z2.number().min(-1).max(1)
|
|
745
|
+
}).strict()
|
|
746
|
+
]);
|
|
712
747
|
var connectionElementSchema = z2.object({
|
|
713
748
|
type: z2.literal("connection"),
|
|
714
749
|
from: z2.string().min(1).max(120),
|
|
@@ -722,9 +757,12 @@ var connectionElementSchema = z2.object({
|
|
|
722
757
|
width: z2.number().min(0.5).max(10).optional(),
|
|
723
758
|
strokeWidth: z2.number().min(0.5).max(10).default(2),
|
|
724
759
|
arrowSize: z2.number().min(4).max(32).optional(),
|
|
760
|
+
arrowPlacement: z2.enum(["endpoint", "boundary"]).default("endpoint"),
|
|
725
761
|
opacity: z2.number().min(0).max(1).default(1),
|
|
726
762
|
routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
|
|
727
|
-
tension: z2.number().min(0.1).max(0.8).default(0.35)
|
|
763
|
+
tension: z2.number().min(0.1).max(0.8).default(0.35),
|
|
764
|
+
fromAnchor: anchorHintSchema.optional(),
|
|
765
|
+
toAnchor: anchorHintSchema.optional()
|
|
728
766
|
}).strict();
|
|
729
767
|
var codeBlockStyleSchema = z2.object({
|
|
730
768
|
paddingVertical: z2.number().min(0).max(128).default(56),
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { i as DEFAULT_GENERATOR_VERSION, P as LayoutSnapshot, a as Rect, R as RenderMetadata, U as RenderResult, d as RenderedElement, $ as WrittenArtifacts, a2 as computeSpecHash, al as inferSidecarPath, ao as renderDesign, aq as writeRenderArtifacts } from './spec.schema-BDvtn_mJ.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@napi-rs/canvas';
|