@misoto22/design 0.6.1 → 0.7.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.
Files changed (157) hide show
  1. package/README.md +12 -0
  2. package/dist/agent/Accordion.md +1 -1
  3. package/dist/agent/Alert.md +1 -1
  4. package/dist/agent/AppShell.md +1 -1
  5. package/dist/agent/ArchitectureFigure.md +48 -0
  6. package/dist/agent/AreaChart.md +1 -1
  7. package/dist/agent/Article.md +1 -1
  8. package/dist/agent/Avatar.md +1 -1
  9. package/dist/agent/Badge.md +1 -1
  10. package/dist/agent/BarChart.md +1 -1
  11. package/dist/agent/BarList.md +1 -1
  12. package/dist/agent/BigNumber.md +1 -1
  13. package/dist/agent/BoxPlot.md +1 -1
  14. package/dist/agent/Breadcrumb.md +1 -1
  15. package/dist/agent/BulletChart.md +1 -1
  16. package/dist/agent/Button.md +1 -1
  17. package/dist/agent/Calendar.md +1 -1
  18. package/dist/agent/Card.md +1 -1
  19. package/dist/agent/Checkbox.md +1 -1
  20. package/dist/agent/Collapsible.md +1 -1
  21. package/dist/agent/Combobox.md +1 -1
  22. package/dist/agent/Command.md +1 -1
  23. package/dist/agent/ComposedChart.md +1 -1
  24. package/dist/agent/ContextMenu.md +1 -1
  25. package/dist/agent/DataflowFigure.md +27 -0
  26. package/dist/agent/DatePicker.md +1 -1
  27. package/dist/agent/Diagram.md +1 -1
  28. package/dist/agent/DiagramCanvas.md +47 -0
  29. package/dist/agent/DiagramExportMenu.md +38 -0
  30. package/dist/agent/DiagramInspector.md +50 -0
  31. package/dist/agent/DiagramLegend.md +34 -0
  32. package/dist/agent/DiagramMinimap.md +48 -0
  33. package/dist/agent/DiagramToolbar.md +47 -0
  34. package/dist/agent/Dialog.md +1 -1
  35. package/dist/agent/DropdownMenu.md +1 -1
  36. package/dist/agent/EmptyState.md +1 -1
  37. package/dist/agent/ErrorState.md +1 -1
  38. package/dist/agent/Facet.md +1 -1
  39. package/dist/agent/Field.md +1 -1
  40. package/dist/agent/FigureBand.md +1 -1
  41. package/dist/agent/FloatingIconButton.md +1 -1
  42. package/dist/agent/FunnelChart.md +1 -1
  43. package/dist/agent/Heatmap.md +1 -1
  44. package/dist/agent/Histogram.md +1 -1
  45. package/dist/agent/Input.md +1 -1
  46. package/dist/agent/Kbd.md +1 -1
  47. package/dist/agent/LifecycleFigure.md +28 -0
  48. package/dist/agent/LineChart.md +1 -1
  49. package/dist/agent/LinkArrow.md +1 -1
  50. package/dist/agent/NativeSelect.md +1 -1
  51. package/dist/agent/NavItem.md +1 -1
  52. package/dist/agent/Pagination.md +1 -1
  53. package/dist/agent/PieChart.md +1 -1
  54. package/dist/agent/Popover.md +1 -1
  55. package/dist/agent/Progress.md +1 -1
  56. package/dist/agent/RadarChart.md +1 -1
  57. package/dist/agent/RadialChart.md +1 -1
  58. package/dist/agent/RadioGroup.md +1 -1
  59. package/dist/agent/SankeyChart.md +1 -1
  60. package/dist/agent/ScatterChart.md +1 -1
  61. package/dist/agent/ScrollArea.md +1 -1
  62. package/dist/agent/SearchableMenu.md +1 -1
  63. package/dist/agent/Select.md +1 -1
  64. package/dist/agent/Separator.md +1 -1
  65. package/dist/agent/SequenceFigure.md +28 -0
  66. package/dist/agent/Sheet.md +1 -1
  67. package/dist/agent/Skeleton.md +1 -1
  68. package/dist/agent/Slider.md +1 -1
  69. package/dist/agent/Sparkline.md +1 -1
  70. package/dist/agent/Spinner.md +1 -1
  71. package/dist/agent/StatusDot.md +1 -1
  72. package/dist/agent/StatusPill.md +1 -1
  73. package/dist/agent/Steps.md +1 -1
  74. package/dist/agent/Switch.md +1 -1
  75. package/dist/agent/Table.md +1 -1
  76. package/dist/agent/Tabs.md +1 -1
  77. package/dist/agent/Tag.md +1 -1
  78. package/dist/agent/Textarea.md +1 -1
  79. package/dist/agent/Toast.md +1 -1
  80. package/dist/agent/ToggleGroup.md +1 -1
  81. package/dist/agent/Tooltip.md +1 -1
  82. package/dist/agent/TreemapChart.md +1 -1
  83. package/dist/agent/WaterfallChart.md +1 -1
  84. package/dist/agent/WorkflowFigure.md +28 -0
  85. package/dist/agent/catalog.json +223 -3
  86. package/dist/agent/index.md +15 -1
  87. package/dist/charts/index.d.ts +2 -1
  88. package/dist/charts/lib/export.d.ts +33 -43
  89. package/dist/charts/lib/export.js +16 -158
  90. package/dist/charts/lib/export.js.map +1 -1
  91. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +49 -0
  92. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +135 -0
  93. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
  94. package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
  95. package/dist/diagrams/DataflowFigure/DataflowFigure.js +129 -0
  96. package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
  97. package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +64 -0
  98. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +222 -0
  99. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
  100. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +72 -0
  101. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +125 -0
  102. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
  103. package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
  104. package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
  105. package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
  106. package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
  107. package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
  108. package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
  109. package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +61 -0
  110. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +79 -0
  111. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
  112. package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
  113. package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
  114. package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
  115. package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
  116. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +202 -0
  117. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
  118. package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
  119. package/dist/diagrams/SequenceFigure/SequenceFigure.js +231 -0
  120. package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
  121. package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +34 -0
  122. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +211 -0
  123. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
  124. package/dist/diagrams/index.d.ts +16 -0
  125. package/dist/diagrams/index.js +19 -0
  126. package/dist/diagrams/index.js.map +1 -0
  127. package/dist/diagrams/lib/frame.d.ts +97 -0
  128. package/dist/diagrams/lib/frame.js +116 -0
  129. package/dist/diagrams/lib/frame.js.map +1 -0
  130. package/dist/diagrams/lib/geometry.d.ts +114 -0
  131. package/dist/diagrams/lib/geometry.js +113 -0
  132. package/dist/diagrams/lib/geometry.js.map +1 -0
  133. package/dist/diagrams/lib/legend.d.ts +32 -0
  134. package/dist/diagrams/lib/legend.js +84 -0
  135. package/dist/diagrams/lib/legend.js.map +1 -0
  136. package/dist/diagrams/lib/marks.d.ts +207 -0
  137. package/dist/diagrams/lib/marks.js +480 -0
  138. package/dist/diagrams/lib/marks.js.map +1 -0
  139. package/dist/diagrams/lib/route.d.ts +85 -0
  140. package/dist/diagrams/lib/route.js +178 -0
  141. package/dist/diagrams/lib/route.js.map +1 -0
  142. package/dist/diagrams/lib/wires.d.ts +59 -0
  143. package/dist/diagrams/lib/wires.js +90 -0
  144. package/dist/diagrams/lib/wires.js.map +1 -0
  145. package/dist/diagrams/spec.d.ts +353 -0
  146. package/dist/diagrams/spec.js +1 -0
  147. package/dist/diagrams/spec.js.map +1 -0
  148. package/dist/lib/svg-export.d.ts +138 -0
  149. package/dist/lib/svg-export.js +198 -0
  150. package/dist/lib/svg-export.js.map +1 -0
  151. package/dist/semantic.css +34 -0
  152. package/dist/styles.css +1 -1
  153. package/dist/tokens.d.ts +16 -0
  154. package/dist/tokens.js +82 -0
  155. package/dist/tokens.json +82 -0
  156. package/package.json +5 -1
  157. package/skills/misoto22-design/SKILL.md +21 -7
@@ -0,0 +1,207 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { NodeKind, Variant, LifecycleStateKind } from '../spec.js';
4
+ import { Box } from './geometry.js';
5
+
6
+ /** What each kind is called on a plate's eyebrow. Short, because it is a kicker. */
7
+ declare const KIND_WORD: Record<NodeKind, string>;
8
+ /**
9
+ * The marker definitions every figure needs.
10
+ *
11
+ * Rendered once per figure. The ids are namespaced by the figure's own id
12
+ * because two diagrams on one page would otherwise share one `<defs>`, and the
13
+ * second figure's arrowheads would silently take the first figure's paint —
14
+ * SVG ids are document-global, and a duplicate is resolved to whichever came
15
+ * first rather than to the nearest one.
16
+ */
17
+ declare function DiagramDefs({ uid }: {
18
+ uid: string;
19
+ }): react.JSX.Element;
20
+ /**
21
+ * The 14×14 mark that says what kind of thing a node is.
22
+ *
23
+ * Drawn on a 14-unit grid at a 1.35 stroke. Both numbers went up from the first
24
+ * pass and both had to: at 12 units and a 1.2 stroke the seven forms were a few
25
+ * grey pixels apart at reading size, which is not a distinction — it is a
26
+ * smudge. Every path is closed geometry rather than an icon font, because a
27
+ * figure has to serialise into a standalone file and a font the exported
28
+ * document cannot fetch renders as a box.
29
+ */
30
+ declare function Sigil({ kind, x, y, reversed, }: {
31
+ kind: NodeKind;
32
+ x: number;
33
+ y: number;
34
+ reversed?: boolean;
35
+ }): react.JSX.Element;
36
+ /**
37
+ * A plate's internal vertical rhythm, in user units from its top edge.
38
+ *
39
+ * Written out as one object rather than computed inline in three renderers,
40
+ * because these numbers ARE the plate: change one and the card stops looking
41
+ * like a card. The eyebrow sits high and tight, the name is the only thing set
42
+ * at reading size, and the sublabel hangs under it in the meta voice.
43
+ */
44
+ declare const PLATE: {
45
+ readonly padX: 15;
46
+ readonly eyebrow: 19;
47
+ readonly label: 39;
48
+ readonly sub: 53;
49
+ readonly lineStep: 17;
50
+ /** Where the eyebrow lands when there is none — the label moves up into it. */
51
+ readonly riseWithoutEyebrow: 16;
52
+ };
53
+ /**
54
+ * How tall a plate has to be to hold what it was given.
55
+ *
56
+ * A declared height is a FLOOR, not a ceiling. When a specification asks for a
57
+ * 60-unit box and then puts two lines of name and a qualifier in it, honouring
58
+ * the 60 prints the qualifier through the bottom rule — which reads as a
59
+ * rendering fault rather than as a box asked to hold too much. Growing is
60
+ * visible and correct; clipping is invisible and wrong.
61
+ */
62
+ declare function plateHeight(labelLines: number, hasSub: boolean, hasEyebrow: boolean, floor?: number): number;
63
+ interface NodePlateProps {
64
+ box: Box;
65
+ label: string;
66
+ sublabel?: string;
67
+ tag?: string;
68
+ kind?: NodeKind;
69
+ variant?: Variant;
70
+ /** Printed in the trailing corner in mono — a step number. */
71
+ step?: string;
72
+ /** Paints the plate on the recessed ground rather than on paper. */
73
+ muted?: boolean;
74
+ /** Lit by a guided chapter or a reader's focus. */
75
+ active?: boolean;
76
+ /** Dimmed because something else is lit. */
77
+ dimmed?: boolean;
78
+ onSelect?: () => void;
79
+ /** A stable hook the viewer chrome and the tests both address nodes by. */
80
+ nodeId?: string;
81
+ }
82
+ /**
83
+ * One box, with everything that can be printed inside it.
84
+ *
85
+ * Three registers, top to bottom, and each is a different voice on purpose: a
86
+ * mono kicker naming the KIND, the name at reading size in the interface face,
87
+ * and the qualifier back in mono. That is the same ladder a record on a page
88
+ * uses — the diagram is not inventing a second typography for itself.
89
+ *
90
+ * WHAT IT IS NOT is a button, and that is deliberate. The `<svg>` around it
91
+ * carries `role="img"`, which makes everything inside it presentational to
92
+ * assistive technology — so a `role="button"` here would announce a control a
93
+ * screen reader can never reach. The keyboard route to the same selection is
94
+ * the figure's own summary list, which is a real `<ul>` of real `<button>`s
95
+ * sitting beside the picture. `onSelect` here is the POINTER path to that same
96
+ * action, and nothing else.
97
+ */
98
+ declare function NodePlate({ box, label, sublabel, tag, kind, variant, step, muted, active, dimmed, onSelect, nodeId, }: NodePlateProps): react.JSX.Element;
99
+ /**
100
+ * A mono chip: a version, a region, a protocol, a data classification.
101
+ *
102
+ * A rule and a word, with no fill under it. The filled chip this replaced put a
103
+ * third ground inside a plate that already sat on a figure that sat on the
104
+ * page, and three grounds deep is where a diagram stops reading as structure
105
+ * and starts reading as packaging.
106
+ */
107
+ declare function Chip({ x, y, text, align, reversed, }: {
108
+ x: number;
109
+ y: number;
110
+ text: string;
111
+ align?: 'start' | 'middle' | 'end';
112
+ reversed?: boolean;
113
+ }): react.JSX.Element;
114
+ /**
115
+ * How a line is painted: the colour as a class, the geometry as attributes.
116
+ *
117
+ * THE SPLIT IS NOT ARBITRARY, and getting it wrong cost an afternoon. Tailwind
118
+ * generates a rule only for a class name it can find as a LITERAL in the
119
+ * source. A width built at runtime — `` `[stroke-width:${weight}]` `` — is a
120
+ * class that never gets a rule, so the browser falls back to SVG's default
121
+ * 1px, silently, on exactly the lines a figure most needs to be heavier. The
122
+ * main path came out the same weight as a side branch and nothing said so.
123
+ *
124
+ * Colour still goes through a class, because a paint has to resolve a custom
125
+ * property and `stroke="var(--x)"` is not valid as an attribute. Width and dash
126
+ * pattern are plain numbers, so they go through presentation attributes where
127
+ * no build step has to have predicted them — and `getComputedStyle` reports an
128
+ * attribute exactly as it reports a rule, so the export still picks them up.
129
+ */
130
+ declare function edgeClasses(variant?: Variant | 'return'): string;
131
+ /** A line's width and dash pattern, as presentation attributes. */
132
+ declare function edgeStroke(variant?: Variant | 'return', weight?: number): {
133
+ strokeWidth: number;
134
+ strokeDasharray?: string;
135
+ };
136
+ /** Which arrowhead a line ends in. */
137
+ declare function edgeMarker(variant?: Variant | 'return'): 'arrow' | 'arrow-strong' | 'arrow-open';
138
+ interface EdgeLabelProps {
139
+ x: number;
140
+ y: number;
141
+ axis: 'x' | 'y';
142
+ text: string;
143
+ /** A mono chip printed under the wording — a data classification. */
144
+ chip?: string;
145
+ /** A second, quieter line — a condition, a timeout, a retry count. */
146
+ note?: string;
147
+ }
148
+ /**
149
+ * A relationship's wording, on a mask that punches the line out from under it.
150
+ *
151
+ * The mask is not decoration. A label drawn straight onto a line is unreadable
152
+ * at every size, and the two repairs a renderer can make are moving the label
153
+ * or hiding the line behind it. Moving it changes which segment the wording
154
+ * belongs to, which is a semantic change; masking is the one that leaves the
155
+ * meaning alone.
156
+ *
157
+ * Set in mono rather than in the interface face. The wording on a line is an
158
+ * ANNOTATION on the picture, not a second rank of content — and at the sans
159
+ * face it competed with the names on the plates, which is the one comparison it
160
+ * must lose.
161
+ */
162
+ declare function EdgeLabel({ x, y, axis, text, chip, note }: EdgeLabelProps): react.JSX.Element;
163
+ /**
164
+ * A labelled frame around a set of boxes: a region, a security group, a phase,
165
+ * a process group.
166
+ *
167
+ * A FRAME IS A RULE AND NOT A GROUND. Archify washes its regions with a tint,
168
+ * which this system cannot copy for two reasons: a second ground inside a paper
169
+ * figure reads as packaging rather than as structure — the same argument the
170
+ * containment `Diagram` primitive makes about nested boxes — and every
171
+ * relationship label crossing the wash would then need to know which of two
172
+ * grounds its mask is punching through, which is a question a label cannot
173
+ * answer. `muted` therefore washes only where a band IS the ground it labels: a
174
+ * workflow's exception lane, which nothing routes across.
175
+ *
176
+ * The label sits ABOVE the top rule rather than inside the frame or on it.
177
+ * Inside, it costs a line of vertical space in every frame whether or not the
178
+ * frame had one to spare. ON the rule — which is where it started — it has to
179
+ * punch a mask through the frame, and that mask then competes for the same few
180
+ * units of clear ground as any relationship label routed along the frame's own
181
+ * edge: two captions, two white plates, one on top of the other. Above the
182
+ * rule it needs no mask, leaves the frame unbroken, and reads as a caption for
183
+ * the frame rather than as its first child.
184
+ */
185
+ declare function BandFrame({ box, label, dashed, muted, }: {
186
+ box: Box;
187
+ label?: string;
188
+ dashed?: boolean;
189
+ muted?: boolean;
190
+ }): react.JSX.Element;
191
+ /**
192
+ * The plate shape for a lifecycle state.
193
+ *
194
+ * This is the one place the system spends colour, and it spends exactly the two
195
+ * tokens it reserves for state: `--success` on a terminal success, `--danger`
196
+ * on a terminal failure. Every other kind is carried by shape — a filled cap
197
+ * for a start, a diamond for a decision, a dashed frame for a wait, a cut
198
+ * corner for something outside the system — so a greyscale print loses the two
199
+ * outcomes' hue and keeps all six other distinctions.
200
+ */
201
+ declare function StatePlate({ box, kind, children, }: {
202
+ box: Box;
203
+ kind: LifecycleStateKind;
204
+ children?: ReactNode;
205
+ }): react.JSX.Element;
206
+
207
+ export { BandFrame, Chip, DiagramDefs, EdgeLabel, type EdgeLabelProps, KIND_WORD, NodePlate, type NodePlateProps, PLATE, Sigil, StatePlate, edgeClasses, edgeMarker, edgeStroke, plateHeight };
@@ -0,0 +1,480 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ import { round, TYPE, textWidth, wrapText } from "./geometry.js";
4
+ const PLATE_RADIUS = "[rx:var(--radius-sm)] [ry:var(--radius-sm)]";
5
+ const KIND_WORD = {
6
+ frontend: "CLIENT",
7
+ backend: "SERVICE",
8
+ database: "DATA",
9
+ cloud: "CLOUD",
10
+ security: "POLICY",
11
+ messagebus: "QUEUE",
12
+ external: "EXTERNAL"
13
+ };
14
+ function DiagramDefs({ uid }) {
15
+ return /* @__PURE__ */ jsxs("defs", { children: [
16
+ /* @__PURE__ */ jsx(
17
+ "marker",
18
+ {
19
+ id: `${uid}-arrow`,
20
+ markerWidth: "11",
21
+ markerHeight: "11",
22
+ refX: "9.5",
23
+ refY: "5.5",
24
+ orient: "auto-start-reverse",
25
+ markerUnits: "userSpaceOnUse",
26
+ children: /* @__PURE__ */ jsx("path", { d: "M 0.6 1.4 L 10 5.5 L 0.6 9.6 Z", className: "fill-(--diagram-line)" })
27
+ }
28
+ ),
29
+ /* @__PURE__ */ jsx(
30
+ "marker",
31
+ {
32
+ id: `${uid}-arrow-strong`,
33
+ markerWidth: "12",
34
+ markerHeight: "12",
35
+ refX: "10.5",
36
+ refY: "6",
37
+ orient: "auto-start-reverse",
38
+ markerUnits: "userSpaceOnUse",
39
+ children: /* @__PURE__ */ jsx("path", { d: "M 0.6 1.6 L 11 6 L 0.6 10.4 Z", className: "fill-(--diagram-line-strong)" })
40
+ }
41
+ ),
42
+ /* @__PURE__ */ jsx(
43
+ "marker",
44
+ {
45
+ id: `${uid}-arrow-open`,
46
+ markerWidth: "11",
47
+ markerHeight: "11",
48
+ refX: "9.5",
49
+ refY: "5.5",
50
+ orient: "auto-start-reverse",
51
+ markerUnits: "userSpaceOnUse",
52
+ children: /* @__PURE__ */ jsx(
53
+ "path",
54
+ {
55
+ d: "M 1 1.6 L 9.6 5.5 L 1 9.4",
56
+ fill: "none",
57
+ strokeWidth: "1.4",
58
+ strokeLinecap: "round",
59
+ strokeLinejoin: "round",
60
+ className: "stroke-(--diagram-line-soft)"
61
+ }
62
+ )
63
+ }
64
+ )
65
+ ] });
66
+ }
67
+ function Sigil({
68
+ kind,
69
+ x,
70
+ y,
71
+ reversed
72
+ }) {
73
+ const stroke = cn(
74
+ "fill-none [stroke-width:1.35] [stroke-linejoin:round] [stroke-linecap:round]",
75
+ reversed ? "stroke-(--diagram-plate-ink)" : "stroke-(--diagram-sigil)"
76
+ );
77
+ return /* @__PURE__ */ jsxs("g", { transform: `translate(${round(x)}, ${round(y)})`, "aria-hidden": "true", children: [
78
+ kind === "frontend" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
79
+ /* @__PURE__ */ jsx("rect", { x: "0.8", y: "2", width: "12.4", height: "10", rx: "1.6" }),
80
+ /* @__PURE__ */ jsx("path", { d: "M 0.8 5.2 H 13.2" }),
81
+ /* @__PURE__ */ jsx("path", { d: "M 3 3.6 H 4" })
82
+ ] }),
83
+ kind === "backend" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
84
+ /* @__PURE__ */ jsx("rect", { x: "0.8", y: "1.8", width: "12.4", height: "4.4", rx: "1.2" }),
85
+ /* @__PURE__ */ jsx("rect", { x: "0.8", y: "7.8", width: "12.4", height: "4.4", rx: "1.2" }),
86
+ /* @__PURE__ */ jsx("path", { d: "M 3 4 H 4.2" }),
87
+ /* @__PURE__ */ jsx("path", { d: "M 3 10 H 4.2" })
88
+ ] }),
89
+ kind === "database" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
90
+ /* @__PURE__ */ jsx("ellipse", { cx: "7", cy: "3.4", rx: "6", ry: "2.4" }),
91
+ /* @__PURE__ */ jsx("path", { d: "M 1 3.4 V 10.6 A 6 2.4 0 0 0 13 10.6 V 3.4" }),
92
+ /* @__PURE__ */ jsx("path", { d: "M 1 7 A 6 2.4 0 0 0 13 7" })
93
+ ] }),
94
+ kind === "cloud" && /* @__PURE__ */ jsx("g", { className: stroke, children: /* @__PURE__ */ jsx("path", { d: "M 3.4 10.8 A 2.9 2.9 0 0 1 3.5 5 A 3.8 3.8 0 0 1 10.5 4.2 A 3.2 3.2 0 0 1 11 10.8 Z" }) }),
95
+ kind === "security" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
96
+ /* @__PURE__ */ jsx("path", { d: "M 7 1 L 12.5 3.1 V 7 C 12.5 10 10 12.1 7 13 C 4 12.1 1.5 10 1.5 7 V 3.1 Z" }),
97
+ /* @__PURE__ */ jsx("path", { d: "M 4.7 7 L 6.4 8.7 L 9.4 5.3" })
98
+ ] }),
99
+ kind === "messagebus" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
100
+ /* @__PURE__ */ jsx("path", { d: "M 0.9 2.8 H 13.1" }),
101
+ /* @__PURE__ */ jsx("path", { d: "M 0.9 11.2 H 13.1" }),
102
+ /* @__PURE__ */ jsx("path", { d: "M 3.6 5.2 V 8.8" }),
103
+ /* @__PURE__ */ jsx("path", { d: "M 7 5.2 V 8.8" }),
104
+ /* @__PURE__ */ jsx("path", { d: "M 10.4 5.2 V 8.8" })
105
+ ] }),
106
+ kind === "external" && /* @__PURE__ */ jsxs("g", { className: stroke, children: [
107
+ /* @__PURE__ */ jsx("path", { d: "M 7.4 1.8 H 1.6 V 12.2 H 12.4 V 6.4" }),
108
+ /* @__PURE__ */ jsx("path", { d: "M 8.4 5.4 L 13 1" }),
109
+ /* @__PURE__ */ jsx("path", { d: "M 9.6 0.9 H 13.1 V 4.4" })
110
+ ] })
111
+ ] });
112
+ }
113
+ function plateClasses(variant, muted) {
114
+ switch (variant) {
115
+ case "emphasis":
116
+ return "fill-(--diagram-plate) stroke-(--diagram-plate) [stroke-width:1]";
117
+ case "security":
118
+ return "fill-(--diagram-node) stroke-(--diagram-rule-hard) [stroke-width:1.3] [stroke-dasharray:5_3]";
119
+ case "dashed":
120
+ return "fill-(--diagram-node) stroke-(--diagram-rule) [stroke-width:1] [stroke-dasharray:4_3]";
121
+ default:
122
+ return muted ? "fill-(--diagram-node-2) stroke-(--diagram-rule) [stroke-width:1]" : "fill-(--diagram-node) stroke-(--diagram-rule) [stroke-width:1]";
123
+ }
124
+ }
125
+ const PLATE = {
126
+ padX: 15,
127
+ eyebrow: 19,
128
+ label: 39,
129
+ sub: 53,
130
+ lineStep: 17,
131
+ /** Where the eyebrow lands when there is none — the label moves up into it. */
132
+ riseWithoutEyebrow: 16
133
+ };
134
+ function plateHeight(labelLines, hasSub, hasEyebrow, floor = 0) {
135
+ const last = hasSub ? PLATE.sub : PLATE.label;
136
+ const content = last + (labelLines - 1) * PLATE.lineStep + 16 - (hasEyebrow ? 0 : PLATE.riseWithoutEyebrow);
137
+ return Math.max(floor, Math.ceil(content));
138
+ }
139
+ function NodePlate({
140
+ box,
141
+ label,
142
+ sublabel,
143
+ tag,
144
+ kind,
145
+ variant,
146
+ step,
147
+ muted,
148
+ active,
149
+ dimmed,
150
+ onSelect,
151
+ nodeId
152
+ }) {
153
+ const reversed = variant === "emphasis";
154
+ const lines = wrapText(label, TYPE.label, box.w - PLATE.padX * 2, 2);
155
+ const eyebrow = tag ?? (kind ? KIND_WORD[kind] : void 0);
156
+ const hasEyebrow = Boolean(eyebrow || step);
157
+ const rise = hasEyebrow ? 0 : PLATE.riseWithoutEyebrow;
158
+ const labelY = box.y + PLATE.label - rise;
159
+ const subY = box.y + PLATE.sub - rise + (lines.length - 1) * PLATE.lineStep;
160
+ return /* @__PURE__ */ jsxs(
161
+ "g",
162
+ {
163
+ "data-node": nodeId,
164
+ "data-active": active ? "" : void 0,
165
+ className: cn(
166
+ "transition-opacity duration-(--duration-fast)",
167
+ dimmed && "opacity-25",
168
+ onSelect && "cursor-pointer"
169
+ ),
170
+ onClick: onSelect,
171
+ children: [
172
+ /* @__PURE__ */ jsx(
173
+ "rect",
174
+ {
175
+ x: round(box.x),
176
+ y: round(box.y),
177
+ width: round(box.w),
178
+ height: round(box.h),
179
+ rx: 6,
180
+ ry: 6,
181
+ className: cn(PLATE_RADIUS, plateClasses(variant, Boolean(muted)))
182
+ }
183
+ ),
184
+ active && /* @__PURE__ */ jsx(
185
+ "rect",
186
+ {
187
+ x: round(box.x) - 3.5,
188
+ y: round(box.y) - 3.5,
189
+ width: round(box.w) + 7,
190
+ height: round(box.h) + 7,
191
+ rx: 9,
192
+ ry: 9,
193
+ fill: "none",
194
+ className: "stroke-(--accent) [stroke-width:1.5]"
195
+ }
196
+ ),
197
+ kind && /* @__PURE__ */ jsx(
198
+ Sigil,
199
+ {
200
+ kind,
201
+ x: box.x + PLATE.padX,
202
+ y: box.y + PLATE.eyebrow - 11,
203
+ reversed
204
+ }
205
+ ),
206
+ eyebrow && /* @__PURE__ */ jsx(
207
+ "text",
208
+ {
209
+ x: round(box.x + PLATE.padX + (kind ? 20 : 0)),
210
+ y: round(box.y + PLATE.eyebrow),
211
+ className: cn(
212
+ "font-mono [font-size:8.5px] [letter-spacing:0.13em] uppercase",
213
+ reversed ? "fill-(--diagram-plate-ink) opacity-70" : "fill-(--diagram-ink-3)"
214
+ ),
215
+ children: eyebrow
216
+ }
217
+ ),
218
+ step && /* @__PURE__ */ jsx(
219
+ "text",
220
+ {
221
+ x: round(box.x + box.w - PLATE.padX),
222
+ y: round(box.y + PLATE.eyebrow),
223
+ textAnchor: "end",
224
+ className: cn(
225
+ "font-mono [font-size:9px] [letter-spacing:0.1em]",
226
+ reversed ? "fill-(--diagram-plate-ink) opacity-65" : "fill-(--diagram-ink-3)"
227
+ ),
228
+ children: step
229
+ }
230
+ ),
231
+ lines.map((line, index) => /* @__PURE__ */ jsx(
232
+ "text",
233
+ {
234
+ x: round(box.x + PLATE.padX),
235
+ y: round(labelY + index * PLATE.lineStep),
236
+ className: cn(
237
+ "font-sans [font-size:14px] [letter-spacing:-0.005em]",
238
+ reversed ? "fill-(--diagram-plate-ink)" : "fill-(--diagram-ink)"
239
+ ),
240
+ children: line
241
+ },
242
+ index
243
+ )),
244
+ sublabel && /* @__PURE__ */ jsx(
245
+ "text",
246
+ {
247
+ x: round(box.x + PLATE.padX),
248
+ y: round(subY),
249
+ className: cn(
250
+ "font-mono [font-size:10px]",
251
+ reversed ? "fill-(--diagram-plate-ink) opacity-65" : "fill-(--diagram-ink-3)"
252
+ ),
253
+ children: sublabel
254
+ }
255
+ )
256
+ ]
257
+ }
258
+ );
259
+ }
260
+ function Chip({
261
+ x,
262
+ y,
263
+ text,
264
+ align = "start",
265
+ reversed
266
+ }) {
267
+ const width = textWidth(text, TYPE.chip) + 12;
268
+ const left = align === "end" ? x - width : align === "middle" ? x - width / 2 : x;
269
+ return /* @__PURE__ */ jsxs("g", { "aria-hidden": "true", children: [
270
+ /* @__PURE__ */ jsx(
271
+ "rect",
272
+ {
273
+ x: round(left),
274
+ y: round(y - 7.5),
275
+ width: round(width),
276
+ height: 15,
277
+ rx: 3,
278
+ ry: 3,
279
+ className: cn(
280
+ "[stroke-width:0.9] fill-(--diagram-surface)",
281
+ reversed ? "stroke-(--diagram-plate-ink) opacity-40" : "stroke-(--diagram-rule)"
282
+ )
283
+ }
284
+ ),
285
+ /* @__PURE__ */ jsx(
286
+ "text",
287
+ {
288
+ x: round(left + width / 2),
289
+ y: round(y + 2.8),
290
+ textAnchor: "middle",
291
+ className: cn(
292
+ "font-mono [font-size:9px] [letter-spacing:0.05em]",
293
+ reversed ? "fill-(--diagram-plate-ink) opacity-70" : "fill-(--diagram-ink-3)"
294
+ ),
295
+ children: text
296
+ }
297
+ )
298
+ ] });
299
+ }
300
+ function edgeClasses(variant) {
301
+ switch (variant) {
302
+ case "emphasis":
303
+ return "stroke-(--diagram-line-strong)";
304
+ case "dashed":
305
+ case "return":
306
+ return "stroke-(--diagram-line-soft)";
307
+ default:
308
+ return "stroke-(--diagram-line)";
309
+ }
310
+ }
311
+ function edgeStroke(variant, weight) {
312
+ switch (variant) {
313
+ case "emphasis":
314
+ return { strokeWidth: weight ?? 2.1 };
315
+ case "security":
316
+ return { strokeWidth: weight ?? 1.4, strokeDasharray: "7 4" };
317
+ case "dashed":
318
+ case "return":
319
+ return { strokeWidth: weight ?? 1.3, strokeDasharray: "4.5 4" };
320
+ default:
321
+ return { strokeWidth: weight ?? 1.4 };
322
+ }
323
+ }
324
+ function edgeMarker(variant) {
325
+ if (variant === "emphasis") return "arrow-strong";
326
+ if (variant === "return") return "arrow-open";
327
+ return "arrow";
328
+ }
329
+ function EdgeLabel({ x, y, axis, text, chip, note }) {
330
+ const width = textWidth(text, TYPE.edge) + 10;
331
+ const noteWidth = note ? textWidth(note, TYPE.chip) + 10 : 0;
332
+ const cy = y + (axis === "x" ? -10 : 0);
333
+ return /* @__PURE__ */ jsxs("g", { "aria-hidden": "true", children: [
334
+ /* @__PURE__ */ jsx(
335
+ "rect",
336
+ {
337
+ x: round(x - width / 2),
338
+ y: round(cy - 7),
339
+ width: round(width),
340
+ height: 14,
341
+ className: "fill-(--diagram-surface)"
342
+ }
343
+ ),
344
+ /* @__PURE__ */ jsx(
345
+ "text",
346
+ {
347
+ x: round(x),
348
+ y: round(cy + 3.5),
349
+ textAnchor: "middle",
350
+ className: "fill-(--diagram-ink-2) font-mono [font-size:10px]",
351
+ children: text
352
+ }
353
+ ),
354
+ note && /* @__PURE__ */ jsxs(Fragment, { children: [
355
+ /* @__PURE__ */ jsx(
356
+ "rect",
357
+ {
358
+ x: round(x - noteWidth / 2),
359
+ y: round(cy + 6),
360
+ width: round(noteWidth),
361
+ height: 13,
362
+ className: "fill-(--diagram-surface)"
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsx(
366
+ "text",
367
+ {
368
+ x: round(x),
369
+ y: round(cy + 15.5),
370
+ textAnchor: "middle",
371
+ className: "fill-(--diagram-ink-3) font-mono [font-size:9px]",
372
+ children: note
373
+ }
374
+ )
375
+ ] }),
376
+ chip && /* @__PURE__ */ jsx(Chip, { x, y: cy + (note ? 33 : 20), text: chip, align: "middle" })
377
+ ] });
378
+ }
379
+ function BandFrame({
380
+ box,
381
+ label,
382
+ dashed,
383
+ muted
384
+ }) {
385
+ return /* @__PURE__ */ jsxs("g", { "aria-hidden": "true", children: [
386
+ /* @__PURE__ */ jsx(
387
+ "rect",
388
+ {
389
+ x: round(box.x),
390
+ y: round(box.y),
391
+ width: round(box.w),
392
+ height: round(box.h),
393
+ rx: 10,
394
+ ry: 10,
395
+ className: cn(
396
+ "[rx:var(--radius-lg)] [ry:var(--radius-lg)]",
397
+ muted ? "fill-(--diagram-band)" : "fill-none",
398
+ dashed ? "stroke-(--diagram-rule-hard) [stroke-width:1.2] [stroke-dasharray:6_4]" : "stroke-(--diagram-rule) [stroke-width:1]"
399
+ )
400
+ }
401
+ ),
402
+ label && /* @__PURE__ */ jsx(
403
+ "text",
404
+ {
405
+ x: round(box.x + 2),
406
+ y: round(box.y - 7),
407
+ className: "fill-(--diagram-ink-3) font-mono [font-size:9px] [letter-spacing:0.14em] uppercase",
408
+ children: label
409
+ }
410
+ )
411
+ ] });
412
+ }
413
+ function StatePlate({
414
+ box,
415
+ kind,
416
+ children
417
+ }) {
418
+ const { x, y, w, h } = box;
419
+ const common = "[stroke-width:1.3]";
420
+ if (kind === "decision") {
421
+ const cx = x + w / 2;
422
+ const cy = y + h / 2;
423
+ return /* @__PURE__ */ jsxs("g", { children: [
424
+ /* @__PURE__ */ jsx(
425
+ "path",
426
+ {
427
+ d: `M ${round(cx)} ${round(y)} L ${round(x + w)} ${round(cy)} L ${round(cx)} ${round(y + h)} L ${round(x)} ${round(cy)} Z`,
428
+ className: cn("fill-(--diagram-node) stroke-(--diagram-rule-hard)", common)
429
+ }
430
+ ),
431
+ children
432
+ ] });
433
+ }
434
+ if (kind === "external") {
435
+ const cut = 13;
436
+ return /* @__PURE__ */ jsxs("g", { children: [
437
+ /* @__PURE__ */ jsx(
438
+ "path",
439
+ {
440
+ d: `M ${round(x)} ${round(y)} H ${round(x + w - cut)} L ${round(x + w)} ${round(y + cut)} V ${round(y + h)} H ${round(x)} Z`,
441
+ className: cn("fill-(--diagram-node-2) stroke-(--diagram-rule)", common)
442
+ }
443
+ ),
444
+ children
445
+ ] });
446
+ }
447
+ const shape = kind === "start" ? "fill-(--diagram-plate) stroke-(--diagram-plate)" : kind === "success" ? "fill-(--success-wash) stroke-(--success)" : kind === "failure" ? "fill-(--danger-wash) stroke-(--danger)" : kind === "waiting" ? "fill-(--diagram-node) stroke-(--diagram-rule) [stroke-dasharray:5_3]" : kind === "neutral" ? "fill-(--diagram-node-2) stroke-(--diagram-rule)" : "fill-(--diagram-node) stroke-(--diagram-rule-hard)";
448
+ const radius = kind === "start" ? h / 2 : 6;
449
+ return /* @__PURE__ */ jsxs("g", { children: [
450
+ /* @__PURE__ */ jsx(
451
+ "rect",
452
+ {
453
+ x: round(x),
454
+ y: round(y),
455
+ width: round(w),
456
+ height: round(h),
457
+ rx: radius,
458
+ ry: radius,
459
+ className: cn(kind === "start" ? "" : PLATE_RADIUS, shape, common)
460
+ }
461
+ ),
462
+ children
463
+ ] });
464
+ }
465
+ export {
466
+ BandFrame,
467
+ Chip,
468
+ DiagramDefs,
469
+ EdgeLabel,
470
+ KIND_WORD,
471
+ NodePlate,
472
+ PLATE,
473
+ Sigil,
474
+ StatePlate,
475
+ edgeClasses,
476
+ edgeMarker,
477
+ edgeStroke,
478
+ plateHeight
479
+ };
480
+ //# sourceMappingURL=marks.js.map