@misoto22/design 0.6.0 → 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 +2 -2
  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 +2 -2
  11. package/dist/agent/BarList.md +2 -2
  12. package/dist/agent/BigNumber.md +2 -2
  13. package/dist/agent/BoxPlot.md +2 -2
  14. package/dist/agent/Breadcrumb.md +1 -1
  15. package/dist/agent/BulletChart.md +2 -2
  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 +2 -2
  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 +2 -2
  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 +2 -2
  43. package/dist/agent/Heatmap.md +2 -2
  44. package/dist/agent/Histogram.md +2 -2
  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 +2 -2
  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 +2 -2
  54. package/dist/agent/Popover.md +1 -1
  55. package/dist/agent/Progress.md +1 -1
  56. package/dist/agent/RadarChart.md +2 -2
  57. package/dist/agent/RadialChart.md +2 -2
  58. package/dist/agent/RadioGroup.md +1 -1
  59. package/dist/agent/SankeyChart.md +2 -2
  60. package/dist/agent/ScatterChart.md +2 -2
  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 +2 -2
  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 +2 -2
  83. package/dist/agent/WaterfallChart.md +2 -2
  84. package/dist/agent/WorkflowFigure.md +28 -0
  85. package/dist/agent/catalog.json +295 -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 +58 -6
@@ -0,0 +1,34 @@
1
+ import * as react from 'react';
2
+ import { FigureChrome } from '../lib/frame.js';
3
+ import { WorkflowSpec } from '../spec.js';
4
+ import '../lib/geometry.js';
5
+
6
+ interface WorkflowFigureProps extends FigureChrome {
7
+ spec: WorkflowSpec;
8
+ }
9
+ /**
10
+ * A process: who does what, in what order, and where it can go wrong.
11
+ *
12
+ * Three structures stacked on one grid, and they are three because they answer
13
+ * three different questions a reader brings to a runbook.
14
+ *
15
+ * **Lanes** are rows and answer WHO. A lane marked `exception` is the one band
16
+ * that gets a wash rather than a rule, and it earns the exception to the
17
+ * frames-are-rules law because nothing routes across it — it IS the ground for
18
+ * the failure path, not a frame drawn over the happy one.
19
+ *
20
+ * **Phases** are columns across every lane and answer WHEN. Printed as captions
21
+ * on one header rule, because a phase is an axis label. **Groups** are frames
22
+ * inside a single lane and answer WHAT BELONGS TOGETHER — a planning loop, an
23
+ * evidence path.
24
+ *
25
+ * THE MAIN PATH IS HEAVIER, and that is the whole hierarchy. `mainPath` lists
26
+ * the node ids a reader should be able to follow without thinking. Every edge
27
+ * between two consecutive ids on it is drawn at the emphasis weight whatever
28
+ * its own variant says, which is the one thing that turns fourteen boxes and
29
+ * nineteen arrows into a diagram with a subject. An `error` role goes the other
30
+ * way — dashed and soft — so the exception path recedes without disappearing.
31
+ */
32
+ declare function WorkflowFigure({ spec, className, legend, cards, heading, activeIds, onSelectNode, }: WorkflowFigureProps): react.JSX.Element;
33
+
34
+ export { WorkflowFigure, type WorkflowFigureProps, WorkflowFigure as default };
@@ -0,0 +1,211 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId, useMemo } from "react";
4
+ import { DiagramFrame } from "../lib/frame.js";
5
+ import { inflate, round, textWidth, TYPE, union, wrapText } from "../lib/geometry.js";
6
+ import { resolveLegend, variantLegend } from "../lib/legend.js";
7
+ import { BandFrame, NodePlate, PLATE, plateHeight } from "../lib/marks.js";
8
+ import { renderWires, wiresFor } from "../lib/wires.js";
9
+ const VARIANTS = ["default", "emphasis", "security", "dashed"];
10
+ const GRID = {
11
+ /** The gutter the lane names live in. */
12
+ railW: 118,
13
+ originY: 74,
14
+ colW: 168,
15
+ gapX: 58,
16
+ laneH: 92,
17
+ laneGap: 40
18
+ };
19
+ function WorkflowFigure({
20
+ spec,
21
+ className,
22
+ legend = "auto",
23
+ cards = true,
24
+ heading = true,
25
+ activeIds,
26
+ onSelectNode
27
+ }) {
28
+ const uid = useId().replace(/:/g, "");
29
+ const model = useMemo(
30
+ () => buildModel(spec, uid, activeIds, onSelectNode),
31
+ [spec, uid, activeIds, onSelectNode]
32
+ );
33
+ return /* @__PURE__ */ jsx(
34
+ DiagramFrame,
35
+ {
36
+ meta: spec.meta,
37
+ model,
38
+ cards: spec.cards,
39
+ showCards: cards,
40
+ heading,
41
+ legend,
42
+ className,
43
+ activeIds,
44
+ onSelectNode
45
+ }
46
+ );
47
+ }
48
+ const colX = (col) => GRID.railW + col * (GRID.colW + GRID.gapX);
49
+ const spanBox = (fromCol, toCol, y, h) => ({
50
+ x: colX(fromCol),
51
+ y,
52
+ w: colX(toCol) + GRID.colW - colX(fromCol),
53
+ h
54
+ });
55
+ function buildModel(spec, uid, activeIds, onSelectNode) {
56
+ const laneIndex = new Map(spec.lanes.map((lane, index) => [lane.id, index]));
57
+ const laneY = (index) => GRID.originY + index * (GRID.laneH + GRID.laneGap);
58
+ const boxes = /* @__PURE__ */ new Map();
59
+ const placed = spec.nodes.map((node) => {
60
+ const w = node.width ?? GRID.colW;
61
+ const lines = wrapText(node.label, TYPE.label, w - PLATE.padX * 2, 2);
62
+ const h = plateHeight(lines.length, Boolean(node.sublabel), true, node.height ?? 0);
63
+ const index = laneIndex.get(node.lane) ?? 0;
64
+ const box = {
65
+ x: colX(node.col),
66
+ y: laneY(index) + (GRID.laneH - h) / 2 + (node.yOffset ?? 0),
67
+ w,
68
+ h
69
+ };
70
+ boxes.set(node.id, box);
71
+ return { node, box, lane: index };
72
+ });
73
+ const mainPairs = /* @__PURE__ */ new Set();
74
+ for (let index = 0; index < (spec.mainPath?.length ?? 0) - 1; index += 1) {
75
+ mainPairs.add(`${spec.mainPath[index]}\u2192${spec.mainPath[index + 1]}`);
76
+ }
77
+ const wires = wiresFor(spec.edges, boxes, (edge) => {
78
+ const onMain = mainPairs.has(`${edge.from}\u2192${edge.to}`);
79
+ return {
80
+ weight: onMain ? 2.1 : void 0,
81
+ open: edge.role === "return"
82
+ };
83
+ });
84
+ const { paths, labels } = renderWires(wires, uid);
85
+ const laneBoxes = spec.lanes.map((lane, index) => {
86
+ const inside = placed.filter((entry) => entry.lane === index).map((entry) => entry.box);
87
+ const span = union(inside);
88
+ const left2 = span ? span.x - 14 : GRID.railW - 14;
89
+ return {
90
+ lane,
91
+ index,
92
+ box: {
93
+ x: left2,
94
+ y: laneY(index) - 8,
95
+ w: (span ? span.x + span.w + 14 : colX(0) + GRID.colW) - left2,
96
+ h: GRID.laneH + 16
97
+ }
98
+ };
99
+ });
100
+ const drawn = [...boxes.values(), ...laneBoxes.map((entry) => entry.box)];
101
+ const headerY = GRID.originY - 30;
102
+ const railTextW = Math.max(0, ...spec.lanes.map((lane) => textWidth(lane.label, 9)));
103
+ const raw = union(drawn) ?? { x: 0, y: 0, w: 600, h: 300 };
104
+ const left = Math.min(raw.x, GRID.railW - 26 - railTextW);
105
+ const top = Math.min(raw.y, headerY - 14);
106
+ const extent = inflate(
107
+ { x: left, y: top, w: raw.x + raw.w - left, h: raw.y + raw.h - top },
108
+ 24
109
+ );
110
+ const active = activeIds && activeIds.length > 0 ? new Set(activeIds) : null;
111
+ const artwork = /* @__PURE__ */ jsxs(Fragment, { children: [
112
+ (spec.phases ?? []).length > 0 && /* @__PURE__ */ jsx(
113
+ "path",
114
+ {
115
+ d: `M ${round(GRID.railW)} ${round(headerY + 8)} H ${round(extent.x + extent.w - 20)}`,
116
+ className: "stroke-(--diagram-rule)",
117
+ strokeWidth: 1,
118
+ "aria-hidden": "true"
119
+ }
120
+ ),
121
+ (spec.phases ?? []).map((phase) => /* @__PURE__ */ jsx(
122
+ "text",
123
+ {
124
+ x: round(colX(phase.fromCol)),
125
+ y: round(headerY),
126
+ className: "fill-(--diagram-ink-3) font-mono [font-size:9px] [letter-spacing:0.14em] uppercase",
127
+ "aria-hidden": "true",
128
+ children: phase.label
129
+ },
130
+ phase.id
131
+ )),
132
+ laneBoxes.map(({ lane, box }) => /* @__PURE__ */ jsxs("g", { "aria-hidden": "true", children: [
133
+ lane.variant === "exception" && /* @__PURE__ */ jsx(
134
+ "rect",
135
+ {
136
+ x: round(box.x),
137
+ y: round(box.y),
138
+ width: round(box.w),
139
+ height: round(box.h),
140
+ rx: 10,
141
+ className: "fill-(--diagram-band) [rx:var(--radius-lg)] [ry:var(--radius-lg)]"
142
+ }
143
+ ),
144
+ /* @__PURE__ */ jsx(
145
+ "text",
146
+ {
147
+ x: round(GRID.railW - 26),
148
+ y: round(box.y + box.h / 2 + 3),
149
+ textAnchor: "end",
150
+ className: "fill-(--diagram-ink-3) font-mono [font-size:9px] [letter-spacing:0.14em] uppercase",
151
+ children: lane.label
152
+ }
153
+ )
154
+ ] }, lane.id)),
155
+ (spec.groups ?? []).map((group) => {
156
+ const index = laneIndex.get(group.lane) ?? 0;
157
+ return /* @__PURE__ */ jsx(
158
+ BandFrame,
159
+ {
160
+ box: spanBox(group.fromCol, group.toCol, laneY(index) - 2, GRID.laneH + 4),
161
+ label: group.label,
162
+ dashed: group.variant === "security"
163
+ },
164
+ group.id
165
+ );
166
+ }),
167
+ paths,
168
+ placed.map(({ node, box }) => /* @__PURE__ */ jsx(
169
+ NodePlate,
170
+ {
171
+ nodeId: node.id,
172
+ box,
173
+ label: node.label,
174
+ sublabel: node.sublabel,
175
+ tag: node.tag,
176
+ kind: node.type,
177
+ active: active?.has(node.id),
178
+ dimmed: active ? !active.has(node.id) : false,
179
+ onSelect: onSelectNode ? () => onSelectNode(node.id) : void 0
180
+ },
181
+ node.id
182
+ )),
183
+ labels
184
+ ] });
185
+ const used = [...new Set((spec.edges ?? []).map((edge) => edge.variant ?? "default"))];
186
+ return {
187
+ extent,
188
+ artwork,
189
+ nodes: spec.nodes.map((node) => ({
190
+ id: node.id,
191
+ label: node.label,
192
+ sublabel: node.sublabel,
193
+ kind: node.type
194
+ })),
195
+ edges: (spec.edges ?? []).map((edge) => ({
196
+ from: edge.from,
197
+ to: edge.to,
198
+ label: edge.label
199
+ })),
200
+ legend: variantLegend(
201
+ resolveLegend(used, spec.meta.legend?.mode, VARIANTS, spec.meta.legend?.entries),
202
+ spec.meta.legend?.entries
203
+ )
204
+ };
205
+ }
206
+ var WorkflowFigure_default = WorkflowFigure;
207
+ export {
208
+ WorkflowFigure,
209
+ WorkflowFigure_default as default
210
+ };
211
+ //# sourceMappingURL=WorkflowFigure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/diagrams/WorkflowFigure/WorkflowFigure.tsx"],"sourcesContent":["'use client'\n\nimport { useId, useMemo } from 'react'\nimport { DiagramFrame, type FigureChrome, type FigureModel } from '../lib/frame'\nimport { inflate, round, textWidth, TYPE, union, wrapText, type Box } from '../lib/geometry'\nimport { resolveLegend, variantLegend } from '../lib/legend'\nimport { BandFrame, NodePlate, PLATE, plateHeight } from '../lib/marks'\nimport { renderWires, wiresFor, type Wire } from '../lib/wires'\nimport type { Variant, WorkflowEdge, WorkflowSpec } from '../spec'\n\nconst VARIANTS: (Variant | 'return')[] = ['default', 'emphasis', 'security', 'dashed']\n\nconst GRID = {\n /** The gutter the lane names live in. */\n railW: 118,\n originY: 74,\n colW: 168,\n gapX: 58,\n laneH: 92,\n laneGap: 40,\n}\n\nexport interface WorkflowFigureProps extends FigureChrome {\n spec: WorkflowSpec\n}\n\n/**\n * A process: who does what, in what order, and where it can go wrong.\n *\n * Three structures stacked on one grid, and they are three because they answer\n * three different questions a reader brings to a runbook.\n *\n * **Lanes** are rows and answer WHO. A lane marked `exception` is the one band\n * that gets a wash rather than a rule, and it earns the exception to the\n * frames-are-rules law because nothing routes across it — it IS the ground for\n * the failure path, not a frame drawn over the happy one.\n *\n * **Phases** are columns across every lane and answer WHEN. Printed as captions\n * on one header rule, because a phase is an axis label. **Groups** are frames\n * inside a single lane and answer WHAT BELONGS TOGETHER — a planning loop, an\n * evidence path.\n *\n * THE MAIN PATH IS HEAVIER, and that is the whole hierarchy. `mainPath` lists\n * the node ids a reader should be able to follow without thinking. Every edge\n * between two consecutive ids on it is drawn at the emphasis weight whatever\n * its own variant says, which is the one thing that turns fourteen boxes and\n * nineteen arrows into a diagram with a subject. An `error` role goes the other\n * way — dashed and soft — so the exception path recedes without disappearing.\n */\nexport function WorkflowFigure({\n spec,\n className,\n legend = 'auto',\n cards = true,\n heading = true,\n activeIds,\n onSelectNode,\n}: WorkflowFigureProps) {\n const uid = useId().replace(/:/g, '')\n const model = useMemo(\n () => buildModel(spec, uid, activeIds, onSelectNode),\n [spec, uid, activeIds, onSelectNode],\n )\n\n return (\n <DiagramFrame\n meta={spec.meta}\n model={model}\n cards={spec.cards}\n showCards={cards}\n heading={heading}\n legend={legend}\n className={className}\n activeIds={activeIds}\n onSelectNode={onSelectNode}\n />\n )\n}\n\n/** The x of a column's left edge, and of the whole span from `from` to `to`. */\nconst colX = (col: number) => GRID.railW + col * (GRID.colW + GRID.gapX)\nconst spanBox = (fromCol: number, toCol: number, y: number, h: number): Box => ({\n x: colX(fromCol),\n y,\n w: colX(toCol) + GRID.colW - colX(fromCol),\n h,\n})\n\nfunction buildModel(\n spec: WorkflowSpec,\n uid: string,\n activeIds: string[] | undefined,\n onSelectNode: ((id: string) => void) | undefined,\n): FigureModel {\n const laneIndex = new Map(spec.lanes.map((lane, index) => [lane.id, index]))\n const laneY = (index: number) => GRID.originY + index * (GRID.laneH + GRID.laneGap)\n\n const boxes = new Map<string, Box>()\n const placed = spec.nodes.map((node) => {\n const w = node.width ?? GRID.colW\n const lines = wrapText(node.label, TYPE.label, w - PLATE.padX * 2, 2)\n const h = plateHeight(lines.length, Boolean(node.sublabel), true, node.height ?? 0)\n const index = laneIndex.get(node.lane) ?? 0\n\n const box: Box = {\n x: colX(node.col),\n y: laneY(index) + (GRID.laneH - h) / 2 + (node.yOffset ?? 0),\n w,\n h,\n }\n boxes.set(node.id, box)\n return { node, box, lane: index }\n })\n\n // Consecutive pairs on the main path, so the edge between them can be drawn\n // at the weight that says \"follow this one\".\n const mainPairs = new Set<string>()\n for (let index = 0; index < (spec.mainPath?.length ?? 0) - 1; index += 1) {\n mainPairs.add(`${spec.mainPath![index]}→${spec.mainPath![index + 1]}`)\n }\n\n const wires = wiresFor(spec.edges, boxes, (edge: WorkflowEdge): Partial<Wire> => {\n const onMain = mainPairs.has(`${edge.from}→${edge.to}`)\n return {\n weight: onMain ? 2.1 : undefined,\n open: edge.role === 'return',\n }\n })\n const { paths, labels } = renderWires(wires, uid)\n\n // A lane's band spans what the lane actually holds. Starting it at the rail\n // instead ran the exception wash under the label gutter, which made the\n // gutter look like part of the band rather than like the axis it is.\n const laneBoxes = spec.lanes.map((lane, index) => {\n const inside = placed.filter((entry) => entry.lane === index).map((entry) => entry.box)\n const span = union(inside)\n const left = span ? span.x - 14 : GRID.railW - 14\n return {\n lane,\n index,\n box: {\n x: left,\n y: laneY(index) - 8,\n w: (span ? span.x + span.w + 14 : colX(0) + GRID.colW) - left,\n h: GRID.laneH + 16,\n } as Box,\n }\n })\n\n const drawn = [...boxes.values(), ...laneBoxes.map((entry) => entry.box)]\n const headerY = GRID.originY - 30\n\n // The frame has to hold what is printed OUTSIDE the boxes too: the lane names\n // in the gutter and the phase captions above the header rule. Sizing the\n // extent from the boxes alone clipped both — and a clipped axis label is the\n // one kind of overflow a reader reads as a broken renderer rather than as a\n // long word.\n const railTextW = Math.max(0, ...spec.lanes.map((lane) => textWidth(lane.label, 9)))\n const raw = union(drawn) ?? { x: 0, y: 0, w: 600, h: 300 }\n const left = Math.min(raw.x, GRID.railW - 26 - railTextW)\n const top = Math.min(raw.y, headerY - 14)\n const extent = inflate(\n { x: left, y: top, w: raw.x + raw.w - left, h: raw.y + raw.h - top },\n 24,\n )\n const active = activeIds && activeIds.length > 0 ? new Set(activeIds) : null\n\n const artwork = (\n <>\n {/* Phases: one header rule across the figure, with a caption per span. */}\n {(spec.phases ?? []).length > 0 && (\n <path\n d={`M ${round(GRID.railW)} ${round(headerY + 8)} H ${round(extent.x + extent.w - 20)}`}\n className=\"stroke-(--diagram-rule)\"\n strokeWidth={1}\n aria-hidden=\"true\"\n />\n )}\n {(spec.phases ?? []).map((phase) => (\n <text\n key={phase.id}\n x={round(colX(phase.fromCol))}\n y={round(headerY)}\n className=\"fill-(--diagram-ink-3) font-mono [font-size:9px] [letter-spacing:0.14em] uppercase\"\n aria-hidden=\"true\"\n >\n {phase.label}\n </text>\n ))}\n\n {/* Lanes. The exception band is the one wash in the system's diagrams. */}\n {laneBoxes.map(({ lane, box }) => (\n <g key={lane.id} aria-hidden=\"true\">\n {lane.variant === 'exception' && (\n <rect\n x={round(box.x)}\n y={round(box.y)}\n width={round(box.w)}\n height={round(box.h)}\n rx={10}\n className=\"fill-(--diagram-band) [rx:var(--radius-lg)] [ry:var(--radius-lg)]\"\n />\n )}\n <text\n x={round(GRID.railW - 26)}\n y={round(box.y + box.h / 2 + 3)}\n textAnchor=\"end\"\n className=\"fill-(--diagram-ink-3) font-mono [font-size:9px] [letter-spacing:0.14em] uppercase\"\n >\n {lane.label}\n </text>\n </g>\n ))}\n\n {/* Groups: a frame inside one lane. */}\n {(spec.groups ?? []).map((group) => {\n const index = laneIndex.get(group.lane) ?? 0\n return (\n <BandFrame\n key={group.id}\n box={spanBox(group.fromCol, group.toCol, laneY(index) - 2, GRID.laneH + 4)}\n label={group.label}\n dashed={group.variant === 'security'}\n />\n )\n })}\n\n {paths}\n\n {placed.map(({ node, box }) => (\n <NodePlate\n key={node.id}\n nodeId={node.id}\n box={box}\n label={node.label}\n sublabel={node.sublabel}\n tag={node.tag}\n kind={node.type}\n active={active?.has(node.id)}\n dimmed={active ? !active.has(node.id) : false}\n onSelect={onSelectNode ? () => onSelectNode(node.id) : undefined}\n />\n ))}\n\n {labels}\n </>\n )\n\n const used = [...new Set((spec.edges ?? []).map((edge) => edge.variant ?? 'default'))]\n\n return {\n extent,\n artwork,\n nodes: spec.nodes.map((node) => ({\n id: node.id,\n label: node.label,\n sublabel: node.sublabel,\n kind: node.type,\n })),\n edges: (spec.edges ?? []).map((edge) => ({\n from: edge.from,\n to: edge.to,\n label: edge.label,\n })),\n legend: variantLegend(\n resolveLegend(used, spec.meta.legend?.mode, VARIANTS, spec.meta.legend?.entries),\n spec.meta.legend?.entries,\n ),\n }\n}\n\nexport default WorkflowFigure\n"],"mappings":"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","names":["left"]}
@@ -0,0 +1,16 @@
1
+ export { ArchitectureBoundary, ArchitectureComponent, ArchitectureSpec, DataflowEdge, DataflowNode, DataflowSpec, DataflowStage, DiagramCard, DiagramMeta, DiagramSpecAny, DiagramView, EdgeBase, LegendMode, LifecycleLane, LifecycleSpec, LifecycleState, LifecycleStateKind, LifecycleTransition, NodeBase, NodeKind, Point, RouteMode, SequenceActivation, SequenceMessage, SequenceParticipant, SequenceSegment, SequenceSpec, Side, SourceRef, Variant, WorkflowEdge, WorkflowEdgeRole, WorkflowGroup, WorkflowLane, WorkflowNode, WorkflowPhase, WorkflowSpec } from './spec.js';
2
+ export { ArchitectureFigure, ArchitectureFigureProps } from './ArchitectureFigure/ArchitectureFigure.js';
3
+ export { WorkflowFigure, WorkflowFigureProps } from './WorkflowFigure/WorkflowFigure.js';
4
+ export { SequenceFigure, SequenceFigureProps } from './SequenceFigure/SequenceFigure.js';
5
+ export { DataflowFigure, DataflowFigureProps } from './DataflowFigure/DataflowFigure.js';
6
+ export { LifecycleFigure, LifecycleFigureProps } from './LifecycleFigure/LifecycleFigure.js';
7
+ export { CanvasView, DiagramCanvas, DiagramCanvasHandle, DiagramCanvasProps } from './DiagramCanvas/DiagramCanvas.js';
8
+ export { DiagramToolbar, DiagramToolbarGroup, DiagramToolbarProps } from './DiagramToolbar/DiagramToolbar.js';
9
+ export { DiagramExportMenu, DiagramExportMenuProps, ExportFormat, ExportResult, exportFigure } from './DiagramExportMenu/DiagramExportMenu.js';
10
+ export { DiagramInspector, DiagramInspectorProps, InspectorFact, InspectorLink } from './DiagramInspector/DiagramInspector.js';
11
+ export { DiagramMinimap, DiagramMinimapProps } from './DiagramMinimap/DiagramMinimap.js';
12
+ export { DiagramLegend, DiagramLegendEntry, DiagramLegendProps } from './DiagramLegend/DiagramLegend.js';
13
+ export { LegendEntry, kindLegend, resolveLegend, stateLegend, variantLegend } from './lib/legend.js';
14
+ export { FigureChrome } from './lib/frame.js';
15
+ import 'react';
16
+ import './lib/geometry.js';
@@ -0,0 +1,19 @@
1
+ export * from "./ArchitectureFigure/ArchitectureFigure.js";
2
+ export * from "./WorkflowFigure/WorkflowFigure.js";
3
+ export * from "./SequenceFigure/SequenceFigure.js";
4
+ export * from "./DataflowFigure/DataflowFigure.js";
5
+ export * from "./LifecycleFigure/LifecycleFigure.js";
6
+ export * from "./DiagramCanvas/DiagramCanvas.js";
7
+ export * from "./DiagramToolbar/DiagramToolbar.js";
8
+ export * from "./DiagramExportMenu/DiagramExportMenu.js";
9
+ export * from "./DiagramInspector/DiagramInspector.js";
10
+ export * from "./DiagramMinimap/DiagramMinimap.js";
11
+ export * from "./DiagramLegend/DiagramLegend.js";
12
+ import { kindLegend, resolveLegend, stateLegend, variantLegend } from "./lib/legend.js";
13
+ export {
14
+ kindLegend,
15
+ resolveLegend,
16
+ stateLegend,
17
+ variantLegend
18
+ };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/diagrams/index.ts"],"sourcesContent":["/**\n * @misoto22/design/diagrams — the public entry.\n *\n * Five renderers for the five diagram shapes software actually needs, plus the\n * chrome a reader explores one with. They ship from their own entry point\n * rather than from the package root for one reason: a page that renders a Badge\n * should not be paying for a routing engine. Nothing under `src/components`\n * imports anything here, so the main barrel stays the size it was.\n *\n * The specification types mirror\n * [archify](https://github.com/tt-a1i/archify)'s published JSON schemas, so a\n * document authored for that tool renders here with no translation step — in\n * this system's own monochrome terms rather than in archify's palette.\n *\n * The look ships with the rest of the package:\n *\n * import '@misoto22/design/styles.css'\n *\n * Everything below is a consumer contract. Adding an export is cheap; changing\n * or removing one is a breaking change (DESIGN-API-001).\n */\n\n// ─── Specifications ───\nexport type {\n ArchitectureBoundary,\n ArchitectureComponent,\n ArchitectureSpec,\n DataflowEdge,\n DataflowNode,\n DataflowSpec,\n DataflowStage,\n DiagramCard,\n DiagramMeta,\n DiagramSpecAny,\n DiagramView,\n EdgeBase,\n LegendMode,\n LifecycleLane,\n LifecycleSpec,\n LifecycleState,\n LifecycleStateKind,\n LifecycleTransition,\n NodeBase,\n NodeKind,\n Point,\n RouteMode,\n SequenceActivation,\n SequenceMessage,\n SequenceParticipant,\n SequenceSegment,\n SequenceSpec,\n Side,\n SourceRef,\n Variant,\n WorkflowEdge,\n WorkflowEdgeRole,\n WorkflowGroup,\n WorkflowLane,\n WorkflowNode,\n WorkflowPhase,\n WorkflowSpec,\n} from './spec'\n\n// ─── Figures ───\nexport * from './ArchitectureFigure/ArchitectureFigure'\nexport * from './WorkflowFigure/WorkflowFigure'\nexport * from './SequenceFigure/SequenceFigure'\nexport * from './DataflowFigure/DataflowFigure'\nexport * from './LifecycleFigure/LifecycleFigure'\n\n// ─── Chrome ───\nexport * from './DiagramCanvas/DiagramCanvas'\nexport * from './DiagramToolbar/DiagramToolbar'\nexport * from './DiagramExportMenu/DiagramExportMenu'\nexport * from './DiagramInspector/DiagramInspector'\nexport * from './DiagramMinimap/DiagramMinimap'\nexport * from './DiagramLegend/DiagramLegend'\n\n// ─── Building a key ───\nexport { kindLegend, resolveLegend, stateLegend, variantLegend } from './lib/legend'\nexport type { LegendEntry } from './lib/legend'\n\n// ─── Shared chrome types ───\nexport type { FigureChrome } from './lib/frame'\n"],"mappings":"AAgEA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AAGd,SAAS,YAAY,eAAe,aAAa,qBAAqB;","names":[]}
@@ -0,0 +1,97 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { LegendMode, DiagramCard, DiagramMeta } from '../spec.js';
4
+ import { Box } from './geometry.js';
5
+
6
+ /**
7
+ * What a figure hands the frame around it.
8
+ *
9
+ * Five renderers produce this one shape, which is what lets the title, the
10
+ * accessible summary, the key and the conclusion cards be written once. A
11
+ * renderer's only job is placing marks; everything a reader needs AROUND the
12
+ * picture is the same question in all five cases.
13
+ */
14
+ interface FigureModel {
15
+ /** The extent the artwork was drawn into. */
16
+ extent: Box;
17
+ artwork: ReactNode;
18
+ /** Every drawn box, for the summary list. */
19
+ nodes: {
20
+ id: string;
21
+ label: string;
22
+ sublabel?: string;
23
+ kind?: string;
24
+ }[];
25
+ /** Every drawn line, for the summary list. */
26
+ edges: {
27
+ from: string;
28
+ to: string;
29
+ label?: string;
30
+ }[];
31
+ /** The kinds actually used, and how each is drawn. */
32
+ legend: {
33
+ key: string;
34
+ label: string;
35
+ sample: ReactNode;
36
+ }[];
37
+ }
38
+ interface FigureChrome {
39
+ className?: string;
40
+ /** Prints the key under the figure. `auto` shows only the kinds in use. */
41
+ legend?: LegendMode;
42
+ /** Prints the conclusion cards under the figure. Defaults to true. */
43
+ cards?: boolean;
44
+ /** Prints the title and subtitle over the figure. Defaults to true. */
45
+ heading?: boolean;
46
+ /** Node ids currently lit. Everything else is dimmed. */
47
+ activeIds?: string[];
48
+ /**
49
+ * Called when a reader picks a node.
50
+ *
51
+ * Giving this turns the summary list from a description into a control: the
52
+ * same list a screen reader reads becomes the keyboard's route to selection,
53
+ * and the plates in the picture become the pointer's route to the same thing.
54
+ */
55
+ onSelectNode?: (id: string) => void;
56
+ }
57
+ /**
58
+ * The shell every figure sits in: a heading, the picture, a key, the cards, and
59
+ * the part that makes the picture mean anything to a reader who cannot see it.
60
+ *
61
+ * ## The accessibility decision, stated rather than implied
62
+ *
63
+ * The `<svg>` carries `role="img"` and a label, which makes its whole subtree
64
+ * presentational. That is the honest description of what it is — a picture —
65
+ * and it is what stops a screen reader from walking two hundred `<text>`
66
+ * elements in drawing order, which is neither reading order nor useful.
67
+ *
68
+ * The diagram's CONTENT is then published beside it as an ordinary list: every
69
+ * node with what kind of thing it is, and every relationship as "A → B: over
70
+ * HTTPS". That list is where the meaning lives for anyone not looking at the
71
+ * picture, and it is why this component takes a model rather than markup — a
72
+ * frame handed a finished `<svg>` could not have written it.
73
+ *
74
+ * The list is visually hidden by default and NOT hidden from assistive
75
+ * technology, which is the opposite of what `aria-hidden` would do and the
76
+ * whole point.
77
+ */
78
+ declare function DiagramFrame({ meta, model, cards, className, legend, showCards, heading, activeIds, onSelectNode, }: {
79
+ meta: DiagramMeta;
80
+ model: FigureModel;
81
+ cards?: DiagramCard[];
82
+ showCards?: boolean;
83
+ } & Omit<FigureChrome, 'cards'>): react.JSX.Element;
84
+ /**
85
+ * The conclusion cards under a figure.
86
+ *
87
+ * Archify keys these by hue — cyan, emerald, rose. Here the key selects a MARK:
88
+ * a filled square, a ring, a bar, a diagonal. Seven cards in a row stay seven
89
+ * distinguishable cards on paper-white, and the same row survives being
90
+ * printed.
91
+ */
92
+ declare function CardGrid({ cards, className }: {
93
+ cards: DiagramCard[];
94
+ className?: string;
95
+ }): react.JSX.Element;
96
+
97
+ export { CardGrid, DiagramFrame, type FigureChrome, type FigureModel };
@@ -0,0 +1,116 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId } from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import { viewBoxOf } from "./geometry.js";
6
+ import { DiagramLegend } from "../DiagramLegend/DiagramLegend.js";
7
+ import { DiagramDefs } from "./marks.js";
8
+ function DiagramFrame({
9
+ meta,
10
+ model,
11
+ cards,
12
+ className,
13
+ legend = "auto",
14
+ showCards = true,
15
+ heading = true,
16
+ activeIds,
17
+ onSelectNode
18
+ }) {
19
+ const uid = useId().replace(/:/g, "");
20
+ const titleId = `${uid}-title`;
21
+ const descId = `${uid}-desc`;
22
+ const byId = new Map(model.nodes.map((node) => [node.id, node]));
23
+ const description = `${model.nodes.length} elements and ${model.edges.length} relationships. ${meta.subtitle ?? ""}`.trim();
24
+ const showLegend = legend !== "hidden" && model.legend.length > 0;
25
+ return /* @__PURE__ */ jsxs("figure", { className: cn("m-0 flex flex-col gap-5", className), children: [
26
+ heading && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
27
+ /* @__PURE__ */ jsx("h3", { className: "m-0 font-heading text-[length:var(--fs-sub)] font-normal leading-[1.15] tracking-[-0.015em] text-(--ink)", children: meta.title }),
28
+ meta.subtitle && /* @__PURE__ */ jsx("span", { className: "mono-meta text-(--ink-3-aa)", children: meta.subtitle })
29
+ ] }),
30
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-(--radius-lg) border border-(--rule) bg-(--diagram-surface) p-[clamp(0.75rem,calc(1.6*var(--fluid)),1.25rem)] scroll-slim", children: /* @__PURE__ */ jsxs(
31
+ "svg",
32
+ {
33
+ viewBox: viewBoxOf(model.extent),
34
+ role: "img",
35
+ "aria-labelledby": `${titleId} ${descId}`,
36
+ className: "block h-auto w-full max-w-full font-sans",
37
+ "data-diagram-artwork": "",
38
+ children: [
39
+ /* @__PURE__ */ jsx("title", { id: titleId, children: meta.title }),
40
+ /* @__PURE__ */ jsx("desc", { id: descId, children: description }),
41
+ /* @__PURE__ */ jsx(DiagramDefs, { uid }),
42
+ model.artwork
43
+ ]
44
+ }
45
+ ) }),
46
+ /* @__PURE__ */ jsxs("div", { className: "sr-only", children: [
47
+ /* @__PURE__ */ jsx("p", { children: description }),
48
+ /* @__PURE__ */ jsx("ul", { children: model.nodes.map((node) => /* @__PURE__ */ jsx("li", { children: onSelectNode ? /* @__PURE__ */ jsx("button", { type: "button", onClick: () => onSelectNode(node.id), children: summaryLine(node) }) : summaryLine(node) }, node.id)) }),
49
+ model.edges.length > 0 && /* @__PURE__ */ jsx("ul", { children: model.edges.map((edge, index) => /* @__PURE__ */ jsxs("li", { children: [
50
+ byId.get(edge.from)?.label ?? edge.from,
51
+ " \u2192 ",
52
+ byId.get(edge.to)?.label ?? edge.to,
53
+ edge.label ? `: ${edge.label}` : ""
54
+ ] }, index)) })
55
+ ] }),
56
+ showLegend && /* @__PURE__ */ jsx(DiagramLegend, { entries: model.legend }),
57
+ showCards && cards && cards.length > 0 && /* @__PURE__ */ jsx(CardGrid, { cards }),
58
+ activeIds && activeIds.length > 0 && /* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", children: `${activeIds.length} highlighted` })
59
+ ] });
60
+ }
61
+ function summaryLine(node) {
62
+ const parts = [node.label];
63
+ if (node.kind) parts.push(`(${node.kind})`);
64
+ if (node.sublabel) parts.push(`\u2014 ${node.sublabel}`);
65
+ return parts.join(" ");
66
+ }
67
+ function CardGrid({ cards, className }) {
68
+ return /* @__PURE__ */ jsx(
69
+ "div",
70
+ {
71
+ className: cn(
72
+ "grid gap-3 sm:grid-cols-2 lg:grid-cols-3",
73
+ className
74
+ ),
75
+ children: cards.map((card) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 border-t border-(--ink) pt-3", children: [
76
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
77
+ /* @__PURE__ */ jsx(CardMark, { shape: card.dot }),
78
+ /* @__PURE__ */ jsx("span", { className: "font-sans text-[13.5px] leading-[1.35] text-(--ink)", children: card.title })
79
+ ] }),
80
+ /* @__PURE__ */ jsx("ul", { className: "m-0 flex list-none flex-col gap-1.5 p-0", children: card.items.map((item, index) => /* @__PURE__ */ jsx(
81
+ "li",
82
+ {
83
+ className: "text-[12.5px] leading-[1.55] text-(--ink-2) ps-3 -indent-3 before:content-['\u2014'] before:pe-1.5 before:text-(--ink-3-aa)",
84
+ children: item
85
+ },
86
+ index
87
+ )) })
88
+ ] }, card.title))
89
+ }
90
+ );
91
+ }
92
+ function CardMark({ shape }) {
93
+ const common = "size-2.5 shrink-0";
94
+ switch (shape) {
95
+ case "cyan":
96
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "bg-(--ink)") });
97
+ case "emerald":
98
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rounded-full bg-(--ink)") });
99
+ case "violet":
100
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rounded-full border border-(--ink)") });
101
+ case "amber":
102
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "border border-(--ink)") });
103
+ case "rose":
104
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rotate-45 bg-(--ink)") });
105
+ case "orange":
106
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rotate-45 border border-(--ink)") });
107
+ case "slate":
108
+ default:
109
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("h-1 w-2.5 shrink-0 bg-(--ink-3-aa)") });
110
+ }
111
+ }
112
+ export {
113
+ CardGrid,
114
+ DiagramFrame
115
+ };
116
+ //# sourceMappingURL=frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/diagrams/lib/frame.tsx"],"sourcesContent":["'use client'\n\nimport { useId, type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport type { DiagramCard, DiagramMeta, LegendMode } from '../spec'\nimport { viewBoxOf, type Box } from './geometry'\nimport { DiagramLegend } from '../DiagramLegend/DiagramLegend'\nimport { DiagramDefs } from './marks'\n\n/**\n * What a figure hands the frame around it.\n *\n * Five renderers produce this one shape, which is what lets the title, the\n * accessible summary, the key and the conclusion cards be written once. A\n * renderer's only job is placing marks; everything a reader needs AROUND the\n * picture is the same question in all five cases.\n */\nexport interface FigureModel {\n /** The extent the artwork was drawn into. */\n extent: Box\n artwork: ReactNode\n /** Every drawn box, for the summary list. */\n nodes: { id: string; label: string; sublabel?: string; kind?: string }[]\n /** Every drawn line, for the summary list. */\n edges: { from: string; to: string; label?: string }[]\n /** The kinds actually used, and how each is drawn. */\n legend: { key: string; label: string; sample: ReactNode }[]\n}\n\nexport interface FigureChrome {\n className?: string\n /** Prints the key under the figure. `auto` shows only the kinds in use. */\n legend?: LegendMode\n /** Prints the conclusion cards under the figure. Defaults to true. */\n cards?: boolean\n /** Prints the title and subtitle over the figure. Defaults to true. */\n heading?: boolean\n /** Node ids currently lit. Everything else is dimmed. */\n activeIds?: string[]\n /**\n * Called when a reader picks a node.\n *\n * Giving this turns the summary list from a description into a control: the\n * same list a screen reader reads becomes the keyboard's route to selection,\n * and the plates in the picture become the pointer's route to the same thing.\n */\n onSelectNode?: (id: string) => void\n}\n\n/**\n * The shell every figure sits in: a heading, the picture, a key, the cards, and\n * the part that makes the picture mean anything to a reader who cannot see it.\n *\n * ## The accessibility decision, stated rather than implied\n *\n * The `<svg>` carries `role=\"img\"` and a label, which makes its whole subtree\n * presentational. That is the honest description of what it is — a picture —\n * and it is what stops a screen reader from walking two hundred `<text>`\n * elements in drawing order, which is neither reading order nor useful.\n *\n * The diagram's CONTENT is then published beside it as an ordinary list: every\n * node with what kind of thing it is, and every relationship as \"A → B: over\n * HTTPS\". That list is where the meaning lives for anyone not looking at the\n * picture, and it is why this component takes a model rather than markup — a\n * frame handed a finished `<svg>` could not have written it.\n *\n * The list is visually hidden by default and NOT hidden from assistive\n * technology, which is the opposite of what `aria-hidden` would do and the\n * whole point.\n */\nexport function DiagramFrame({\n meta,\n model,\n cards,\n className,\n legend = 'auto',\n showCards = true,\n heading = true,\n activeIds,\n onSelectNode,\n}: {\n meta: DiagramMeta\n model: FigureModel\n cards?: DiagramCard[]\n showCards?: boolean\n} & Omit<FigureChrome, 'cards'>) {\n const uid = useId().replace(/:/g, '')\n const titleId = `${uid}-title`\n const descId = `${uid}-desc`\n\n const byId = new Map(model.nodes.map((node) => [node.id, node]))\n const description = `${model.nodes.length} elements and ${model.edges.length} relationships. ${\n meta.subtitle ?? ''\n }`.trim()\n\n const showLegend = legend !== 'hidden' && model.legend.length > 0\n\n return (\n <figure className={cn('m-0 flex flex-col gap-5', className)}>\n {/* The title is set in the editorial serif, which is the system's own\n answer to \"this is a heading\" — and it is what stops a figure from\n reading as a screenshot dropped into the page. The subtitle stays in\n the meta voice underneath it. */}\n {heading && (\n <div className=\"flex flex-col gap-1.5\">\n <h3 className=\"m-0 font-heading text-[length:var(--fs-sub)] font-normal leading-[1.15] tracking-[-0.015em] text-(--ink)\">\n {meta.title}\n </h3>\n {meta.subtitle && <span className=\"mono-meta text-(--ink-3-aa)\">{meta.subtitle}</span>}\n </div>\n )}\n\n <div className=\"overflow-x-auto rounded-(--radius-lg) border border-(--rule) bg-(--diagram-surface) p-[clamp(0.75rem,calc(1.6*var(--fluid)),1.25rem)] scroll-slim\">\n <svg\n viewBox={viewBoxOf(model.extent)}\n role=\"img\"\n aria-labelledby={`${titleId} ${descId}`}\n className=\"block h-auto w-full max-w-full font-sans\"\n data-diagram-artwork=\"\"\n >\n <title id={titleId}>{meta.title}</title>\n <desc id={descId}>{description}</desc>\n <DiagramDefs uid={uid} />\n {model.artwork}\n </svg>\n </div>\n\n {/* The picture's content, for anyone not looking at the picture. */}\n <div className=\"sr-only\">\n <p>{description}</p>\n <ul>\n {model.nodes.map((node) => (\n <li key={node.id}>\n {onSelectNode ? (\n <button type=\"button\" onClick={() => onSelectNode(node.id)}>\n {summaryLine(node)}\n </button>\n ) : (\n summaryLine(node)\n )}\n </li>\n ))}\n </ul>\n {model.edges.length > 0 && (\n <ul>\n {model.edges.map((edge, index) => (\n <li key={index}>\n {(byId.get(edge.from)?.label ?? edge.from)} → {(byId.get(edge.to)?.label ?? edge.to)}\n {edge.label ? `: ${edge.label}` : ''}\n </li>\n ))}\n </ul>\n )}\n </div>\n\n {showLegend && <DiagramLegend entries={model.legend} />}\n\n {showCards && cards && cards.length > 0 && <CardGrid cards={cards} />}\n\n {activeIds && activeIds.length > 0 && <span className=\"sr-only\" role=\"status\">{`${activeIds.length} highlighted`}</span>}\n </figure>\n )\n}\n\nfunction summaryLine(node: { label: string; sublabel?: string; kind?: string }): string {\n const parts = [node.label]\n if (node.kind) parts.push(`(${node.kind})`)\n if (node.sublabel) parts.push(`— ${node.sublabel}`)\n return parts.join(' ')\n}\n\n/**\n * The conclusion cards under a figure.\n *\n * Archify keys these by hue — cyan, emerald, rose. Here the key selects a MARK:\n * a filled square, a ring, a bar, a diagonal. Seven cards in a row stay seven\n * distinguishable cards on paper-white, and the same row survives being\n * printed.\n */\nexport function CardGrid({ cards, className }: { cards: DiagramCard[]; className?: string }) {\n return (\n <div\n className={cn(\n 'grid gap-3 sm:grid-cols-2 lg:grid-cols-3',\n className,\n )}\n >\n {cards.map((card) => (\n <div key={card.title} className=\"flex flex-col gap-2.5 border-t border-(--ink) pt-3\">\n <div className=\"flex items-center gap-2\">\n <CardMark shape={card.dot} />\n <span className=\"font-sans text-[13.5px] leading-[1.35] text-(--ink)\">{card.title}</span>\n </div>\n <ul className=\"m-0 flex list-none flex-col gap-1.5 p-0\">\n {card.items.map((item, index) => (\n <li\n key={index}\n className=\"text-[12.5px] leading-[1.55] text-(--ink-2) ps-3 -indent-3 before:content-['—'] before:pe-1.5 before:text-(--ink-3-aa)\"\n >\n {item}\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n )\n}\n\n/** Seven marks, one per archify dot name, and not one of them a hue. */\nfunction CardMark({ shape }: { shape: DiagramCard['dot'] }) {\n const common = 'size-2.5 shrink-0'\n switch (shape) {\n case 'cyan':\n return <span aria-hidden className={cn(common, 'bg-(--ink)')} />\n case 'emerald':\n return <span aria-hidden className={cn(common, 'rounded-full bg-(--ink)')} />\n case 'violet':\n return <span aria-hidden className={cn(common, 'rounded-full border border-(--ink)')} />\n case 'amber':\n return <span aria-hidden className={cn(common, 'border border-(--ink)')} />\n case 'rose':\n return <span aria-hidden className={cn(common, 'rotate-45 bg-(--ink)')} />\n case 'orange':\n return <span aria-hidden className={cn(common, 'rotate-45 border border-(--ink)')} />\n case 'slate':\n default:\n return <span aria-hidden className={cn('h-1 w-2.5 shrink-0 bg-(--ink-3-aa)')} />\n }\n}\n"],"mappings":"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","names":[]}