@spectratools/graphic-designer-cli 0.9.0 → 0.10.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.
@@ -1,3 +1,3 @@
1
- export { i as DEFAULT_GENERATOR_VERSION, S as LayoutSnapshot, a as Rect, R as RenderMetadata, W as RenderResult, d as RenderedElement, a1 as WrittenArtifacts, a4 as computeSpecHash, an as inferSidecarPath, aq as renderDesign, as as writeRenderArtifacts } from './spec.schema-B_Z-KNqt.js';
1
+ export { i as DEFAULT_GENERATOR_VERSION, S as IterationMeta, V as LayoutSnapshot, a as Rect, Y as RenderDesignOptions, R as RenderMetadata, Z as RenderResult, d as RenderedElement, a4 as WrittenArtifacts, a7 as computeSpecHash, aq as inferSidecarPath, at as renderDesign, av as writeRenderArtifacts } from './spec.schema-B6sXTTou.js';
2
2
  import 'zod';
3
3
  import '@napi-rs/canvas';
package/dist/renderer.js CHANGED
@@ -2008,16 +2008,6 @@ function drawBezier(ctx, points, style) {
2008
2008
  ctx.quadraticCurveTo(penultimate.x, penultimate.y, last.x, last.y);
2009
2009
  ctx.stroke();
2010
2010
  }
2011
- function drawOrthogonalPath(ctx, from, to, style) {
2012
- const midX = (from.x + to.x) / 2;
2013
- applyLineStyle(ctx, style);
2014
- ctx.beginPath();
2015
- ctx.moveTo(from.x, from.y);
2016
- ctx.lineTo(midX, from.y);
2017
- ctx.lineTo(midX, to.y);
2018
- ctx.lineTo(to.x, to.y);
2019
- ctx.stroke();
2020
- }
2021
2011
 
2022
2012
  // src/renderers/connection.ts
2023
2013
  var ELLIPSE_KAPPA = 4 * (Math.sqrt(2) - 1) / 3;
@@ -2257,11 +2247,36 @@ function pointAlongPolyline(points, t) {
2257
2247
  }
2258
2248
  return points[points.length - 1];
2259
2249
  }
2260
- function drawCubicInterpolatedPath(ctx, points, style) {
2250
+ function createConnectionGradient(ctx, start, end, fromColor, baseColor, toColor) {
2251
+ const gradient = ctx.createLinearGradient(start.x, start.y, end.x, end.y);
2252
+ gradient.addColorStop(0, fromColor);
2253
+ gradient.addColorStop(0.5, baseColor);
2254
+ gradient.addColorStop(1, toColor);
2255
+ return gradient;
2256
+ }
2257
+ function resolveConnectionStroke(ctx, start, end, fromColor, baseColor, toColor) {
2258
+ if (!fromColor || !toColor) {
2259
+ return baseColor;
2260
+ }
2261
+ return createConnectionGradient(ctx, start, end, fromColor, baseColor, toColor);
2262
+ }
2263
+ function drawOrthogonalPathWithStroke(ctx, from, to, style, stroke) {
2264
+ const midX = (from.x + to.x) / 2;
2265
+ ctx.strokeStyle = stroke;
2266
+ ctx.lineWidth = style.width;
2267
+ ctx.setLineDash(style.dash ?? []);
2268
+ ctx.beginPath();
2269
+ ctx.moveTo(from.x, from.y);
2270
+ ctx.lineTo(midX, from.y);
2271
+ ctx.lineTo(midX, to.y);
2272
+ ctx.lineTo(to.x, to.y);
2273
+ ctx.stroke();
2274
+ }
2275
+ function drawCubicInterpolatedPath(ctx, points, style, stroke) {
2261
2276
  if (points.length < 2) {
2262
2277
  return;
2263
2278
  }
2264
- ctx.strokeStyle = style.color;
2279
+ ctx.strokeStyle = stroke;
2265
2280
  ctx.lineWidth = style.width;
2266
2281
  ctx.setLineDash(style.dash ?? []);
2267
2282
  ctx.beginPath();
@@ -2332,7 +2347,8 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
2332
2347
  conn.fromAnchor,
2333
2348
  conn.toAnchor
2334
2349
  );
2335
- ctx.strokeStyle = style.color;
2350
+ const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
2351
+ ctx.strokeStyle = stroke;
2336
2352
  ctx.lineWidth = style.width;
2337
2353
  ctx.setLineDash(style.dash ?? []);
2338
2354
  ctx.beginPath();
@@ -2374,7 +2390,8 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
2374
2390
  );
2375
2391
  const [p0, cp1, cp2, pMid] = first;
2376
2392
  const [, cp3, cp4, p3] = second;
2377
- ctx.strokeStyle = style.color;
2393
+ const stroke = resolveConnectionStroke(ctx, p0, p3, conn.fromColor, style.color, conn.toColor);
2394
+ ctx.strokeStyle = stroke;
2378
2395
  ctx.lineWidth = style.width;
2379
2396
  ctx.setLineDash(style.dash ?? []);
2380
2397
  ctx.beginPath();
@@ -2417,10 +2434,18 @@ function renderConnection(ctx, conn, fromBounds, toBounds, theme, edgeRoute, opt
2417
2434
  endPoint = linePoints[linePoints.length - 1] ?? linePoints[0];
2418
2435
  startAngle = Math.atan2(startSegment.y - linePoints[0].y, startSegment.x - linePoints[0].x) + Math.PI;
2419
2436
  endAngle = Math.atan2(endPoint.y - endStart.y, endPoint.x - endStart.x);
2437
+ const stroke = resolveConnectionStroke(
2438
+ ctx,
2439
+ startPoint,
2440
+ endPoint,
2441
+ conn.fromColor,
2442
+ style.color,
2443
+ conn.toColor
2444
+ );
2420
2445
  if (useElkRoute) {
2421
- drawCubicInterpolatedPath(ctx, linePoints, style);
2446
+ drawCubicInterpolatedPath(ctx, linePoints, style, stroke);
2422
2447
  } else {
2423
- drawOrthogonalPath(ctx, startPoint, endPoint, style);
2448
+ drawOrthogonalPathWithStroke(ctx, startPoint, endPoint, style, stroke);
2424
2449
  }
2425
2450
  labelPoint = pointAlongPolyline(linePoints, labelT);
2426
2451
  }
@@ -2725,6 +2750,9 @@ function measureTextBounds(ctx, options) {
2725
2750
  function angleBetween(from, to) {
2726
2751
  return Math.atan2(to.y - from.y, to.x - from.x);
2727
2752
  }
2753
+ function degreesToRadians(angle) {
2754
+ return angle * Math.PI / 180;
2755
+ }
2728
2756
  function pathBounds(operations) {
2729
2757
  let minX = Number.POSITIVE_INFINITY;
2730
2758
  let minY = Number.POSITIVE_INFINITY;
@@ -2962,6 +2990,34 @@ function renderDrawCommands(ctx, commands, theme) {
2962
2990
  });
2963
2991
  break;
2964
2992
  }
2993
+ case "arc": {
2994
+ const startAngle = degreesToRadians(command.startAngle);
2995
+ const endAngle = degreesToRadians(command.endAngle);
2996
+ withOpacity(ctx, command.opacity, () => {
2997
+ applyDrawShadow(ctx, command.shadow);
2998
+ ctx.beginPath();
2999
+ ctx.setLineDash(command.dash ?? []);
3000
+ ctx.lineWidth = command.width;
3001
+ ctx.strokeStyle = command.color;
3002
+ ctx.arc(command.center.x, command.center.y, command.radius, startAngle, endAngle);
3003
+ ctx.stroke();
3004
+ });
3005
+ rendered.push({
3006
+ id,
3007
+ kind: "draw",
3008
+ bounds: expandRect(
3009
+ {
3010
+ x: command.center.x - command.radius,
3011
+ y: command.center.y - command.radius,
3012
+ width: command.radius * 2,
3013
+ height: command.radius * 2
3014
+ },
3015
+ command.width / 2
3016
+ ),
3017
+ foregroundColor: command.color
3018
+ });
3019
+ break;
3020
+ }
2965
3021
  case "bezier": {
2966
3022
  const points = command.points;
2967
3023
  withOpacity(ctx, command.opacity, () => {
@@ -3545,6 +3601,21 @@ var drawLineSchema = z2.object({
3545
3601
  opacity: z2.number().min(0).max(1).default(1),
3546
3602
  shadow: drawShadowSchema.optional()
3547
3603
  }).strict();
3604
+ var drawArcSchema = z2.object({
3605
+ type: z2.literal("arc"),
3606
+ center: z2.object({
3607
+ x: z2.number(),
3608
+ y: z2.number()
3609
+ }).strict(),
3610
+ radius: z2.number().positive(),
3611
+ startAngle: z2.number(),
3612
+ endAngle: z2.number(),
3613
+ color: colorHexSchema2.default("#FFFFFF"),
3614
+ width: z2.number().min(0.5).max(32).default(2),
3615
+ dash: z2.array(z2.number()).max(6).optional(),
3616
+ opacity: z2.number().min(0).max(1).default(1),
3617
+ shadow: drawShadowSchema.optional()
3618
+ }).strict();
3548
3619
  var drawPointSchema = z2.object({
3549
3620
  x: z2.number(),
3550
3621
  y: z2.number()
@@ -3629,6 +3700,7 @@ var drawCommandSchema = z2.discriminatedUnion("type", [
3629
3700
  drawCircleSchema,
3630
3701
  drawTextSchema,
3631
3702
  drawLineSchema,
3703
+ drawArcSchema,
3632
3704
  drawBezierSchema,
3633
3705
  drawPathSchema,
3634
3706
  drawBadgeSchema,
@@ -3764,6 +3836,8 @@ var connectionElementSchema = z2.object({
3764
3836
  label: z2.string().min(1).max(200).optional(),
3765
3837
  labelPosition: z2.enum(["start", "middle", "end"]).default("middle"),
3766
3838
  color: colorHexSchema2.optional(),
3839
+ fromColor: colorHexSchema2.optional(),
3840
+ toColor: colorHexSchema2.optional(),
3767
3841
  width: z2.number().min(0.5).max(10).optional(),
3768
3842
  strokeWidth: z2.number().min(0.5).max(10).default(2),
3769
3843
  arrowSize: z2.number().min(4).max(32).optional(),
@@ -4149,6 +4223,18 @@ async function renderDesign(input, options = {}) {
4149
4223
  const specHash = computeSpecHash(spec);
4150
4224
  const generatorVersion = options.generatorVersion ?? DEFAULT_GENERATOR_VERSION;
4151
4225
  const renderedAt = options.renderedAt ?? (/* @__PURE__ */ new Date()).toISOString();
4226
+ const iteration = options.iteration;
4227
+ if (iteration) {
4228
+ if (!Number.isInteger(iteration.iteration) || iteration.iteration <= 0) {
4229
+ throw new Error("Iteration metadata requires iteration to be a positive integer.");
4230
+ }
4231
+ if (iteration.maxIterations != null && (!Number.isInteger(iteration.maxIterations) || iteration.maxIterations <= 0)) {
4232
+ throw new Error("Iteration metadata requires maxIterations to be a positive integer.");
4233
+ }
4234
+ if (iteration.maxIterations != null && iteration.maxIterations < iteration.iteration) {
4235
+ throw new Error("Iteration metadata requires maxIterations to be >= iteration.");
4236
+ }
4237
+ }
4152
4238
  const renderScale = resolveRenderScale(spec);
4153
4239
  const canvas = createCanvas(spec.canvas.width * renderScale, spec.canvas.height * renderScale);
4154
4240
  const ctx = canvas.getContext("2d");
@@ -4389,7 +4475,8 @@ async function renderDesign(input, options = {}) {
4389
4475
  layout: {
4390
4476
  safeFrame,
4391
4477
  elements
4392
- }
4478
+ },
4479
+ ...iteration ? { iteration } : {}
4393
4480
  };
4394
4481
  return {
4395
4482
  png: pngBuffer,