@spectratools/graphic-designer-cli 0.12.2 → 0.14.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 +316 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +316 -5
- package/dist/qa.d.ts +1 -1
- package/dist/qa.js +49 -3
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +316 -5
- package/dist/{spec.schema-BkbcnVcm.d.ts → spec.schema-De-IkUjn.d.ts} +584 -26
- package/dist/spec.schema.d.ts +1 -1
- package/dist/spec.schema.js +49 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -929,6 +929,27 @@ var drawTextRowSchema = z2.object({
|
|
|
929
929
|
defaultColor: colorHexSchema2.default("#FFFFFF"),
|
|
930
930
|
opacity: z2.number().min(0).max(1).default(1)
|
|
931
931
|
}).strict();
|
|
932
|
+
var drawStatsBarItemSchema = z2.object({
|
|
933
|
+
value: z2.string().min(1).max(50),
|
|
934
|
+
label: z2.string().min(1).max(100)
|
|
935
|
+
}).strict();
|
|
936
|
+
var drawStatsBarSchema = z2.object({
|
|
937
|
+
type: z2.literal("stats-bar"),
|
|
938
|
+
y: z2.number().describe("Vertical position of the stats bar"),
|
|
939
|
+
items: z2.array(drawStatsBarItemSchema).min(1).max(8),
|
|
940
|
+
separator: z2.enum(["dot", "pipe", "none"]).default("dot"),
|
|
941
|
+
valueColor: colorHexSchema2.default("#FFFFFF"),
|
|
942
|
+
valueFontSize: z2.number().min(8).max(72).default(18),
|
|
943
|
+
valueFontWeight: z2.number().int().min(100).max(900).default(700),
|
|
944
|
+
valueFontFamily: drawFontFamilySchema.default("mono"),
|
|
945
|
+
labelColor: colorHexSchema2.default("#AAAAAA"),
|
|
946
|
+
labelFontSize: z2.number().min(8).max(72).default(14),
|
|
947
|
+
labelFontWeight: z2.number().int().min(100).max(900).default(400),
|
|
948
|
+
labelFontFamily: drawFontFamilySchema.default("body"),
|
|
949
|
+
separatorColor: colorHexSchema2.default("#666666"),
|
|
950
|
+
gap: z2.number().min(0).max(100).default(24),
|
|
951
|
+
opacity: z2.number().min(0).max(1).default(1)
|
|
952
|
+
}).strict();
|
|
932
953
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
933
954
|
drawRectSchema,
|
|
934
955
|
drawCircleSchema,
|
|
@@ -940,7 +961,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
940
961
|
drawBadgeSchema,
|
|
941
962
|
drawGradientRectSchema,
|
|
942
963
|
drawGridSchema,
|
|
943
|
-
drawTextRowSchema
|
|
964
|
+
drawTextRowSchema,
|
|
965
|
+
drawStatsBarSchema
|
|
944
966
|
]);
|
|
945
967
|
var defaultCanvas = {
|
|
946
968
|
width: 1200,
|
|
@@ -1142,6 +1164,24 @@ var imageElementSchema = z2.object({
|
|
|
1142
1164
|
fit: z2.enum(["contain", "cover", "fill", "none"]).default("contain"),
|
|
1143
1165
|
borderRadius: z2.number().min(0).default(0)
|
|
1144
1166
|
}).strict();
|
|
1167
|
+
var ringSegmentSchema = z2.object({
|
|
1168
|
+
color: colorHexSchema2
|
|
1169
|
+
}).strict();
|
|
1170
|
+
var ringElementSchema = z2.object({
|
|
1171
|
+
type: z2.literal("ring"),
|
|
1172
|
+
id: z2.string().min(1).max(120),
|
|
1173
|
+
radius: z2.number().min(8).max(512).default(48),
|
|
1174
|
+
strokeWidth: z2.number().min(1).max(32).default(2),
|
|
1175
|
+
label: z2.string().max(100).optional(),
|
|
1176
|
+
labelColor: colorHexSchema2.optional(),
|
|
1177
|
+
labelSize: z2.number().min(8).max(48).default(12),
|
|
1178
|
+
segments: z2.array(ringSegmentSchema).min(1).max(24).default([{ color: "#4A7BF7" }]),
|
|
1179
|
+
glowRadius: z2.number().min(0).max(64).default(0),
|
|
1180
|
+
glowColor: colorHexSchema2.optional(),
|
|
1181
|
+
showCycleArrows: z2.boolean().default(false),
|
|
1182
|
+
fill: colorHexSchema2.optional(),
|
|
1183
|
+
fillOpacity: z2.number().min(0).max(1).default(0.05)
|
|
1184
|
+
}).strict();
|
|
1145
1185
|
var elementSchema = z2.discriminatedUnion("type", [
|
|
1146
1186
|
cardElementSchema,
|
|
1147
1187
|
flowNodeElementSchema,
|
|
@@ -1150,7 +1190,8 @@ var elementSchema = z2.discriminatedUnion("type", [
|
|
|
1150
1190
|
terminalElementSchema,
|
|
1151
1191
|
textElementSchema,
|
|
1152
1192
|
shapeElementSchema,
|
|
1153
|
-
imageElementSchema
|
|
1193
|
+
imageElementSchema,
|
|
1194
|
+
ringElementSchema
|
|
1154
1195
|
]);
|
|
1155
1196
|
var diagramCenterSchema = z2.object({
|
|
1156
1197
|
x: z2.number(),
|
|
@@ -1271,8 +1312,13 @@ var decoratorSchema = z2.discriminatedUnion("type", [
|
|
|
1271
1312
|
}).strict(),
|
|
1272
1313
|
z2.object({
|
|
1273
1314
|
type: z2.literal("vignette"),
|
|
1315
|
+
mode: z2.enum(["radial", "edge"]).default("radial"),
|
|
1274
1316
|
intensity: z2.number().min(0).max(1).default(0.3),
|
|
1275
|
-
color: colorHexSchema2.default("#000000")
|
|
1317
|
+
color: colorHexSchema2.default("#000000"),
|
|
1318
|
+
edgeTopHeight: z2.number().min(0).max(200).default(35),
|
|
1319
|
+
edgeBottomHeight: z2.number().min(0).max(200).default(55),
|
|
1320
|
+
edgeTopOpacity: z2.number().min(0).max(1).default(0.3),
|
|
1321
|
+
edgeBottomOpacity: z2.number().min(0).max(1).default(0.4)
|
|
1276
1322
|
}).strict(),
|
|
1277
1323
|
z2.object({
|
|
1278
1324
|
type: z2.literal("gradient-overlay"),
|
|
@@ -2082,6 +2128,8 @@ function estimateElementHeight(element) {
|
|
|
2082
2128
|
return 130;
|
|
2083
2129
|
case "image":
|
|
2084
2130
|
return 220;
|
|
2131
|
+
case "ring":
|
|
2132
|
+
return element.radius * 2 + element.glowRadius * 2 + 16;
|
|
2085
2133
|
case "connection":
|
|
2086
2134
|
return 0;
|
|
2087
2135
|
}
|
|
@@ -2102,6 +2150,8 @@ function estimateElementWidth(element) {
|
|
|
2102
2150
|
return 280;
|
|
2103
2151
|
case "image":
|
|
2104
2152
|
return 320;
|
|
2153
|
+
case "ring":
|
|
2154
|
+
return element.radius * 2 + element.glowRadius * 2 + 16;
|
|
2105
2155
|
case "connection":
|
|
2106
2156
|
return 0;
|
|
2107
2157
|
}
|
|
@@ -2716,6 +2766,30 @@ function drawRainbowRule(ctx, x, y, width, thickness = 2, colors = [...DEFAULT_R
|
|
|
2716
2766
|
ctx.fill();
|
|
2717
2767
|
ctx.restore();
|
|
2718
2768
|
}
|
|
2769
|
+
function drawEdgeVignette(ctx, width, height, color = "#000000", topHeight = 35, bottomHeight = 55, topOpacity = 0.3, bottomOpacity = 0.4) {
|
|
2770
|
+
if (width <= 0 || height <= 0) {
|
|
2771
|
+
return;
|
|
2772
|
+
}
|
|
2773
|
+
if (topHeight > 0 && topOpacity > 0) {
|
|
2774
|
+
const topGradient = ctx.createLinearGradient(0, 0, 0, topHeight);
|
|
2775
|
+
topGradient.addColorStop(0, withAlpha2(color, clamp01(topOpacity)));
|
|
2776
|
+
topGradient.addColorStop(1, withAlpha2(color, 0));
|
|
2777
|
+
ctx.save();
|
|
2778
|
+
ctx.fillStyle = topGradient;
|
|
2779
|
+
ctx.fillRect(0, 0, width, topHeight);
|
|
2780
|
+
ctx.restore();
|
|
2781
|
+
}
|
|
2782
|
+
if (bottomHeight > 0 && bottomOpacity > 0) {
|
|
2783
|
+
const bottomY = height - bottomHeight;
|
|
2784
|
+
const bottomGradient = ctx.createLinearGradient(0, bottomY, 0, height);
|
|
2785
|
+
bottomGradient.addColorStop(0, withAlpha2(color, 0));
|
|
2786
|
+
bottomGradient.addColorStop(1, withAlpha2(color, clamp01(bottomOpacity)));
|
|
2787
|
+
ctx.save();
|
|
2788
|
+
ctx.fillStyle = bottomGradient;
|
|
2789
|
+
ctx.fillRect(0, bottomY, width, bottomHeight);
|
|
2790
|
+
ctx.restore();
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2719
2793
|
function drawVignette(ctx, width, height, intensity = 0.3, color = "#000000") {
|
|
2720
2794
|
if (width <= 0 || height <= 0 || intensity <= 0) {
|
|
2721
2795
|
return;
|
|
@@ -4621,10 +4695,118 @@ function renderDrawCommands(ctx, commands, theme) {
|
|
|
4621
4695
|
});
|
|
4622
4696
|
break;
|
|
4623
4697
|
}
|
|
4698
|
+
case "stats-bar": {
|
|
4699
|
+
const barRect = renderStatsBar(ctx, command, theme);
|
|
4700
|
+
rendered.push({
|
|
4701
|
+
id,
|
|
4702
|
+
kind: "draw",
|
|
4703
|
+
bounds: barRect,
|
|
4704
|
+
foregroundColor: command.valueColor,
|
|
4705
|
+
backgroundColor: theme.background
|
|
4706
|
+
});
|
|
4707
|
+
break;
|
|
4708
|
+
}
|
|
4624
4709
|
}
|
|
4625
4710
|
}
|
|
4626
4711
|
return rendered;
|
|
4627
4712
|
}
|
|
4713
|
+
function renderStatsBar(ctx, command, theme) {
|
|
4714
|
+
const canvasWidth = ctx.canvas.width;
|
|
4715
|
+
const valueFontFamily = resolveDrawFont(theme, command.valueFontFamily);
|
|
4716
|
+
const labelFontFamily = resolveDrawFont(theme, command.labelFontFamily);
|
|
4717
|
+
const spaceWidth = 4;
|
|
4718
|
+
const measuredItems = [];
|
|
4719
|
+
for (const item of command.items) {
|
|
4720
|
+
applyFont(ctx, {
|
|
4721
|
+
size: command.valueFontSize,
|
|
4722
|
+
weight: command.valueFontWeight,
|
|
4723
|
+
family: valueFontFamily
|
|
4724
|
+
});
|
|
4725
|
+
const valueWidth = ctx.measureText(item.value).width;
|
|
4726
|
+
applyFont(ctx, {
|
|
4727
|
+
size: command.labelFontSize,
|
|
4728
|
+
weight: command.labelFontWeight,
|
|
4729
|
+
family: labelFontFamily
|
|
4730
|
+
});
|
|
4731
|
+
const labelWidth = ctx.measureText(item.label).width;
|
|
4732
|
+
measuredItems.push({
|
|
4733
|
+
valueWidth,
|
|
4734
|
+
labelWidth,
|
|
4735
|
+
totalWidth: valueWidth + spaceWidth + labelWidth
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
let separatorWidth = 0;
|
|
4739
|
+
let separatorText = "";
|
|
4740
|
+
if (command.separator !== "none" && command.items.length > 1) {
|
|
4741
|
+
separatorText = command.separator === "dot" ? "\xB7" : "|";
|
|
4742
|
+
const sepFontSize = Math.max(command.valueFontSize, command.labelFontSize);
|
|
4743
|
+
applyFont(ctx, { size: sepFontSize, weight: 400, family: labelFontFamily });
|
|
4744
|
+
separatorWidth = ctx.measureText(separatorText).width;
|
|
4745
|
+
}
|
|
4746
|
+
const itemsWidth = measuredItems.reduce((sum, m) => sum + m.totalWidth, 0);
|
|
4747
|
+
const gapCount = command.items.length - 1;
|
|
4748
|
+
const totalWidth = itemsWidth + gapCount * (command.gap + separatorWidth);
|
|
4749
|
+
let cursorX = (canvasWidth - totalWidth) / 2;
|
|
4750
|
+
const startX = cursorX;
|
|
4751
|
+
applyFont(ctx, {
|
|
4752
|
+
size: command.valueFontSize,
|
|
4753
|
+
weight: command.valueFontWeight,
|
|
4754
|
+
family: valueFontFamily
|
|
4755
|
+
});
|
|
4756
|
+
const valueMetrics = ctx.measureText("M");
|
|
4757
|
+
const valueAscent = valueMetrics.actualBoundingBoxAscent || command.valueFontSize * 0.75;
|
|
4758
|
+
const valueDescent = valueMetrics.actualBoundingBoxDescent || command.valueFontSize * 0.25;
|
|
4759
|
+
applyFont(ctx, {
|
|
4760
|
+
size: command.labelFontSize,
|
|
4761
|
+
weight: command.labelFontWeight,
|
|
4762
|
+
family: labelFontFamily
|
|
4763
|
+
});
|
|
4764
|
+
const labelMetrics = ctx.measureText("M");
|
|
4765
|
+
const labelAscent = labelMetrics.actualBoundingBoxAscent || command.labelFontSize * 0.75;
|
|
4766
|
+
const labelDescent = labelMetrics.actualBoundingBoxDescent || command.labelFontSize * 0.25;
|
|
4767
|
+
const maxAscent = Math.max(valueAscent, labelAscent);
|
|
4768
|
+
const maxDescent = Math.max(valueDescent, labelDescent);
|
|
4769
|
+
withOpacity(ctx, command.opacity, () => {
|
|
4770
|
+
for (let i = 0; i < command.items.length; i++) {
|
|
4771
|
+
const item = command.items[i];
|
|
4772
|
+
const measured = measuredItems[i];
|
|
4773
|
+
applyFont(ctx, {
|
|
4774
|
+
size: command.valueFontSize,
|
|
4775
|
+
weight: command.valueFontWeight,
|
|
4776
|
+
family: valueFontFamily
|
|
4777
|
+
});
|
|
4778
|
+
ctx.fillStyle = command.valueColor;
|
|
4779
|
+
ctx.textAlign = "left";
|
|
4780
|
+
ctx.textBaseline = "alphabetic";
|
|
4781
|
+
ctx.fillText(item.value, cursorX, command.y);
|
|
4782
|
+
cursorX += measured.valueWidth + spaceWidth;
|
|
4783
|
+
applyFont(ctx, {
|
|
4784
|
+
size: command.labelFontSize,
|
|
4785
|
+
weight: command.labelFontWeight,
|
|
4786
|
+
family: labelFontFamily
|
|
4787
|
+
});
|
|
4788
|
+
ctx.fillStyle = command.labelColor;
|
|
4789
|
+
ctx.fillText(item.label, cursorX, command.y);
|
|
4790
|
+
cursorX += measured.labelWidth;
|
|
4791
|
+
if (i < command.items.length - 1 && command.separator !== "none") {
|
|
4792
|
+
const sepFontSize = Math.max(command.valueFontSize, command.labelFontSize);
|
|
4793
|
+
applyFont(ctx, { size: sepFontSize, weight: 400, family: labelFontFamily });
|
|
4794
|
+
ctx.fillStyle = command.separatorColor;
|
|
4795
|
+
ctx.textAlign = "center";
|
|
4796
|
+
ctx.fillText(separatorText, cursorX + command.gap / 2 + separatorWidth / 2, command.y);
|
|
4797
|
+
ctx.textAlign = "left";
|
|
4798
|
+
cursorX += command.gap + separatorWidth;
|
|
4799
|
+
}
|
|
4800
|
+
}
|
|
4801
|
+
});
|
|
4802
|
+
const height = Math.max(1, maxAscent + maxDescent);
|
|
4803
|
+
return {
|
|
4804
|
+
x: startX,
|
|
4805
|
+
y: command.y - maxAscent,
|
|
4806
|
+
width: Math.max(1, totalWidth),
|
|
4807
|
+
height
|
|
4808
|
+
};
|
|
4809
|
+
}
|
|
4628
4810
|
|
|
4629
4811
|
// src/renderers/image.ts
|
|
4630
4812
|
import { loadImage } from "@napi-rs/canvas";
|
|
@@ -4711,6 +4893,110 @@ async function renderImageElement(ctx, image, bounds, theme) {
|
|
|
4711
4893
|
}
|
|
4712
4894
|
}
|
|
4713
4895
|
|
|
4896
|
+
// src/renderers/ring.ts
|
|
4897
|
+
function renderRingElement(ctx, ring, bounds, theme) {
|
|
4898
|
+
const cx = bounds.x + bounds.width / 2;
|
|
4899
|
+
const cy = bounds.y + bounds.height / 2;
|
|
4900
|
+
const { radius, strokeWidth, segments } = ring;
|
|
4901
|
+
if (ring.glowRadius > 0) {
|
|
4902
|
+
const glowColor = ring.glowColor ?? segments[0].color;
|
|
4903
|
+
ctx.save();
|
|
4904
|
+
ctx.globalAlpha = 0.15;
|
|
4905
|
+
ctx.beginPath();
|
|
4906
|
+
ctx.arc(cx, cy, radius + ring.glowRadius, 0, Math.PI * 2);
|
|
4907
|
+
ctx.fillStyle = glowColor;
|
|
4908
|
+
ctx.fill();
|
|
4909
|
+
ctx.restore();
|
|
4910
|
+
}
|
|
4911
|
+
if (ring.fill || ring.fillOpacity > 0) {
|
|
4912
|
+
const fillColor = ring.fill ?? segments[0].color;
|
|
4913
|
+
ctx.save();
|
|
4914
|
+
ctx.globalAlpha = ring.fillOpacity;
|
|
4915
|
+
ctx.beginPath();
|
|
4916
|
+
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
|
|
4917
|
+
ctx.fillStyle = fillColor;
|
|
4918
|
+
ctx.fill();
|
|
4919
|
+
ctx.restore();
|
|
4920
|
+
}
|
|
4921
|
+
ctx.save();
|
|
4922
|
+
ctx.globalAlpha = 0.2;
|
|
4923
|
+
ctx.beginPath();
|
|
4924
|
+
ctx.arc(cx, cy, radius, 0, Math.PI * 2);
|
|
4925
|
+
ctx.strokeStyle = theme.border;
|
|
4926
|
+
ctx.lineWidth = strokeWidth;
|
|
4927
|
+
ctx.stroke();
|
|
4928
|
+
ctx.restore();
|
|
4929
|
+
const segmentAngle = 2 * Math.PI / segments.length;
|
|
4930
|
+
for (let i = 0; i < segments.length; i++) {
|
|
4931
|
+
const startAngle = i * segmentAngle - Math.PI / 2;
|
|
4932
|
+
ctx.beginPath();
|
|
4933
|
+
ctx.arc(cx, cy, radius, startAngle, startAngle + segmentAngle);
|
|
4934
|
+
ctx.strokeStyle = segments[i].color;
|
|
4935
|
+
ctx.lineWidth = strokeWidth;
|
|
4936
|
+
ctx.stroke();
|
|
4937
|
+
}
|
|
4938
|
+
if (ring.showCycleArrows) {
|
|
4939
|
+
const arrowArcRadius = radius + strokeWidth + 4;
|
|
4940
|
+
const arrowColor = segments[0].color;
|
|
4941
|
+
const numArrows = Math.min(segments.length, 4);
|
|
4942
|
+
const arrowSpacing = 2 * Math.PI / numArrows;
|
|
4943
|
+
for (let i = 0; i < numArrows; i++) {
|
|
4944
|
+
const baseAngle = i * arrowSpacing - Math.PI / 2;
|
|
4945
|
+
const arcStart = baseAngle + 0.15;
|
|
4946
|
+
const arcEnd = baseAngle + arrowSpacing - 0.15;
|
|
4947
|
+
ctx.beginPath();
|
|
4948
|
+
ctx.arc(cx, cy, arrowArcRadius, arcStart, arcEnd);
|
|
4949
|
+
ctx.strokeStyle = arrowColor;
|
|
4950
|
+
ctx.lineWidth = Math.max(1, strokeWidth * 0.6);
|
|
4951
|
+
ctx.stroke();
|
|
4952
|
+
const headAngle = arcEnd;
|
|
4953
|
+
const headX = cx + arrowArcRadius * Math.cos(headAngle);
|
|
4954
|
+
const headY = cy + arrowArcRadius * Math.sin(headAngle);
|
|
4955
|
+
const tangentAngle = headAngle + Math.PI / 2;
|
|
4956
|
+
const headSize = Math.max(4, strokeWidth * 2);
|
|
4957
|
+
ctx.beginPath();
|
|
4958
|
+
ctx.moveTo(headX, headY);
|
|
4959
|
+
ctx.lineTo(
|
|
4960
|
+
headX - headSize * Math.cos(tangentAngle - 0.4),
|
|
4961
|
+
headY - headSize * Math.sin(tangentAngle - 0.4)
|
|
4962
|
+
);
|
|
4963
|
+
ctx.lineTo(
|
|
4964
|
+
headX - headSize * Math.cos(tangentAngle + 0.4),
|
|
4965
|
+
headY - headSize * Math.sin(tangentAngle + 0.4)
|
|
4966
|
+
);
|
|
4967
|
+
ctx.closePath();
|
|
4968
|
+
ctx.fillStyle = arrowColor;
|
|
4969
|
+
ctx.fill();
|
|
4970
|
+
}
|
|
4971
|
+
}
|
|
4972
|
+
if (ring.label) {
|
|
4973
|
+
const labelColor = ring.labelColor ?? theme.text;
|
|
4974
|
+
const labelSize = ring.labelSize;
|
|
4975
|
+
const bodyFont = resolveFont(theme.fonts.body, "body");
|
|
4976
|
+
applyFont(ctx, { size: labelSize, weight: 500, family: bodyFont });
|
|
4977
|
+
ctx.fillStyle = labelColor;
|
|
4978
|
+
ctx.textAlign = "center";
|
|
4979
|
+
ctx.textBaseline = "middle";
|
|
4980
|
+
const lines = ring.label.split("\\n");
|
|
4981
|
+
const lineHeight = labelSize * 1.3;
|
|
4982
|
+
const totalHeight = lines.length * lineHeight;
|
|
4983
|
+
const startY = cy - totalHeight / 2 + lineHeight / 2;
|
|
4984
|
+
for (let i = 0; i < lines.length; i++) {
|
|
4985
|
+
ctx.fillText(lines[i], cx, startY + i * lineHeight);
|
|
4986
|
+
}
|
|
4987
|
+
ctx.textAlign = "left";
|
|
4988
|
+
ctx.textBaseline = "alphabetic";
|
|
4989
|
+
}
|
|
4990
|
+
return [
|
|
4991
|
+
{
|
|
4992
|
+
id: `ring-${ring.id}`,
|
|
4993
|
+
kind: "shape",
|
|
4994
|
+
bounds,
|
|
4995
|
+
foregroundColor: segments[0].color
|
|
4996
|
+
}
|
|
4997
|
+
];
|
|
4998
|
+
}
|
|
4999
|
+
|
|
4714
5000
|
// src/renderers/shape.ts
|
|
4715
5001
|
function renderShapeElement(ctx, shape, bounds, theme) {
|
|
4716
5002
|
const fill = shape.fill ?? theme.surfaceMuted;
|
|
@@ -5146,7 +5432,16 @@ async function renderDesign(input, options = {}) {
|
|
|
5146
5432
|
const deferredVignettes = [];
|
|
5147
5433
|
for (const [index, decorator] of spec.decorators.entries()) {
|
|
5148
5434
|
if (decorator.type === "vignette") {
|
|
5149
|
-
deferredVignettes.push({
|
|
5435
|
+
deferredVignettes.push({
|
|
5436
|
+
index,
|
|
5437
|
+
mode: decorator.mode,
|
|
5438
|
+
intensity: decorator.intensity,
|
|
5439
|
+
color: decorator.color,
|
|
5440
|
+
edgeTopHeight: decorator.edgeTopHeight,
|
|
5441
|
+
edgeBottomHeight: decorator.edgeBottomHeight,
|
|
5442
|
+
edgeTopOpacity: decorator.edgeTopOpacity,
|
|
5443
|
+
edgeBottomOpacity: decorator.edgeBottomOpacity
|
|
5444
|
+
});
|
|
5150
5445
|
continue;
|
|
5151
5446
|
}
|
|
5152
5447
|
if (decorator.type === "gradient-overlay") {
|
|
@@ -5219,6 +5514,9 @@ async function renderDesign(input, options = {}) {
|
|
|
5219
5514
|
case "image":
|
|
5220
5515
|
elements.push(...await renderImageElement(ctx, element, rect, theme));
|
|
5221
5516
|
break;
|
|
5517
|
+
case "ring":
|
|
5518
|
+
elements.push(...renderRingElement(ctx, element, rect, theme));
|
|
5519
|
+
break;
|
|
5222
5520
|
}
|
|
5223
5521
|
}
|
|
5224
5522
|
const nodeBounds = spec.elements.filter((element) => element.type !== "connection").map((element) => elementRects.get(element.id)).filter((rect) => rect != null);
|
|
@@ -5273,7 +5571,20 @@ async function renderDesign(input, options = {}) {
|
|
|
5273
5571
|
}
|
|
5274
5572
|
elements.push(...renderDrawCommands(ctx, spec.draw, theme));
|
|
5275
5573
|
for (const vignette of deferredVignettes) {
|
|
5276
|
-
|
|
5574
|
+
if (vignette.mode === "edge") {
|
|
5575
|
+
drawEdgeVignette(
|
|
5576
|
+
ctx,
|
|
5577
|
+
spec.canvas.width,
|
|
5578
|
+
spec.canvas.height,
|
|
5579
|
+
vignette.color,
|
|
5580
|
+
vignette.edgeTopHeight,
|
|
5581
|
+
vignette.edgeBottomHeight,
|
|
5582
|
+
vignette.edgeTopOpacity,
|
|
5583
|
+
vignette.edgeBottomOpacity
|
|
5584
|
+
);
|
|
5585
|
+
} else {
|
|
5586
|
+
drawVignette(ctx, spec.canvas.width, spec.canvas.height, vignette.intensity, vignette.color);
|
|
5587
|
+
}
|
|
5277
5588
|
elements.push({
|
|
5278
5589
|
id: `decorator-vignette-${vignette.index}`,
|
|
5279
5590
|
kind: "vignette",
|
package/dist/qa.d.ts
CHANGED
package/dist/qa.js
CHANGED
|
@@ -663,6 +663,27 @@ var drawTextRowSchema = z2.object({
|
|
|
663
663
|
defaultColor: colorHexSchema2.default("#FFFFFF"),
|
|
664
664
|
opacity: z2.number().min(0).max(1).default(1)
|
|
665
665
|
}).strict();
|
|
666
|
+
var drawStatsBarItemSchema = z2.object({
|
|
667
|
+
value: z2.string().min(1).max(50),
|
|
668
|
+
label: z2.string().min(1).max(100)
|
|
669
|
+
}).strict();
|
|
670
|
+
var drawStatsBarSchema = z2.object({
|
|
671
|
+
type: z2.literal("stats-bar"),
|
|
672
|
+
y: z2.number().describe("Vertical position of the stats bar"),
|
|
673
|
+
items: z2.array(drawStatsBarItemSchema).min(1).max(8),
|
|
674
|
+
separator: z2.enum(["dot", "pipe", "none"]).default("dot"),
|
|
675
|
+
valueColor: colorHexSchema2.default("#FFFFFF"),
|
|
676
|
+
valueFontSize: z2.number().min(8).max(72).default(18),
|
|
677
|
+
valueFontWeight: z2.number().int().min(100).max(900).default(700),
|
|
678
|
+
valueFontFamily: drawFontFamilySchema.default("mono"),
|
|
679
|
+
labelColor: colorHexSchema2.default("#AAAAAA"),
|
|
680
|
+
labelFontSize: z2.number().min(8).max(72).default(14),
|
|
681
|
+
labelFontWeight: z2.number().int().min(100).max(900).default(400),
|
|
682
|
+
labelFontFamily: drawFontFamilySchema.default("body"),
|
|
683
|
+
separatorColor: colorHexSchema2.default("#666666"),
|
|
684
|
+
gap: z2.number().min(0).max(100).default(24),
|
|
685
|
+
opacity: z2.number().min(0).max(1).default(1)
|
|
686
|
+
}).strict();
|
|
666
687
|
var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
667
688
|
drawRectSchema,
|
|
668
689
|
drawCircleSchema,
|
|
@@ -674,7 +695,8 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
|
|
|
674
695
|
drawBadgeSchema,
|
|
675
696
|
drawGradientRectSchema,
|
|
676
697
|
drawGridSchema,
|
|
677
|
-
drawTextRowSchema
|
|
698
|
+
drawTextRowSchema,
|
|
699
|
+
drawStatsBarSchema
|
|
678
700
|
]);
|
|
679
701
|
var defaultCanvas = {
|
|
680
702
|
width: 1200,
|
|
@@ -875,6 +897,24 @@ var imageElementSchema = z2.object({
|
|
|
875
897
|
fit: z2.enum(["contain", "cover", "fill", "none"]).default("contain"),
|
|
876
898
|
borderRadius: z2.number().min(0).default(0)
|
|
877
899
|
}).strict();
|
|
900
|
+
var ringSegmentSchema = z2.object({
|
|
901
|
+
color: colorHexSchema2
|
|
902
|
+
}).strict();
|
|
903
|
+
var ringElementSchema = z2.object({
|
|
904
|
+
type: z2.literal("ring"),
|
|
905
|
+
id: z2.string().min(1).max(120),
|
|
906
|
+
radius: z2.number().min(8).max(512).default(48),
|
|
907
|
+
strokeWidth: z2.number().min(1).max(32).default(2),
|
|
908
|
+
label: z2.string().max(100).optional(),
|
|
909
|
+
labelColor: colorHexSchema2.optional(),
|
|
910
|
+
labelSize: z2.number().min(8).max(48).default(12),
|
|
911
|
+
segments: z2.array(ringSegmentSchema).min(1).max(24).default([{ color: "#4A7BF7" }]),
|
|
912
|
+
glowRadius: z2.number().min(0).max(64).default(0),
|
|
913
|
+
glowColor: colorHexSchema2.optional(),
|
|
914
|
+
showCycleArrows: z2.boolean().default(false),
|
|
915
|
+
fill: colorHexSchema2.optional(),
|
|
916
|
+
fillOpacity: z2.number().min(0).max(1).default(0.05)
|
|
917
|
+
}).strict();
|
|
878
918
|
var elementSchema = z2.discriminatedUnion("type", [
|
|
879
919
|
cardElementSchema,
|
|
880
920
|
flowNodeElementSchema,
|
|
@@ -883,7 +923,8 @@ var elementSchema = z2.discriminatedUnion("type", [
|
|
|
883
923
|
terminalElementSchema,
|
|
884
924
|
textElementSchema,
|
|
885
925
|
shapeElementSchema,
|
|
886
|
-
imageElementSchema
|
|
926
|
+
imageElementSchema,
|
|
927
|
+
ringElementSchema
|
|
887
928
|
]);
|
|
888
929
|
var diagramCenterSchema = z2.object({
|
|
889
930
|
x: z2.number(),
|
|
@@ -1004,8 +1045,13 @@ var decoratorSchema = z2.discriminatedUnion("type", [
|
|
|
1004
1045
|
}).strict(),
|
|
1005
1046
|
z2.object({
|
|
1006
1047
|
type: z2.literal("vignette"),
|
|
1048
|
+
mode: z2.enum(["radial", "edge"]).default("radial"),
|
|
1007
1049
|
intensity: z2.number().min(0).max(1).default(0.3),
|
|
1008
|
-
color: colorHexSchema2.default("#000000")
|
|
1050
|
+
color: colorHexSchema2.default("#000000"),
|
|
1051
|
+
edgeTopHeight: z2.number().min(0).max(200).default(35),
|
|
1052
|
+
edgeBottomHeight: z2.number().min(0).max(200).default(55),
|
|
1053
|
+
edgeTopOpacity: z2.number().min(0).max(1).default(0.3),
|
|
1054
|
+
edgeBottomOpacity: z2.number().min(0).max(1).default(0.4)
|
|
1009
1055
|
}).strict(),
|
|
1010
1056
|
z2.object({
|
|
1011
1057
|
type: z2.literal("gradient-overlay"),
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { i as DEFAULT_GENERATOR_VERSION, U as IterationMeta, W as LayoutSnapshot, a as Rect, Z as RenderDesignOptions, R as RenderMetadata, _ as RenderResult, d as RenderedElement, a5 as WrittenArtifacts, a8 as computeSpecHash, ar as inferSidecarPath, au as renderDesign, aw as writeRenderArtifacts } from './spec.schema-
|
|
1
|
+
export { i as DEFAULT_GENERATOR_VERSION, U as IterationMeta, W as LayoutSnapshot, a as Rect, Z as RenderDesignOptions, R as RenderMetadata, _ as RenderResult, d as RenderedElement, a5 as WrittenArtifacts, a8 as computeSpecHash, ar as inferSidecarPath, au as renderDesign, aw as writeRenderArtifacts } from './spec.schema-De-IkUjn.js';
|
|
2
2
|
import 'zod';
|
|
3
3
|
import '@napi-rs/canvas';
|