@spectratools/graphic-designer-cli 0.3.2 → 0.6.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
1
  import 'zod';
2
- export { A as AutoLayoutConfig, B as BuiltInTheme, C as CardElement, e as CodeBlockElement, ae as CodeBlockStyle, f as ConnectionElement, g as ConstraintSpec, j as Decorator, k as DesignSafeFrame, D as DesignSpec, l as DrawBadge, m as DrawBezier, n as DrawCircle, b as DrawCommand, o as DrawFontFamily, p as DrawGradientRect, q as DrawLine, r as DrawPath, s as DrawPoint, t as DrawRect, u as DrawText, E as Element, F as FlowNodeElement, G as Gradient, v as GradientOverlayDecorator, af as GradientStop, y as GridLayoutConfig, I as ImageElement, L as LayoutConfig, ag as LinearGradient, M as ManualLayoutConfig, ah as RadialGradient, H as RainbowRuleDecorator, S as ShapeElement, K as StackLayoutConfig, N as TerminalElement, O as TextElement, c as Theme, P as ThemeInput, V as VignetteDecorator, Q as builtInThemeBackgrounds, U as builtInThemes, Y as defaultAutoLayout, Z as defaultCanvas, _ as defaultConstraints, $ as defaultGridLayout, a0 as defaultLayout, a1 as defaultStackLayout, a2 as defaultTheme, a3 as deriveSafeFrame, a4 as designSpecSchema, a8 as inferLayout, aa as parseDesignSpec, ac as resolveTheme } from './spec.schema-DhAI-tE8.js';
2
+ export { A as AutoLayoutConfig, B as BuiltInTheme, e as CardElement, f as CodeBlockElement, ap as CodeBlockStyle, C as ConnectionElement, g as ConstraintSpec, j as Decorator, k as DesignCardSpec, l as DesignSafeFrame, D as DesignSpec, m as DesignTheme, n as DiagramElement, o as DiagramLayout, p as DiagramSpec, q as DrawBadge, r as DrawBezier, s as DrawCircle, b as DrawCommand, t as DrawFontFamily, u as DrawGradientRect, v as DrawLine, w as DrawPath, x as DrawPoint, y as DrawRect, z as DrawText, E as Element, F as FlowNodeElement, aq as FlowNodeShadow, G as Gradient, H as GradientOverlayDecorator, ar as GradientStop, K as GridLayoutConfig, L as ImageElement, M as LayoutConfig, as as LinearGradient, O as ManualLayoutConfig, at as RadialGradient, P as RainbowRuleDecorator, S as ShapeElement, U as StackLayoutConfig, V as TerminalElement, W as TextElement, c as Theme, X as ThemeInput, Y as VignetteDecorator, _ as builtInThemeBackgrounds, $ as builtInThemes, a1 as connectionElementSchema, a2 as defaultAutoLayout, a3 as defaultCanvas, a4 as defaultConstraints, a5 as defaultGridLayout, a6 as defaultLayout, a7 as defaultStackLayout, a8 as defaultTheme, a9 as deriveSafeFrame, aa as designSpecSchema, ab as diagramElementSchema, ac as diagramLayoutSchema, ad as diagramSpecSchema, ah as flowNodeElementSchema, ai as inferLayout, ak as parseDesignSpec, al as parseDiagramSpec, an as resolveTheme } from './spec.schema-Dm_wOLTd.js';
3
3
  import '@napi-rs/canvas';
@@ -3,7 +3,62 @@ import { z as z2 } from "zod";
3
3
 
4
4
  // src/themes/builtin.ts
5
5
  import { z } from "zod";
6
- var colorHexSchema = z.string().regex(/^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, "Expected #RRGGBB or #RRGGBBAA color");
6
+
7
+ // src/utils/color.ts
8
+ var rgbaRegex = /^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*([01](?:\.\d+)?|0?\.\d+)\s*)?\)$/;
9
+ var hexColorRegex = /^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
10
+ function toHex(n) {
11
+ return n.toString(16).padStart(2, "0");
12
+ }
13
+ function parseRgbaToHex(color) {
14
+ const match = rgbaRegex.exec(color);
15
+ if (!match) {
16
+ throw new Error(`Invalid rgb/rgba color: ${color}`);
17
+ }
18
+ const r = Number.parseInt(match[1], 10);
19
+ const g = Number.parseInt(match[2], 10);
20
+ const b = Number.parseInt(match[3], 10);
21
+ if (r > 255 || g > 255 || b > 255) {
22
+ throw new Error(`RGB channel values must be 0-255, got: ${color}`);
23
+ }
24
+ if (match[4] !== void 0) {
25
+ const a = Number.parseFloat(match[4]);
26
+ if (a < 0 || a > 1) {
27
+ throw new Error(`Alpha value must be 0-1, got: ${a}`);
28
+ }
29
+ const alphaByte = Math.round(a * 255);
30
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}${toHex(alphaByte)}`;
31
+ }
32
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
33
+ }
34
+ function isRgbaColor(color) {
35
+ return rgbaRegex.test(color);
36
+ }
37
+ function isHexColor(color) {
38
+ return hexColorRegex.test(color);
39
+ }
40
+ function normalizeColor(color) {
41
+ if (isHexColor(color)) {
42
+ return color;
43
+ }
44
+ if (isRgbaColor(color)) {
45
+ return parseRgbaToHex(color);
46
+ }
47
+ throw new Error(`Expected #RRGGBB, #RRGGBBAA, rgb(), or rgba() color, got: ${color}`);
48
+ }
49
+
50
+ // src/themes/builtin.ts
51
+ var colorHexSchema = z.string().refine(
52
+ (v) => {
53
+ try {
54
+ normalizeColor(v);
55
+ return true;
56
+ } catch {
57
+ return false;
58
+ }
59
+ },
60
+ { message: "Expected #RRGGBB, #RRGGBBAA, rgb(), or rgba() color" }
61
+ ).transform((v) => normalizeColor(v));
7
62
  var fontFamilySchema = z.string().min(1).max(120);
8
63
  var codeThemeSchema = z.object({
9
64
  background: colorHexSchema,
@@ -194,7 +249,17 @@ function resolveTheme(theme) {
194
249
  }
195
250
 
196
251
  // src/spec.schema.ts
197
- var colorHexSchema2 = z2.string().regex(/^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/, "Expected #RRGGBB or #RRGGBBAA color");
252
+ var colorHexSchema2 = z2.string().refine(
253
+ (v) => {
254
+ try {
255
+ normalizeColor(v);
256
+ return true;
257
+ } catch {
258
+ return false;
259
+ }
260
+ },
261
+ { message: "Expected #RRGGBB, #RRGGBBAA, rgb(), or rgba() color" }
262
+ ).transform((v) => normalizeColor(v));
198
263
  var gradientStopSchema = z2.object({
199
264
  offset: z2.number().min(0).max(1),
200
265
  color: colorHexSchema2
@@ -379,13 +444,32 @@ var cardElementSchema = z2.object({
379
444
  tone: z2.enum(["neutral", "accent", "success", "warning", "error"]).default("neutral"),
380
445
  icon: z2.string().min(1).max(64).optional()
381
446
  }).strict();
447
+ var flowNodeShadowSchema = z2.object({
448
+ color: colorHexSchema2.optional(),
449
+ blur: z2.number().min(0).max(64).default(8),
450
+ offsetX: z2.number().min(-32).max(32).default(0),
451
+ offsetY: z2.number().min(-32).max(32).default(0),
452
+ opacity: z2.number().min(0).max(1).default(0.3)
453
+ }).strict();
382
454
  var flowNodeElementSchema = z2.object({
383
455
  type: z2.literal("flow-node"),
384
456
  id: z2.string().min(1).max(120),
385
- shape: z2.enum(["box", "rounded-box", "diamond", "circle", "pill", "cylinder", "parallelogram"]),
457
+ shape: z2.enum([
458
+ "box",
459
+ "rounded-box",
460
+ "diamond",
461
+ "circle",
462
+ "pill",
463
+ "cylinder",
464
+ "parallelogram",
465
+ "hexagon"
466
+ ]).default("rounded-box"),
386
467
  label: z2.string().min(1).max(200),
387
468
  sublabel: z2.string().min(1).max(300).optional(),
388
469
  sublabelColor: colorHexSchema2.optional(),
470
+ sublabel2: z2.string().min(1).max(300).optional(),
471
+ sublabel2Color: colorHexSchema2.optional(),
472
+ sublabel2FontSize: z2.number().min(8).max(32).optional(),
389
473
  labelColor: colorHexSchema2.optional(),
390
474
  labelFontSize: z2.number().min(10).max(48).optional(),
391
475
  color: colorHexSchema2.optional(),
@@ -394,20 +478,30 @@ var flowNodeElementSchema = z2.object({
394
478
  cornerRadius: z2.number().min(0).max(64).optional(),
395
479
  width: z2.number().int().min(40).max(800).optional(),
396
480
  height: z2.number().int().min(30).max(600).optional(),
397
- opacity: z2.number().min(0).max(1).default(1)
481
+ fillOpacity: z2.number().min(0).max(1).default(1),
482
+ opacity: z2.number().min(0).max(1).default(1),
483
+ badgeText: z2.string().min(1).max(32).optional(),
484
+ badgeColor: colorHexSchema2.optional(),
485
+ badgeBackground: colorHexSchema2.optional(),
486
+ badgePosition: z2.enum(["top", "inside-top"]).default("inside-top"),
487
+ shadow: flowNodeShadowSchema.optional()
398
488
  }).strict();
399
489
  var connectionElementSchema = z2.object({
400
490
  type: z2.literal("connection"),
401
491
  from: z2.string().min(1).max(120),
402
492
  to: z2.string().min(1).max(120),
403
493
  style: z2.enum(["solid", "dashed", "dotted"]).default("solid"),
494
+ strokeStyle: z2.enum(["solid", "dashed", "dotted"]).default("solid"),
404
495
  arrow: z2.enum(["end", "start", "both", "none"]).default("end"),
405
496
  label: z2.string().min(1).max(200).optional(),
406
497
  labelPosition: z2.enum(["start", "middle", "end"]).default("middle"),
407
498
  color: colorHexSchema2.optional(),
408
- width: z2.number().min(0.5).max(8).optional(),
499
+ width: z2.number().min(0.5).max(10).optional(),
500
+ strokeWidth: z2.number().min(0.5).max(10).default(2),
409
501
  arrowSize: z2.number().min(4).max(32).optional(),
410
- opacity: z2.number().min(0).max(1).default(1)
502
+ opacity: z2.number().min(0).max(1).default(1),
503
+ routing: z2.enum(["auto", "orthogonal", "curve", "arc"]).default("auto"),
504
+ tension: z2.number().min(0.1).max(0.8).default(0.35)
411
505
  }).strict();
412
506
  var codeBlockStyleSchema = z2.object({
413
507
  paddingVertical: z2.number().min(0).max(128).default(56),
@@ -476,6 +570,10 @@ var elementSchema = z2.discriminatedUnion("type", [
476
570
  shapeElementSchema,
477
571
  imageElementSchema
478
572
  ]);
573
+ var diagramCenterSchema = z2.object({
574
+ x: z2.number(),
575
+ y: z2.number()
576
+ }).strict();
479
577
  var autoLayoutConfigSchema = z2.object({
480
578
  mode: z2.literal("auto"),
481
579
  algorithm: z2.enum(["layered", "stress", "force", "radial", "box"]).default("layered"),
@@ -483,7 +581,17 @@ var autoLayoutConfigSchema = z2.object({
483
581
  nodeSpacing: z2.number().int().min(0).max(512).default(80),
484
582
  rankSpacing: z2.number().int().min(0).max(512).default(120),
485
583
  edgeRouting: z2.enum(["orthogonal", "polyline", "spline"]).default("polyline"),
486
- aspectRatio: z2.number().min(0.5).max(3).optional()
584
+ aspectRatio: z2.number().min(0.5).max(3).optional(),
585
+ /** ID of the root node for radial layout. Only relevant when algorithm is 'radial'. */
586
+ radialRoot: z2.string().min(1).max(120).optional(),
587
+ /** Fixed radius in pixels for radial layout. Only relevant when algorithm is 'radial'. */
588
+ radialRadius: z2.number().positive().optional(),
589
+ /** Compaction strategy for radial layout. Only relevant when algorithm is 'radial'. */
590
+ radialCompaction: z2.enum(["none", "radial", "wedge"]).optional(),
591
+ /** Sort strategy for radial layout node ordering. Only relevant when algorithm is 'radial'. */
592
+ radialSortBy: z2.enum(["id", "connections"]).optional(),
593
+ /** Explicit center used by curve/arc connection routing. */
594
+ diagramCenter: diagramCenterSchema.optional()
487
595
  }).strict();
488
596
  var gridLayoutConfigSchema = z2.object({
489
597
  mode: z2.literal("grid"),
@@ -491,13 +599,17 @@ var gridLayoutConfigSchema = z2.object({
491
599
  gap: z2.number().int().min(0).max(256).default(24),
492
600
  cardMinHeight: z2.number().int().min(32).max(4096).optional(),
493
601
  cardMaxHeight: z2.number().int().min(32).max(4096).optional(),
494
- equalHeight: z2.boolean().default(false)
602
+ equalHeight: z2.boolean().default(false),
603
+ /** Explicit center used by curve/arc connection routing. */
604
+ diagramCenter: diagramCenterSchema.optional()
495
605
  }).strict();
496
606
  var stackLayoutConfigSchema = z2.object({
497
607
  mode: z2.literal("stack"),
498
608
  direction: z2.enum(["vertical", "horizontal"]).default("vertical"),
499
609
  gap: z2.number().int().min(0).max(256).default(24),
500
- alignment: z2.enum(["start", "center", "end", "stretch"]).default("stretch")
610
+ alignment: z2.enum(["start", "center", "end", "stretch"]).default("stretch"),
611
+ /** Explicit center used by curve/arc connection routing. */
612
+ diagramCenter: diagramCenterSchema.optional()
501
613
  }).strict();
502
614
  var manualPositionSchema = z2.object({
503
615
  x: z2.number().int(),
@@ -507,7 +619,9 @@ var manualPositionSchema = z2.object({
507
619
  }).strict();
508
620
  var manualLayoutConfigSchema = z2.object({
509
621
  mode: z2.literal("manual"),
510
- positions: z2.record(z2.string().min(1), manualPositionSchema).default({})
622
+ positions: z2.record(z2.string().min(1), manualPositionSchema).default({}),
623
+ /** Explicit center used by curve/arc connection routing. */
624
+ diagramCenter: diagramCenterSchema.optional()
511
625
  }).strict();
512
626
  var layoutConfigSchema = z2.discriminatedUnion("mode", [
513
627
  autoLayoutConfigSchema,
@@ -559,6 +673,31 @@ var canvasSchema = z2.object({
559
673
  padding: z2.number().int().min(0).max(256).default(defaultCanvas.padding)
560
674
  }).strict();
561
675
  var themeInputSchema = z2.union([builtInThemeSchema, themeSchema]);
676
+ var diagramPositionSchema = z2.object({
677
+ x: z2.number(),
678
+ y: z2.number(),
679
+ width: z2.number().positive(),
680
+ height: z2.number().positive()
681
+ }).strict();
682
+ var diagramElementSchema = z2.discriminatedUnion("type", [
683
+ flowNodeElementSchema,
684
+ connectionElementSchema
685
+ ]);
686
+ var diagramLayoutSchema = z2.object({
687
+ mode: z2.enum(["manual", "auto"]).default("manual"),
688
+ positions: z2.record(z2.string(), diagramPositionSchema).optional(),
689
+ diagramCenter: diagramCenterSchema.optional()
690
+ }).strict();
691
+ var diagramSpecSchema = z2.object({
692
+ version: z2.literal(1),
693
+ canvas: z2.object({
694
+ width: z2.number().int().min(320).max(4096).default(1200),
695
+ height: z2.number().int().min(180).max(4096).default(675)
696
+ }).default({ width: 1200, height: 675 }),
697
+ theme: themeSchema.optional(),
698
+ elements: z2.array(diagramElementSchema).min(1),
699
+ layout: diagramLayoutSchema.default({ mode: "manual" })
700
+ }).strict();
562
701
  var designSpecSchema = z2.object({
563
702
  version: z2.literal(2).default(2),
564
703
  canvas: canvasSchema.default(defaultCanvas),
@@ -583,12 +722,16 @@ function deriveSafeFrame(spec) {
583
722
  height: spec.canvas.height - spec.canvas.padding * 2
584
723
  };
585
724
  }
725
+ function parseDiagramSpec(input) {
726
+ return diagramSpecSchema.parse(input);
727
+ }
586
728
  function parseDesignSpec(input) {
587
729
  return designSpecSchema.parse(input);
588
730
  }
589
731
  export {
590
732
  builtInThemeBackgrounds,
591
733
  builtInThemes,
734
+ connectionElementSchema,
592
735
  defaultAutoLayout,
593
736
  defaultCanvas,
594
737
  defaultConstraints,
@@ -598,7 +741,12 @@ export {
598
741
  defaultTheme,
599
742
  deriveSafeFrame,
600
743
  designSpecSchema,
744
+ diagramElementSchema,
745
+ diagramLayoutSchema,
746
+ diagramSpecSchema,
747
+ flowNodeElementSchema,
601
748
  inferLayout,
602
749
  parseDesignSpec,
750
+ parseDiagramSpec,
603
751
  resolveTheme
604
752
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectratools/graphic-designer-cli",
3
- "version": "0.3.2",
3
+ "version": "0.6.0",
4
4
  "description": "Deterministic visual content generator — code screenshots, terminal shots, flowcharts, and infographics. No browser dependency.",
5
5
  "type": "module",
6
6
  "license": "MIT",