@misoto22/design 0.6.1 → 0.8.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 (402) hide show
  1. package/AGENTS.md +87 -0
  2. package/CLAUDE.md +1 -0
  3. package/README.md +62 -5
  4. package/bin/misoto22-design.mjs +59 -13
  5. package/dist/agent/Accordion.md +24 -1
  6. package/dist/agent/Alert.md +23 -1
  7. package/dist/agent/AppShell.md +30 -2
  8. package/dist/agent/ArchitectureFigure.md +71 -0
  9. package/dist/agent/AreaChart.md +27 -2
  10. package/dist/agent/Article.md +26 -3
  11. package/dist/agent/AspectRatio.md +57 -0
  12. package/dist/agent/Avatar.md +25 -5
  13. package/dist/agent/Badge.md +22 -1
  14. package/dist/agent/BarChart.md +29 -2
  15. package/dist/agent/BarList.md +27 -1
  16. package/dist/agent/BigNumber.md +26 -2
  17. package/dist/agent/BoxPlot.md +24 -1
  18. package/dist/agent/Breadcrumb.md +24 -2
  19. package/dist/agent/BulletChart.md +23 -1
  20. package/dist/agent/Button.md +25 -1
  21. package/dist/agent/Calendar.md +37 -3
  22. package/dist/agent/Card.md +24 -2
  23. package/dist/agent/Checkbox.md +23 -2
  24. package/dist/agent/Code.md +50 -0
  25. package/dist/agent/CodeBlock.md +74 -0
  26. package/dist/agent/Collapsible.md +22 -1
  27. package/dist/agent/Combobox.md +29 -3
  28. package/dist/agent/Command.md +25 -2
  29. package/dist/agent/ComposedChart.md +26 -2
  30. package/dist/agent/ContextMenu.md +37 -4
  31. package/dist/agent/DataflowFigure.md +48 -0
  32. package/dist/agent/DatePicker.md +34 -6
  33. package/dist/agent/DescriptionList.md +68 -0
  34. package/dist/agent/Diagram.md +27 -3
  35. package/dist/agent/DiagramCanvas.md +70 -0
  36. package/dist/agent/DiagramExportMenu.md +64 -0
  37. package/dist/agent/DiagramInspector.md +72 -0
  38. package/dist/agent/DiagramLegend.md +55 -0
  39. package/dist/agent/DiagramMinimap.md +68 -0
  40. package/dist/agent/DiagramToolbar.md +69 -0
  41. package/dist/agent/Dialog.md +26 -3
  42. package/dist/agent/DropdownMenu.md +45 -6
  43. package/dist/agent/EmptyState.md +26 -1
  44. package/dist/agent/ErrorState.md +27 -2
  45. package/dist/agent/Facet.md +25 -1
  46. package/dist/agent/Field.md +45 -4
  47. package/dist/agent/FigureBand.md +24 -1
  48. package/dist/agent/FloatingIconButton.md +23 -1
  49. package/dist/agent/FunnelChart.md +23 -1
  50. package/dist/agent/Heading.md +64 -0
  51. package/dist/agent/Heatmap.md +25 -1
  52. package/dist/agent/Histogram.md +26 -2
  53. package/dist/agent/Input.md +22 -1
  54. package/dist/agent/Kbd.md +19 -1
  55. package/dist/agent/LifecycleFigure.md +49 -0
  56. package/dist/agent/LineChart.md +26 -2
  57. package/dist/agent/LinkArrow.md +20 -1
  58. package/dist/agent/Markdown.md +68 -0
  59. package/dist/agent/NativeSelect.md +23 -2
  60. package/dist/agent/NavItem.md +21 -1
  61. package/dist/agent/Pagination.md +28 -2
  62. package/dist/agent/PieChart.md +26 -2
  63. package/dist/agent/Popover.md +23 -1
  64. package/dist/agent/Progress.md +27 -3
  65. package/dist/agent/RadarChart.md +26 -2
  66. package/dist/agent/RadialChart.md +26 -3
  67. package/dist/agent/RadioGroup.md +23 -2
  68. package/dist/agent/SankeyChart.md +25 -2
  69. package/dist/agent/ScatterChart.md +27 -2
  70. package/dist/agent/ScrollArea.md +24 -3
  71. package/dist/agent/SearchableMenu.md +23 -1
  72. package/dist/agent/Select.md +29 -3
  73. package/dist/agent/Separator.md +28 -4
  74. package/dist/agent/SequenceFigure.md +50 -0
  75. package/dist/agent/Sheet.md +25 -2
  76. package/dist/agent/Skeleton.md +24 -2
  77. package/dist/agent/Slider.md +27 -4
  78. package/dist/agent/Sparkline.md +23 -1
  79. package/dist/agent/Spinner.md +24 -2
  80. package/dist/agent/StatusDot.md +20 -1
  81. package/dist/agent/StatusPill.md +28 -2
  82. package/dist/agent/Steps.md +24 -1
  83. package/dist/agent/Switch.md +21 -1
  84. package/dist/agent/Table.md +26 -3
  85. package/dist/agent/Tabs.md +24 -2
  86. package/dist/agent/Tag.md +40 -9
  87. package/dist/agent/Text.md +65 -0
  88. package/dist/agent/Textarea.md +20 -1
  89. package/dist/agent/Timestamp.md +64 -0
  90. package/dist/agent/Toast.md +26 -2
  91. package/dist/agent/ToggleGroup.md +24 -2
  92. package/dist/agent/Toolbar.md +71 -0
  93. package/dist/agent/Tooltip.md +23 -1
  94. package/dist/agent/TreemapChart.md +24 -1
  95. package/dist/agent/WaterfallChart.md +24 -1
  96. package/dist/agent/WorkflowFigure.md +50 -0
  97. package/dist/agent/catalog.json +6086 -1009
  98. package/dist/agent/index.md +27 -4
  99. package/dist/article.css +16 -4
  100. package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
  101. package/dist/charts/AreaChart/AreaChart.js +12 -13
  102. package/dist/charts/AreaChart/AreaChart.js.map +1 -1
  103. package/dist/charts/BarChart/BarChart.d.ts +14 -3
  104. package/dist/charts/BarChart/BarChart.js +20 -12
  105. package/dist/charts/BarChart/BarChart.js.map +1 -1
  106. package/dist/charts/BarList/BarList.d.ts +9 -1
  107. package/dist/charts/BarList/BarList.js +9 -1
  108. package/dist/charts/BarList/BarList.js.map +1 -1
  109. package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
  110. package/dist/charts/BigNumber/BigNumber.js +25 -5
  111. package/dist/charts/BigNumber/BigNumber.js.map +1 -1
  112. package/dist/charts/BoxPlot/BoxPlot.js +4 -2
  113. package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
  114. package/dist/charts/BulletChart/BulletChart.js +28 -7
  115. package/dist/charts/BulletChart/BulletChart.js.map +1 -1
  116. package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
  117. package/dist/charts/ComposedChart/ComposedChart.js +10 -10
  118. package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
  119. package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
  120. package/dist/charts/FunnelChart/FunnelChart.js +6 -16
  121. package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
  122. package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
  123. package/dist/charts/Heatmap/Heatmap.js +20 -11
  124. package/dist/charts/Heatmap/Heatmap.js.map +1 -1
  125. package/dist/charts/Histogram/Histogram.d.ts +24 -1
  126. package/dist/charts/Histogram/Histogram.js +43 -11
  127. package/dist/charts/Histogram/Histogram.js.map +1 -1
  128. package/dist/charts/LineChart/LineChart.d.ts +9 -2
  129. package/dist/charts/LineChart/LineChart.js +11 -12
  130. package/dist/charts/LineChart/LineChart.js.map +1 -1
  131. package/dist/charts/PieChart/PieChart.d.ts +15 -3
  132. package/dist/charts/PieChart/PieChart.js +14 -6
  133. package/dist/charts/PieChart/PieChart.js.map +1 -1
  134. package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
  135. package/dist/charts/RadarChart/RadarChart.js +11 -9
  136. package/dist/charts/RadarChart/RadarChart.js.map +1 -1
  137. package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
  138. package/dist/charts/RadialChart/RadialChart.js +28 -6
  139. package/dist/charts/RadialChart/RadialChart.js.map +1 -1
  140. package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
  141. package/dist/charts/SankeyChart/SankeyChart.js +14 -6
  142. package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
  143. package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
  144. package/dist/charts/ScatterChart/ScatterChart.js +21 -15
  145. package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
  146. package/dist/charts/Sparkline/Sparkline.js +5 -3
  147. package/dist/charts/Sparkline/Sparkline.js.map +1 -1
  148. package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
  149. package/dist/charts/TreemapChart/TreemapChart.js +20 -11
  150. package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
  151. package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
  152. package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
  153. package/dist/charts/index.d.ts +2 -1
  154. package/dist/charts/lib/export.d.ts +34 -43
  155. package/dist/charts/lib/export.js +16 -158
  156. package/dist/charts/lib/export.js.map +1 -1
  157. package/dist/charts/lib/figure.d.ts +21 -1
  158. package/dist/charts/lib/figure.js +5 -2
  159. package/dist/charts/lib/figure.js.map +1 -1
  160. package/dist/charts/lib/scale.d.ts +23 -0
  161. package/dist/charts/lib/scale.js +13 -0
  162. package/dist/charts/lib/scale.js.map +1 -0
  163. package/dist/charts/lib/selection.d.ts +20 -0
  164. package/dist/charts/lib/selection.js +18 -0
  165. package/dist/charts/lib/selection.js.map +1 -0
  166. package/dist/charts/lib/toolbar.d.ts +1 -0
  167. package/dist/components/Accordion/Accordion.js +8 -1
  168. package/dist/components/Accordion/Accordion.js.map +1 -1
  169. package/dist/components/AppShell/AppShell.d.ts +6 -0
  170. package/dist/components/AppShell/AppShell.js +34 -4
  171. package/dist/components/AppShell/AppShell.js.map +1 -1
  172. package/dist/components/Article/Article.d.ts +11 -4
  173. package/dist/components/Article/Article.js +13 -0
  174. package/dist/components/Article/Article.js.map +1 -1
  175. package/dist/components/AspectRatio/AspectRatio.d.ts +46 -0
  176. package/dist/components/AspectRatio/AspectRatio.js +33 -0
  177. package/dist/components/AspectRatio/AspectRatio.js.map +1 -0
  178. package/dist/components/Avatar/Avatar.d.ts +12 -3
  179. package/dist/components/Avatar/Avatar.js +6 -1
  180. package/dist/components/Avatar/Avatar.js.map +1 -1
  181. package/dist/components/Breadcrumb/Breadcrumb.d.ts +6 -0
  182. package/dist/components/Breadcrumb/Breadcrumb.js +15 -0
  183. package/dist/components/Breadcrumb/Breadcrumb.js.map +1 -1
  184. package/dist/components/Button/Button.js +14 -0
  185. package/dist/components/Button/Button.js.map +1 -1
  186. package/dist/components/Calendar/Calendar.d.ts +29 -3
  187. package/dist/components/Calendar/Calendar.js +60 -12
  188. package/dist/components/Calendar/Calendar.js.map +1 -1
  189. package/dist/components/Card/Card.d.ts +6 -0
  190. package/dist/components/Card/Card.js +1 -1
  191. package/dist/components/Card/Card.js.map +1 -1
  192. package/dist/components/Checkbox/Checkbox.d.ts +5 -2
  193. package/dist/components/Checkbox/Checkbox.js +12 -2
  194. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  195. package/dist/components/Code/Code.d.ts +30 -0
  196. package/dist/components/Code/Code.js +21 -0
  197. package/dist/components/Code/Code.js.map +1 -0
  198. package/dist/components/CodeBlock/CodeBlock.d.ts +141 -0
  199. package/dist/components/CodeBlock/CodeBlock.js +123 -0
  200. package/dist/components/CodeBlock/CodeBlock.js.map +1 -0
  201. package/dist/components/Collapsible/Collapsible.js +10 -2
  202. package/dist/components/Collapsible/Collapsible.js.map +1 -1
  203. package/dist/components/Combobox/Combobox.d.ts +15 -1
  204. package/dist/components/Combobox/Combobox.js +25 -5
  205. package/dist/components/Combobox/Combobox.js.map +1 -1
  206. package/dist/components/Command/Command.d.ts +4 -2
  207. package/dist/components/Command/Command.js +13 -1
  208. package/dist/components/Command/Command.js.map +1 -1
  209. package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
  210. package/dist/components/ContextMenu/ContextMenu.js +32 -2
  211. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  212. package/dist/components/DatePicker/DatePicker.d.ts +36 -4
  213. package/dist/components/DatePicker/DatePicker.js +55 -12
  214. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  215. package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
  216. package/dist/components/DescriptionList/DescriptionList.js +35 -0
  217. package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
  218. package/dist/components/Diagram/Diagram.d.ts +8 -3
  219. package/dist/components/Diagram/Diagram.js +82 -10
  220. package/dist/components/Diagram/Diagram.js.map +1 -1
  221. package/dist/components/Dialog/Dialog.d.ts +18 -3
  222. package/dist/components/Dialog/Dialog.js +20 -2
  223. package/dist/components/Dialog/Dialog.js.map +1 -1
  224. package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
  225. package/dist/components/DropdownMenu/DropdownMenu.js +32 -2
  226. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  227. package/dist/components/EmptyState/EmptyState.d.ts +25 -1
  228. package/dist/components/EmptyState/EmptyState.js +3 -1
  229. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  230. package/dist/components/ErrorState/ErrorState.d.ts +22 -1
  231. package/dist/components/ErrorState/ErrorState.js +11 -2
  232. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  233. package/dist/components/Field/Field.d.ts +70 -3
  234. package/dist/components/Field/Field.js +53 -12
  235. package/dist/components/Field/Field.js.map +1 -1
  236. package/dist/components/Field/field-control.d.ts +31 -0
  237. package/dist/components/Field/field-control.js +12 -0
  238. package/dist/components/Field/field-control.js.map +1 -0
  239. package/dist/components/FloatingIconButton/FloatingIconButton.js +2 -0
  240. package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
  241. package/dist/components/Heading/Heading.d.ts +62 -0
  242. package/dist/components/Heading/Heading.js +44 -0
  243. package/dist/components/Heading/Heading.js.map +1 -0
  244. package/dist/components/Markdown/Markdown.d.ts +139 -0
  245. package/dist/components/Markdown/Markdown.js +135 -0
  246. package/dist/components/Markdown/Markdown.js.map +1 -0
  247. package/dist/components/Markdown/inline.d.ts +29 -0
  248. package/dist/components/Markdown/inline.js +74 -0
  249. package/dist/components/Markdown/inline.js.map +1 -0
  250. package/dist/components/Markdown/nodes.d.ts +65 -0
  251. package/dist/components/Markdown/nodes.js +1 -0
  252. package/dist/components/Markdown/nodes.js.map +1 -0
  253. package/dist/components/Markdown/parse.d.ts +24 -0
  254. package/dist/components/Markdown/parse.js +110 -0
  255. package/dist/components/Markdown/parse.js.map +1 -0
  256. package/dist/components/Markdown/slug.d.ts +15 -0
  257. package/dist/components/Markdown/slug.js +7 -0
  258. package/dist/components/Markdown/slug.js.map +1 -0
  259. package/dist/components/NativeSelect/NativeSelect.d.ts +6 -0
  260. package/dist/components/NativeSelect/NativeSelect.js +2 -3
  261. package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
  262. package/dist/components/Pagination/Pagination.d.ts +24 -1
  263. package/dist/components/Pagination/Pagination.js +6 -3
  264. package/dist/components/Pagination/Pagination.js.map +1 -1
  265. package/dist/components/Progress/Progress.d.ts +17 -5
  266. package/dist/components/Progress/Progress.js +18 -6
  267. package/dist/components/Progress/Progress.js.map +1 -1
  268. package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
  269. package/dist/components/RadioGroup/RadioGroup.js +11 -1
  270. package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
  271. package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
  272. package/dist/components/ScrollArea/ScrollArea.js +2 -2
  273. package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
  274. package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
  275. package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
  276. package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
  277. package/dist/components/Select/Select.d.ts +18 -2
  278. package/dist/components/Select/Select.js +20 -3
  279. package/dist/components/Select/Select.js.map +1 -1
  280. package/dist/components/Separator/Separator.d.ts +21 -3
  281. package/dist/components/Separator/Separator.js +9 -1
  282. package/dist/components/Separator/Separator.js.map +1 -1
  283. package/dist/components/Sheet/Sheet.d.ts +3 -0
  284. package/dist/components/Sheet/Sheet.js +11 -2
  285. package/dist/components/Sheet/Sheet.js.map +1 -1
  286. package/dist/components/Skeleton/Skeleton.d.ts +8 -1
  287. package/dist/components/Skeleton/Skeleton.js +1 -1
  288. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  289. package/dist/components/Slider/Slider.d.ts +21 -3
  290. package/dist/components/Slider/Slider.js +54 -27
  291. package/dist/components/Slider/Slider.js.map +1 -1
  292. package/dist/components/Spinner/Spinner.d.ts +8 -0
  293. package/dist/components/Spinner/Spinner.js +3 -2
  294. package/dist/components/Spinner/Spinner.js.map +1 -1
  295. package/dist/components/StatusPill/StatusPill.d.ts +5 -0
  296. package/dist/components/StatusPill/StatusPill.js +6 -0
  297. package/dist/components/StatusPill/StatusPill.js.map +1 -1
  298. package/dist/components/Table/Table.d.ts +6 -0
  299. package/dist/components/Table/Table.js +3 -1
  300. package/dist/components/Table/Table.js.map +1 -1
  301. package/dist/components/Tag/Tag.d.ts +68 -9
  302. package/dist/components/Tag/Tag.js +50 -10
  303. package/dist/components/Tag/Tag.js.map +1 -1
  304. package/dist/components/Text/Text.d.ts +62 -0
  305. package/dist/components/Text/Text.js +30 -0
  306. package/dist/components/Text/Text.js.map +1 -0
  307. package/dist/components/Timestamp/Timestamp.d.ts +59 -0
  308. package/dist/components/Timestamp/Timestamp.js +56 -0
  309. package/dist/components/Timestamp/Timestamp.js.map +1 -0
  310. package/dist/components/Toast/Toast.d.ts +9 -1
  311. package/dist/components/Toast/Toast.js +27 -4
  312. package/dist/components/Toast/Toast.js.map +1 -1
  313. package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
  314. package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
  315. package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
  316. package/dist/components/Toolbar/Toolbar.d.ts +55 -0
  317. package/dist/components/Toolbar/Toolbar.js +43 -0
  318. package/dist/components/Toolbar/Toolbar.js.map +1 -0
  319. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +55 -0
  320. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +175 -0
  321. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -0
  322. package/dist/diagrams/DataflowFigure/DataflowFigure.d.ts +28 -0
  323. package/dist/diagrams/DataflowFigure/DataflowFigure.js +148 -0
  324. package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -0
  325. package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +78 -0
  326. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +229 -0
  327. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -0
  328. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +106 -0
  329. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +123 -0
  330. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -0
  331. package/dist/diagrams/DiagramInspector/DiagramInspector.d.ts +70 -0
  332. package/dist/diagrams/DiagramInspector/DiagramInspector.js +94 -0
  333. package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -0
  334. package/dist/diagrams/DiagramLegend/DiagramLegend.d.ts +42 -0
  335. package/dist/diagrams/DiagramLegend/DiagramLegend.js +35 -0
  336. package/dist/diagrams/DiagramLegend/DiagramLegend.js.map +1 -0
  337. package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +77 -0
  338. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +106 -0
  339. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -0
  340. package/dist/diagrams/DiagramToolbar/DiagramToolbar.d.ts +48 -0
  341. package/dist/diagrams/DiagramToolbar/DiagramToolbar.js +53 -0
  342. package/dist/diagrams/DiagramToolbar/DiagramToolbar.js.map +1 -0
  343. package/dist/diagrams/LifecycleFigure/LifecycleFigure.d.ts +31 -0
  344. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +234 -0
  345. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -0
  346. package/dist/diagrams/SequenceFigure/SequenceFigure.d.ts +38 -0
  347. package/dist/diagrams/SequenceFigure/SequenceFigure.js +261 -0
  348. package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -0
  349. package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +36 -0
  350. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +259 -0
  351. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -0
  352. package/dist/diagrams/index.d.ts +17 -0
  353. package/dist/diagrams/index.js +29 -0
  354. package/dist/diagrams/index.js.map +1 -0
  355. package/dist/diagrams/lib/dev.d.ts +61 -0
  356. package/dist/diagrams/lib/dev.js +96 -0
  357. package/dist/diagrams/lib/dev.js.map +1 -0
  358. package/dist/diagrams/lib/frame.d.ts +138 -0
  359. package/dist/diagrams/lib/frame.js +131 -0
  360. package/dist/diagrams/lib/frame.js.map +1 -0
  361. package/dist/diagrams/lib/geometry.d.ts +114 -0
  362. package/dist/diagrams/lib/geometry.js +113 -0
  363. package/dist/diagrams/lib/geometry.js.map +1 -0
  364. package/dist/diagrams/lib/legend.d.ts +32 -0
  365. package/dist/diagrams/lib/legend.js +84 -0
  366. package/dist/diagrams/lib/legend.js.map +1 -0
  367. package/dist/diagrams/lib/marks.d.ts +207 -0
  368. package/dist/diagrams/lib/marks.js +480 -0
  369. package/dist/diagrams/lib/marks.js.map +1 -0
  370. package/dist/diagrams/lib/route.d.ts +85 -0
  371. package/dist/diagrams/lib/route.js +178 -0
  372. package/dist/diagrams/lib/route.js.map +1 -0
  373. package/dist/diagrams/lib/wires.d.ts +59 -0
  374. package/dist/diagrams/lib/wires.js +90 -0
  375. package/dist/diagrams/lib/wires.js.map +1 -0
  376. package/dist/diagrams/spec.d.ts +405 -0
  377. package/dist/diagrams/spec.js +1 -0
  378. package/dist/diagrams/spec.js.map +1 -0
  379. package/dist/index.d.ts +16 -4
  380. package/dist/index.js +9 -0
  381. package/dist/index.js.map +1 -1
  382. package/dist/keyframes.css +57 -3
  383. package/dist/lib/overlay-container.d.ts +14 -4
  384. package/dist/lib/overlay-container.js.map +1 -1
  385. package/dist/lib/svg-export.d.ts +138 -0
  386. package/dist/lib/svg-export.js +198 -0
  387. package/dist/lib/svg-export.js.map +1 -0
  388. package/dist/lib/warn.d.ts +73 -0
  389. package/dist/lib/warn.js +38 -0
  390. package/dist/lib/warn.js.map +1 -0
  391. package/dist/semantic.css +51 -6
  392. package/dist/styles.css +1 -1
  393. package/dist/tokens.css +20 -2
  394. package/dist/tokens.d.ts +17 -1
  395. package/dist/tokens.js +121 -36
  396. package/dist/tokens.json +121 -36
  397. package/llms.txt +35 -0
  398. package/package.json +9 -2
  399. package/skills/misoto22-design/SKILL.md +21 -7
  400. package/skills/misoto22-design/evals/evals.json +84 -0
  401. package/skills/misoto22-design/rules/a11y.md +55 -3
  402. package/skills/misoto22-design/rules/forms.md +5 -0
@@ -0,0 +1,138 @@
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: FigureNode[];
20
+ /** Every drawn line, for the summary list. */
21
+ edges: {
22
+ from: string;
23
+ to: string;
24
+ label?: string;
25
+ }[];
26
+ /** The kinds actually used, and how each is drawn. */
27
+ legend: {
28
+ key: string;
29
+ label: string;
30
+ sample: ReactNode;
31
+ }[];
32
+ /**
33
+ * The figure's second axis, as a PARTITION of the nodes above.
34
+ *
35
+ * A workflow's lanes and a data flow's stages are not decoration around the
36
+ * boxes — they are the other half of every box's position, and a summary that
37
+ * lists the boxes alone has published one dimension of a two-dimensional
38
+ * picture. Giving the list this structure says it once, in the place a screen
39
+ * reader already walks, rather than repeating "in the CI lane" on every row.
40
+ *
41
+ * A node may appear in at most one band: the list is the keyboard's only
42
+ * route to a selection, and a node in two bands is two controls that do the
43
+ * same thing. Anything left out of every band is published after them.
44
+ */
45
+ bands?: FigureBand[];
46
+ /**
47
+ * What the picture says that is neither a box nor a line.
48
+ *
49
+ * Boundaries, phase captions, segment captions, activation bars: each is a
50
+ * real statement drawn inside an `aria-hidden` `<svg>`, and each is a
51
+ * sentence rather than a row, so each figure writes its own.
52
+ */
53
+ notes?: string[];
54
+ }
55
+ /** One drawn box, as the summary publishes it. */
56
+ interface FigureNode {
57
+ id: string;
58
+ label: string;
59
+ sublabel?: string;
60
+ kind?: string;
61
+ /** A short phrase the picture prints on the box: a step number. */
62
+ detail?: string;
63
+ }
64
+ /** One band of a figure's second axis: a lane, a stage. */
65
+ interface FigureBand {
66
+ /** What KIND of band this is — "Lane", "Stage" — since the label is a name. */
67
+ kind: string;
68
+ label: string;
69
+ /** The nodes inside it, in the order the figure draws them. */
70
+ ids: string[];
71
+ }
72
+ interface FigureChrome {
73
+ className?: string;
74
+ /** Prints the key under the figure. `auto` shows only the kinds in use. */
75
+ legend?: LegendMode;
76
+ /** Prints the conclusion cards under the figure. Defaults to true. */
77
+ cards?: boolean;
78
+ /** Prints the title and subtitle over the figure. Defaults to true. */
79
+ heading?: boolean;
80
+ /** Node ids currently lit. Everything else is dimmed. */
81
+ activeIds?: string[];
82
+ /**
83
+ * Called when a reader picks a node.
84
+ *
85
+ * Giving this turns the summary list from a description into a control: the
86
+ * same list a screen reader reads becomes the keyboard's route to selection,
87
+ * and the plates in the picture become the pointer's route to the same thing.
88
+ */
89
+ onSelectNode?: (id: string) => void;
90
+ }
91
+ /**
92
+ * The shell every figure sits in: a heading, the picture, a key, the cards, and
93
+ * the part that makes the picture mean anything to a reader who cannot see it.
94
+ *
95
+ * ## The accessibility decision, stated rather than implied
96
+ *
97
+ * The `<svg>` carries `role="img"` and a label, which makes its whole subtree
98
+ * presentational. That is the honest description of what it is — a picture —
99
+ * and it is what stops a screen reader from walking two hundred `<text>`
100
+ * elements in drawing order, which is neither reading order nor useful.
101
+ *
102
+ * The diagram's CONTENT is then published beside it as an ordinary list: every
103
+ * node with what kind of thing it is, and every relationship as "A → B: over
104
+ * HTTPS". That list is where the meaning lives for anyone not looking at the
105
+ * picture, and it is why this component takes a model rather than markup — a
106
+ * frame handed a finished `<svg>` could not have written it.
107
+ *
108
+ * The list carries the figure's SECOND AXIS as its own structure. A workflow's
109
+ * lanes and a data flow's stages are half of where every box sits, and they are
110
+ * drawn inside the presentational `<svg>` — so a flat list of boxes published
111
+ * one dimension of a two-dimensional picture and called it the content. Nodes
112
+ * are grouped by their band, and the statements that group nothing — a
113
+ * boundary, a phase caption, an activation bar — follow as sentences.
114
+ *
115
+ * The list is visually hidden by default and NOT hidden from assistive
116
+ * technology, which is the opposite of what `aria-hidden` would do and the
117
+ * whole point.
118
+ */
119
+ declare function DiagramFrame({ meta, model, cards, className, legend, showCards, heading, activeIds, onSelectNode, }: {
120
+ meta: DiagramMeta;
121
+ model: FigureModel;
122
+ cards?: DiagramCard[];
123
+ showCards?: boolean;
124
+ } & Omit<FigureChrome, 'cards'>): react.JSX.Element;
125
+ /**
126
+ * The conclusion cards under a figure.
127
+ *
128
+ * Archify keys these by hue — cyan, emerald, rose. Here the key selects a MARK:
129
+ * a filled square, a ring, a bar, a diagonal. Seven cards in a row stay seven
130
+ * distinguishable cards on paper-white, and the same row survives being
131
+ * printed.
132
+ */
133
+ declare function CardGrid({ cards, className }: {
134
+ cards: DiagramCard[];
135
+ className?: string;
136
+ }): react.JSX.Element;
137
+
138
+ export { CardGrid, DiagramFrame, type FigureBand, type FigureChrome, type FigureModel, type FigureNode };
@@ -0,0 +1,131 @@
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
+ const bands = model.bands ?? [];
26
+ const banded = new Set(bands.flatMap((band) => band.ids));
27
+ const loose = bands.length > 0 ? model.nodes.filter((node) => !banded.has(node.id)) : [];
28
+ const row = (node) => /* @__PURE__ */ jsx("li", { children: onSelectNode ? /* @__PURE__ */ jsx("button", { type: "button", onClick: () => onSelectNode(node.id), children: summaryLine(node) }) : summaryLine(node) }, node.id);
29
+ return /* @__PURE__ */ jsxs("figure", { className: cn("m-0 flex flex-col gap-5", className), children: [
30
+ heading && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
31
+ /* @__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 }),
32
+ meta.subtitle && /* @__PURE__ */ jsx("span", { className: "mono-meta text-(--ink-3-aa)", children: meta.subtitle })
33
+ ] }),
34
+ /* @__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(
35
+ "svg",
36
+ {
37
+ viewBox: viewBoxOf(model.extent),
38
+ role: "img",
39
+ "aria-labelledby": `${titleId} ${descId}`,
40
+ className: "block h-auto w-full max-w-full font-sans",
41
+ "data-diagram-artwork": "",
42
+ children: [
43
+ /* @__PURE__ */ jsx("title", { id: titleId, children: meta.title }),
44
+ /* @__PURE__ */ jsx("desc", { id: descId, children: description }),
45
+ /* @__PURE__ */ jsx(DiagramDefs, { uid }),
46
+ model.artwork
47
+ ]
48
+ }
49
+ ) }),
50
+ /* @__PURE__ */ jsxs("div", { className: "sr-only", children: [
51
+ /* @__PURE__ */ jsx("p", { children: description }),
52
+ bands.length > 0 ? /* @__PURE__ */ jsxs("ul", { children: [
53
+ bands.map((band, index) => /* @__PURE__ */ jsxs("li", { children: [
54
+ /* @__PURE__ */ jsx("span", { children: `${band.kind}: ${band.label}` }),
55
+ /* @__PURE__ */ jsx("ul", { children: band.ids.flatMap((id) => {
56
+ const node = byId.get(id);
57
+ return node ? [row(node)] : [];
58
+ }) })
59
+ ] }, `${band.label}-${index}`)),
60
+ loose.length > 0 && /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("ul", { children: loose.map(row) }) })
61
+ ] }) : /* @__PURE__ */ jsx("ul", { children: model.nodes.map(row) }),
62
+ model.edges.length > 0 && /* @__PURE__ */ jsx("ul", { children: model.edges.map((edge, index) => /* @__PURE__ */ jsxs("li", { children: [
63
+ byId.get(edge.from)?.label ?? edge.from,
64
+ " \u2192 ",
65
+ byId.get(edge.to)?.label ?? edge.to,
66
+ edge.label ? `: ${edge.label}` : ""
67
+ ] }, index)) }),
68
+ model.notes && model.notes.length > 0 && /* @__PURE__ */ jsx("ul", { children: model.notes.map((note, index) => /* @__PURE__ */ jsx("li", { children: note }, index)) })
69
+ ] }),
70
+ showLegend && /* @__PURE__ */ jsx(DiagramLegend, { entries: model.legend }),
71
+ showCards && cards && cards.length > 0 && /* @__PURE__ */ jsx(CardGrid, { cards }),
72
+ activeIds && activeIds.length > 0 && /* @__PURE__ */ jsx("span", { className: "sr-only", role: "status", children: `${activeIds.length} highlighted` })
73
+ ] });
74
+ }
75
+ function summaryLine(node) {
76
+ const parts = [node.label];
77
+ if (node.kind) parts.push(`(${node.kind})`);
78
+ if (node.sublabel) parts.push(`\u2014 ${node.sublabel}`);
79
+ if (node.detail) parts.push(`\u2014 ${node.detail}`);
80
+ return parts.join(" ");
81
+ }
82
+ function CardGrid({ cards, className }) {
83
+ return /* @__PURE__ */ jsx(
84
+ "div",
85
+ {
86
+ className: cn(
87
+ "grid gap-3 sm:grid-cols-2 lg:grid-cols-3",
88
+ className
89
+ ),
90
+ children: cards.map((card) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5 border-t border-(--ink) pt-3", children: [
91
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
92
+ /* @__PURE__ */ jsx(CardMark, { shape: card.dot }),
93
+ /* @__PURE__ */ jsx("span", { className: "font-sans text-[13.5px] leading-[1.35] text-(--ink)", children: card.title })
94
+ ] }),
95
+ /* @__PURE__ */ jsx("ul", { className: "m-0 flex list-none flex-col gap-1.5 p-0", children: card.items.map((item, index) => /* @__PURE__ */ jsx(
96
+ "li",
97
+ {
98
+ 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)",
99
+ children: item
100
+ },
101
+ index
102
+ )) })
103
+ ] }, card.title))
104
+ }
105
+ );
106
+ }
107
+ function CardMark({ shape }) {
108
+ const common = "size-2.5 shrink-0";
109
+ switch (shape) {
110
+ case "cyan":
111
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "bg-(--ink)") });
112
+ case "emerald":
113
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rounded-full bg-(--ink)") });
114
+ case "violet":
115
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rounded-full border border-(--ink)") });
116
+ case "amber":
117
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "border border-(--ink)") });
118
+ case "rose":
119
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rotate-45 bg-(--ink)") });
120
+ case "orange":
121
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(common, "rotate-45 border border-(--ink)") });
122
+ case "slate":
123
+ default:
124
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn("h-1 w-2.5 shrink-0 bg-(--ink-3-aa)") });
125
+ }
126
+ }
127
+ export {
128
+ CardGrid,
129
+ DiagramFrame
130
+ };
131
+ //# 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: FigureNode[]\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 * The figure's second axis, as a PARTITION of the nodes above.\n *\n * A workflow's lanes and a data flow's stages are not decoration around the\n * boxes — they are the other half of every box's position, and a summary that\n * lists the boxes alone has published one dimension of a two-dimensional\n * picture. Giving the list this structure says it once, in the place a screen\n * reader already walks, rather than repeating \"in the CI lane\" on every row.\n *\n * A node may appear in at most one band: the list is the keyboard's only\n * route to a selection, and a node in two bands is two controls that do the\n * same thing. Anything left out of every band is published after them.\n */\n bands?: FigureBand[]\n /**\n * What the picture says that is neither a box nor a line.\n *\n * Boundaries, phase captions, segment captions, activation bars: each is a\n * real statement drawn inside an `aria-hidden` `<svg>`, and each is a\n * sentence rather than a row, so each figure writes its own.\n */\n notes?: string[]\n}\n\n/** One drawn box, as the summary publishes it. */\nexport interface FigureNode {\n id: string\n label: string\n sublabel?: string\n kind?: string\n /** A short phrase the picture prints on the box: a step number. */\n detail?: string\n}\n\n/** One band of a figure's second axis: a lane, a stage. */\nexport interface FigureBand {\n /** What KIND of band this is — \"Lane\", \"Stage\" — since the label is a name. */\n kind: string\n label: string\n /** The nodes inside it, in the order the figure draws them. */\n ids: string[]\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 carries the figure's SECOND AXIS as its own structure. A workflow's\n * lanes and a data flow's stages are half of where every box sits, and they are\n * drawn inside the presentational `<svg>` — so a flat list of boxes published\n * one dimension of a two-dimensional picture and called it the content. Nodes\n * are grouped by their band, and the statements that group nothing — a\n * boundary, a phase caption, an activation bar — follow as sentences.\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 // Bands partition the nodes; anything a figure left out of every band is\n // still published, after them. A node dropped from the list entirely would be\n // a node a keyboard cannot reach.\n const bands = model.bands ?? []\n const banded = new Set(bands.flatMap((band) => band.ids))\n const loose = bands.length > 0 ? model.nodes.filter((node) => !banded.has(node.id)) : []\n\n const row = (node: FigureNode) => (\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\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 {bands.length > 0 ? (\n <ul>\n {bands.map((band, index) => (\n <li key={`${band.label}-${index}`}>\n <span>{`${band.kind}: ${band.label}`}</span>\n <ul>\n {band.ids.flatMap((id) => {\n const node = byId.get(id)\n return node ? [row(node)] : []\n })}\n </ul>\n </li>\n ))}\n {loose.length > 0 && (\n <li>\n <ul>{loose.map(row)}</ul>\n </li>\n )}\n </ul>\n ) : (\n <ul>{model.nodes.map(row)}</ul>\n )}\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 {model.notes && model.notes.length > 0 && (\n <ul>\n {model.notes.map((note, index) => (\n <li key={index}>{note}</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: FigureNode): string {\n const parts = [node.label]\n if (node.kind) parts.push(`(${node.kind})`)\n if (node.sublabel) parts.push(`— ${node.sublabel}`)\n if (node.detail) parts.push(`— ${node.detail}`)\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":";AA2JQ,cAgBA,YAhBA;AAzJR,SAAS,aAA6B;AACtC,SAAS,UAAU;AAEnB,SAAS,iBAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AA+GrB,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EACV;AAAA,EACA;AACF,GAKiC;AAC/B,QAAM,MAAM,MAAM,EAAE,QAAQ,MAAM,EAAE;AACpC,QAAM,UAAU,GAAG,GAAG;AACtB,QAAM,SAAS,GAAG,GAAG;AAErB,QAAM,OAAO,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC/D,QAAM,cAAc,GAAG,MAAM,MAAM,MAAM,iBAAiB,MAAM,MAAM,MAAM,mBAC1E,KAAK,YAAY,EACnB,GAAG,KAAK;AAER,QAAM,aAAa,WAAW,YAAY,MAAM,OAAO,SAAS;AAKhE,QAAM,QAAQ,MAAM,SAAS,CAAC;AAC9B,QAAM,SAAS,IAAI,IAAI,MAAM,QAAQ,CAAC,SAAS,KAAK,GAAG,CAAC;AACxD,QAAM,QAAQ,MAAM,SAAS,IAAI,MAAM,MAAM,OAAO,CAAC,SAAS,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC,IAAI,CAAC;AAEvF,QAAM,MAAM,CAAC,SACX,oBAAC,QACE,yBACC,oBAAC,YAAO,MAAK,UAAS,SAAS,MAAM,aAAa,KAAK,EAAE,GACtD,sBAAY,IAAI,GACnB,IAEA,YAAY,IAAI,KANX,KAAK,EAQd;AAGF,SACE,qBAAC,YAAO,WAAW,GAAG,2BAA2B,SAAS,GAKvD;AAAA,eACC,qBAAC,SAAI,WAAU,yBACb;AAAA,0BAAC,QAAG,WAAU,4GACX,eAAK,OACR;AAAA,MACC,KAAK,YAAY,oBAAC,UAAK,WAAU,+BAA+B,eAAK,UAAS;AAAA,OACjF;AAAA,IAGF,oBAAC,SAAI,WAAU,qJACb;AAAA,MAAC;AAAA;AAAA,QACC,SAAS,UAAU,MAAM,MAAM;AAAA,QAC/B,MAAK;AAAA,QACL,mBAAiB,GAAG,OAAO,IAAI,MAAM;AAAA,QACrC,WAAU;AAAA,QACV,wBAAqB;AAAA,QAErB;AAAA,8BAAC,WAAM,IAAI,SAAU,eAAK,OAAM;AAAA,UAChC,oBAAC,UAAK,IAAI,QAAS,uBAAY;AAAA,UAC/B,oBAAC,eAAY,KAAU;AAAA,UACtB,MAAM;AAAA;AAAA;AAAA,IACT,GACF;AAAA,IAGA,qBAAC,SAAI,WAAU,WACb;AAAA,0BAAC,OAAG,uBAAY;AAAA,MACf,MAAM,SAAS,IACd,qBAAC,QACE;AAAA,cAAM,IAAI,CAAC,MAAM,UAChB,qBAAC,QACC;AAAA,8BAAC,UAAM,aAAG,KAAK,IAAI,KAAK,KAAK,KAAK,IAAG;AAAA,UACrC,oBAAC,QACE,eAAK,IAAI,QAAQ,CAAC,OAAO;AACxB,kBAAM,OAAO,KAAK,IAAI,EAAE;AACxB,mBAAO,OAAO,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;AAAA,UAC/B,CAAC,GACH;AAAA,aAPO,GAAG,KAAK,KAAK,IAAI,KAAK,EAQ/B,CACD;AAAA,QACA,MAAM,SAAS,KACd,oBAAC,QACC,8BAAC,QAAI,gBAAM,IAAI,GAAG,GAAE,GACtB;AAAA,SAEJ,IAEA,oBAAC,QAAI,gBAAM,MAAM,IAAI,GAAG,GAAE;AAAA,MAE3B,MAAM,MAAM,SAAS,KACpB,oBAAC,QACE,gBAAM,MAAM,IAAI,CAAC,MAAM,UACtB,qBAAC,QACG;AAAA,aAAK,IAAI,KAAK,IAAI,GAAG,SAAS,KAAK;AAAA,QAAM;AAAA,QAAK,KAAK,IAAI,KAAK,EAAE,GAAG,SAAS,KAAK;AAAA,QAChF,KAAK,QAAQ,KAAK,KAAK,KAAK,KAAK;AAAA,WAF3B,KAGT,CACD,GACH;AAAA,MAED,MAAM,SAAS,MAAM,MAAM,SAAS,KACnC,oBAAC,QACE,gBAAM,MAAM,IAAI,CAAC,MAAM,UACtB,oBAAC,QAAgB,kBAAR,KAAa,CACvB,GACH;AAAA,OAEJ;AAAA,IAEC,cAAc,oBAAC,iBAAc,SAAS,MAAM,QAAQ;AAAA,IAEpD,aAAa,SAAS,MAAM,SAAS,KAAK,oBAAC,YAAS,OAAc;AAAA,IAElE,aAAa,UAAU,SAAS,KAAK,oBAAC,UAAK,WAAU,WAAU,MAAK,UAAU,aAAG,UAAU,MAAM,gBAAe;AAAA,KACnH;AAEJ;AAEA,SAAS,YAAY,MAA0B;AAC7C,QAAM,QAAQ,CAAC,KAAK,KAAK;AACzB,MAAI,KAAK,KAAM,OAAM,KAAK,IAAI,KAAK,IAAI,GAAG;AAC1C,MAAI,KAAK,SAAU,OAAM,KAAK,UAAK,KAAK,QAAQ,EAAE;AAClD,MAAI,KAAK,OAAQ,OAAM,KAAK,UAAK,KAAK,MAAM,EAAE;AAC9C,SAAO,MAAM,KAAK,GAAG;AACvB;AAUO,SAAS,SAAS,EAAE,OAAO,UAAU,GAAiD;AAC3F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,MAEC,gBAAM,IAAI,CAAC,SACV,qBAAC,SAAqB,WAAU,sDAC9B;AAAA,6BAAC,SAAI,WAAU,2BACb;AAAA,8BAAC,YAAS,OAAO,KAAK,KAAK;AAAA,UAC3B,oBAAC,UAAK,WAAU,uDAAuD,eAAK,OAAM;AAAA,WACpF;AAAA,QACA,oBAAC,QAAG,WAAU,2CACX,eAAK,MAAM,IAAI,CAAC,MAAM,UACrB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YAET;AAAA;AAAA,UAHI;AAAA,QAIP,CACD,GACH;AAAA,WAdQ,KAAK,KAef,CACD;AAAA;AAAA,EACH;AAEJ;AAGA,SAAS,SAAS,EAAE,MAAM,GAAkC;AAC1D,QAAM,SAAS;AACf,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,YAAY,GAAG;AAAA,IAChE,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,yBAAyB,GAAG;AAAA,IAC7E,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,oCAAoC,GAAG;AAAA,IACxF,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,uBAAuB,GAAG;AAAA,IAC3E,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,sBAAsB,GAAG;AAAA,IAC1E,KAAK;AACH,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,QAAQ,iCAAiC,GAAG;AAAA,IACrF,KAAK;AAAA,IACL;AACE,aAAO,oBAAC,UAAK,eAAW,MAAC,WAAW,GAAG,oCAAoC,GAAG;AAAA,EAClF;AACF;","names":[]}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The arithmetic every figure shares: boxes, text extents, and the frame that
3
+ * ends up around them.
4
+ *
5
+ * Everything here is a pure function of numbers already in the specification.
6
+ * That is not a stylistic preference — it is what lets these figures render on
7
+ * a server. A layout that measured real text would need a DOM, a layout that
8
+ * relaxed a force graph would need to settle, and neither can produce the same
9
+ * markup twice. Both would hydrate into a different picture than the one that
10
+ * was sent, which for a diagram is worse than not rendering at all.
11
+ */
12
+ /** A rectangle in the figure's user-unit space. */
13
+ interface Box {
14
+ x: number;
15
+ y: number;
16
+ w: number;
17
+ h: number;
18
+ }
19
+ declare const centerOf: (box: Box) => [number, number];
20
+ /** Grows a rectangle by `pad` on every side. */
21
+ declare function inflate(box: Box, pad: number): Box;
22
+ /** The smallest rectangle containing all of them. Returns null for an empty list. */
23
+ declare function union(boxes: Box[]): Box | null;
24
+ /**
25
+ * How wide a run of text is, without measuring it.
26
+ *
27
+ * A real measurement needs a DOM and the loaded face, and this module has
28
+ * neither by design — so this is an estimate, and the honest thing is to say
29
+ * what kind. Latin glyphs in the system's sans average close to 0.52em of
30
+ * advance across ordinary label text; digits and capitals run wider; a CJK
31
+ * ideograph is a full em by definition, as is a fullwidth punctuation mark.
32
+ *
33
+ * The estimate is used for two things and neither needs to be exact: choosing a
34
+ * box wide enough that a label is not clipped, and deciding where a line's
35
+ * label mask sits. Both fail gracefully — a box a few units too wide is
36
+ * invisible, and a mask a few units too wide hides a little more of a line than
37
+ * it had to.
38
+ *
39
+ * It is deliberately NOT used to justify, wrap mid-word, or letter-space
40
+ * anything. Those need the real face.
41
+ */
42
+ declare function textWidth(text: string, fontSize: number): number;
43
+ /**
44
+ * A label broken to fit a width, with a hard cap on how many lines it may take.
45
+ *
46
+ * Breaks on spaces for Latin and between characters for CJK, which has no
47
+ * spaces to break on. A word longer than the whole line is left to overflow
48
+ * rather than hyphenated: an identifier — `TenantMainMiddleware` — split across
49
+ * two lines is harder to read than one that runs slightly wide, and the caller
50
+ * sized the box from `textWidth` anyway.
51
+ *
52
+ * The last line is ellipsised when the text does not fit in `maxLines`, because
53
+ * silently dropping the tail is how a diagram comes to say something it does
54
+ * not mean.
55
+ */
56
+ declare function wrapText(text: string, fontSize: number, maxWidth: number, maxLines?: number): string[];
57
+ /**
58
+ * The type scale inside a figure, in user units.
59
+ *
60
+ * Fixed numbers rather than tokens, because these are SVG geometry: a `<text>`
61
+ * sized in `rem` inside a scaled `viewBox` changes size when the figure is
62
+ * zoomed, which means a diagram at 200% is a different diagram. The figure
63
+ * scales as one picture, so its type scales with it.
64
+ */
65
+ declare const TYPE: {
66
+ /** A node's name. */
67
+ readonly label: 13;
68
+ /** The line under it. */
69
+ readonly sub: 10.5;
70
+ /** A mono chip: a tag, a classification, a step number. */
71
+ readonly chip: 9.5;
72
+ /** A relationship's own wording. */
73
+ readonly edge: 10.5;
74
+ /** A band, lane or stage heading. */
75
+ readonly band: 10.5;
76
+ };
77
+ /** Default box sizes per diagram type, in user units. */
78
+ declare const BOX: {
79
+ readonly node: {
80
+ readonly w: 168;
81
+ readonly h: 62;
82
+ };
83
+ readonly wide: {
84
+ readonly w: 200;
85
+ readonly h: 62;
86
+ };
87
+ readonly participant: {
88
+ readonly w: 128;
89
+ readonly h: 46;
90
+ };
91
+ };
92
+ /**
93
+ * How tall a box has to be to hold what it was given.
94
+ *
95
+ * A declared height is a FLOOR, not a ceiling. When a specification asks for a
96
+ * 64-unit box and then puts two lines of label, a sublabel and a tag chip in
97
+ * it, honouring the 64 prints the tag over the sublabel — which reads as a
98
+ * rendering fault rather than as a box that was asked to hold too much. Growing
99
+ * the box is visible and correct; clipping is invisible and wrong.
100
+ */
101
+ declare function nodeHeight(labelLines: number, hasSub: boolean, hasTag?: boolean, base?: number): number;
102
+ /** `viewBox` as the attribute wants it. */
103
+ declare function viewBoxOf(box: Box): string;
104
+ /**
105
+ * Coordinates rounded to a tenth.
106
+ *
107
+ * SVG happily accepts eighteen decimal places and puts every one of them in the
108
+ * markup, which on a figure with two hundred line segments is a measurable
109
+ * share of the document. A tenth of a user unit is well under a device pixel at
110
+ * any zoom a reader will use.
111
+ */
112
+ declare function round(value: number): number;
113
+
114
+ export { BOX, type Box, TYPE, centerOf, inflate, nodeHeight, round, textWidth, union, viewBoxOf, wrapText };
@@ -0,0 +1,113 @@
1
+ const centerOf = (box) => [box.x + box.w / 2, box.y + box.h / 2];
2
+ function inflate(box, pad) {
3
+ return { x: box.x - pad, y: box.y - pad, w: box.w + pad * 2, h: box.h + pad * 2 };
4
+ }
5
+ function union(boxes) {
6
+ if (boxes.length === 0) return null;
7
+ let minX = Infinity;
8
+ let minY = Infinity;
9
+ let maxX = -Infinity;
10
+ let maxY = -Infinity;
11
+ for (const box of boxes) {
12
+ if (box.x < minX) minX = box.x;
13
+ if (box.y < minY) minY = box.y;
14
+ if (box.x + box.w > maxX) maxX = box.x + box.w;
15
+ if (box.y + box.h > maxY) maxY = box.y + box.h;
16
+ }
17
+ return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };
18
+ }
19
+ function textWidth(text, fontSize) {
20
+ let em = 0;
21
+ for (const character of text) {
22
+ const code = character.codePointAt(0) ?? 0;
23
+ if (code > 11903) {
24
+ em += 1;
25
+ } else if (character === " ") {
26
+ em += 0.26;
27
+ } else if (/[.,:;'`!|iljtIf()[\]{}]/.test(character)) {
28
+ em += 0.31;
29
+ } else if (/[A-Z0-9@#%&WM]/.test(character)) {
30
+ em += 0.62;
31
+ } else {
32
+ em += 0.52;
33
+ }
34
+ }
35
+ return em * fontSize;
36
+ }
37
+ function wrapText(text, fontSize, maxWidth, maxLines = 2) {
38
+ if (textWidth(text, fontSize) <= maxWidth) return [text];
39
+ const lines = [];
40
+ let current = "";
41
+ const tokens = text.match(/[⺀-鿿豈-﫿＀-￯]|[^\s⺀-鿿]+|\s+/g) ?? [text];
42
+ for (const token of tokens) {
43
+ const candidate = current + token;
44
+ if (current !== "" && textWidth(candidate.trimEnd(), fontSize) > maxWidth) {
45
+ lines.push(current.trimEnd());
46
+ current = token.trimStart();
47
+ if (lines.length === maxLines) break;
48
+ } else {
49
+ current = candidate;
50
+ }
51
+ }
52
+ if (lines.length < maxLines && current.trim() !== "") lines.push(current.trimEnd());
53
+ if (lines.length === maxLines) {
54
+ const placed = lines.join("").replace(/\s+/g, "");
55
+ const whole = text.replace(/\s+/g, "");
56
+ if (placed.length < whole.length) {
57
+ const last = lines[maxLines - 1] ?? "";
58
+ lines[maxLines - 1] = `${clampToWidth(last, fontSize, maxWidth - textWidth("\u2026", fontSize))}\u2026`;
59
+ }
60
+ }
61
+ return lines;
62
+ }
63
+ function clampToWidth(text, fontSize, maxWidth) {
64
+ let width = 0;
65
+ let out = "";
66
+ for (const character of text) {
67
+ const next = textWidth(character, fontSize);
68
+ if (width + next > maxWidth) break;
69
+ width += next;
70
+ out += character;
71
+ }
72
+ return out.trimEnd();
73
+ }
74
+ const TYPE = {
75
+ /** A node's name. */
76
+ label: 13,
77
+ /** The line under it. */
78
+ sub: 10.5,
79
+ /** A mono chip: a tag, a classification, a step number. */
80
+ chip: 9.5,
81
+ /** A relationship's own wording. */
82
+ edge: 10.5,
83
+ /** A band, lane or stage heading. */
84
+ band: 10.5
85
+ };
86
+ const BOX = {
87
+ node: { w: 168, h: 62 },
88
+ wide: { w: 200, h: 62 },
89
+ participant: { w: 128, h: 46 }
90
+ };
91
+ function nodeHeight(labelLines, hasSub, hasTag = false, base = BOX.node.h) {
92
+ const content = 20 + labelLines * (TYPE.label * 1.25) + (hasSub ? TYPE.sub * 1.5 : 0) + (hasTag ? 20 : 0);
93
+ return Math.max(base, Math.ceil(content));
94
+ }
95
+ function viewBoxOf(box) {
96
+ return `${round(box.x)} ${round(box.y)} ${round(box.w)} ${round(box.h)}`;
97
+ }
98
+ function round(value) {
99
+ return Math.round(value * 10) / 10;
100
+ }
101
+ export {
102
+ BOX,
103
+ TYPE,
104
+ centerOf,
105
+ inflate,
106
+ nodeHeight,
107
+ round,
108
+ textWidth,
109
+ union,
110
+ viewBoxOf,
111
+ wrapText
112
+ };
113
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/diagrams/lib/geometry.ts"],"sourcesContent":["/**\n * The arithmetic every figure shares: boxes, text extents, and the frame that\n * ends up around them.\n *\n * Everything here is a pure function of numbers already in the specification.\n * That is not a stylistic preference — it is what lets these figures render on\n * a server. A layout that measured real text would need a DOM, a layout that\n * relaxed a force graph would need to settle, and neither can produce the same\n * markup twice. Both would hydrate into a different picture than the one that\n * was sent, which for a diagram is worse than not rendering at all.\n */\n\n/** A rectangle in the figure's user-unit space. */\nexport interface Box {\n x: number\n y: number\n w: number\n h: number\n}\n\nexport const centerOf = (box: Box): [number, number] => [box.x + box.w / 2, box.y + box.h / 2]\n\n/** Grows a rectangle by `pad` on every side. */\nexport function inflate(box: Box, pad: number): Box {\n return { x: box.x - pad, y: box.y - pad, w: box.w + pad * 2, h: box.h + pad * 2 }\n}\n\n/** The smallest rectangle containing all of them. Returns null for an empty list. */\nexport function union(boxes: Box[]): Box | null {\n if (boxes.length === 0) return null\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n for (const box of boxes) {\n if (box.x < minX) minX = box.x\n if (box.y < minY) minY = box.y\n if (box.x + box.w > maxX) maxX = box.x + box.w\n if (box.y + box.h > maxY) maxY = box.y + box.h\n }\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY }\n}\n\n/**\n * How wide a run of text is, without measuring it.\n *\n * A real measurement needs a DOM and the loaded face, and this module has\n * neither by design — so this is an estimate, and the honest thing is to say\n * what kind. Latin glyphs in the system's sans average close to 0.52em of\n * advance across ordinary label text; digits and capitals run wider; a CJK\n * ideograph is a full em by definition, as is a fullwidth punctuation mark.\n *\n * The estimate is used for two things and neither needs to be exact: choosing a\n * box wide enough that a label is not clipped, and deciding where a line's\n * label mask sits. Both fail gracefully — a box a few units too wide is\n * invisible, and a mask a few units too wide hides a little more of a line than\n * it had to.\n *\n * It is deliberately NOT used to justify, wrap mid-word, or letter-space\n * anything. Those need the real face.\n */\nexport function textWidth(text: string, fontSize: number): number {\n let em = 0\n for (const character of text) {\n const code = character.codePointAt(0) ?? 0\n if (code > 0x2e7f) {\n // CJK, kana, hangul, fullwidth forms — one em each.\n em += 1\n } else if (character === ' ') {\n em += 0.26\n } else if (/[.,:;'`!|iljtIf()[\\]{}]/.test(character)) {\n em += 0.31\n } else if (/[A-Z0-9@#%&WM]/.test(character)) {\n em += 0.62\n } else {\n em += 0.52\n }\n }\n return em * fontSize\n}\n\n/**\n * A label broken to fit a width, with a hard cap on how many lines it may take.\n *\n * Breaks on spaces for Latin and between characters for CJK, which has no\n * spaces to break on. A word longer than the whole line is left to overflow\n * rather than hyphenated: an identifier — `TenantMainMiddleware` — split across\n * two lines is harder to read than one that runs slightly wide, and the caller\n * sized the box from `textWidth` anyway.\n *\n * The last line is ellipsised when the text does not fit in `maxLines`, because\n * silently dropping the tail is how a diagram comes to say something it does\n * not mean.\n */\nexport function wrapText(\n text: string,\n fontSize: number,\n maxWidth: number,\n maxLines = 2,\n): string[] {\n if (textWidth(text, fontSize) <= maxWidth) return [text]\n\n const lines: string[] = []\n let current = ''\n\n // Latin words stay whole; a CJK run is a sequence of individual break\n // opportunities, so each ideograph becomes its own token.\n const tokens = text.match(/[⺀-鿿豈-﫿＀-￯]|[^\\s⺀-鿿]+|\\s+/g) ?? [text]\n\n for (const token of tokens) {\n const candidate = current + token\n if (current !== '' && textWidth(candidate.trimEnd(), fontSize) > maxWidth) {\n lines.push(current.trimEnd())\n current = token.trimStart()\n if (lines.length === maxLines) break\n } else {\n current = candidate\n }\n }\n\n if (lines.length < maxLines && current.trim() !== '') lines.push(current.trimEnd())\n\n if (lines.length === maxLines) {\n // Anything still unplaced belongs to the last line, which must therefore\n // admit that it is truncated.\n const placed = lines.join('').replace(/\\s+/g, '')\n const whole = text.replace(/\\s+/g, '')\n if (placed.length < whole.length) {\n const last = lines[maxLines - 1] ?? ''\n lines[maxLines - 1] = `${clampToWidth(last, fontSize, maxWidth - textWidth('…', fontSize))}…`\n }\n }\n\n return lines\n}\n\n/** The longest prefix of `text` that fits, character by character. */\nfunction clampToWidth(text: string, fontSize: number, maxWidth: number): string {\n let width = 0\n let out = ''\n for (const character of text) {\n const next = textWidth(character, fontSize)\n if (width + next > maxWidth) break\n width += next\n out += character\n }\n return out.trimEnd()\n}\n\n/**\n * The type scale inside a figure, in user units.\n *\n * Fixed numbers rather than tokens, because these are SVG geometry: a `<text>`\n * sized in `rem` inside a scaled `viewBox` changes size when the figure is\n * zoomed, which means a diagram at 200% is a different diagram. The figure\n * scales as one picture, so its type scales with it.\n */\nexport const TYPE = {\n /** A node's name. */\n label: 13,\n /** The line under it. */\n sub: 10.5,\n /** A mono chip: a tag, a classification, a step number. */\n chip: 9.5,\n /** A relationship's own wording. */\n edge: 10.5,\n /** A band, lane or stage heading. */\n band: 10.5,\n} as const\n\n/** Default box sizes per diagram type, in user units. */\nexport const BOX = {\n node: { w: 168, h: 62 },\n wide: { w: 200, h: 62 },\n participant: { w: 128, h: 46 },\n} as const\n\n/**\n * How tall a box has to be to hold what it was given.\n *\n * A declared height is a FLOOR, not a ceiling. When a specification asks for a\n * 64-unit box and then puts two lines of label, a sublabel and a tag chip in\n * it, honouring the 64 prints the tag over the sublabel — which reads as a\n * rendering fault rather than as a box that was asked to hold too much. Growing\n * the box is visible and correct; clipping is invisible and wrong.\n */\nexport function nodeHeight(\n labelLines: number,\n hasSub: boolean,\n hasTag = false,\n base: number = BOX.node.h,\n): number {\n const content =\n 20 + labelLines * (TYPE.label * 1.25) + (hasSub ? TYPE.sub * 1.5 : 0) + (hasTag ? 20 : 0)\n return Math.max(base, Math.ceil(content))\n}\n\n/** `viewBox` as the attribute wants it. */\nexport function viewBoxOf(box: Box): string {\n return `${round(box.x)} ${round(box.y)} ${round(box.w)} ${round(box.h)}`\n}\n\n/**\n * Coordinates rounded to a tenth.\n *\n * SVG happily accepts eighteen decimal places and puts every one of them in the\n * markup, which on a figure with two hundred line segments is a measurable\n * share of the document. A tenth of a user unit is well under a device pixel at\n * any zoom a reader will use.\n */\nexport function round(value: number): number {\n return Math.round(value * 10) / 10\n}\n"],"mappings":"AAoBO,MAAM,WAAW,CAAC,QAA+B,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,CAAC;AAGtF,SAAS,QAAQ,KAAU,KAAkB;AAClD,SAAO,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,MAAM,GAAG,GAAG,IAAI,IAAI,MAAM,EAAE;AAClF;AAGO,SAAS,MAAM,OAA0B;AAC9C,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,aAAW,OAAO,OAAO;AACvB,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,IAAI,IAAI,KAAM,QAAO,IAAI,IAAI,IAAI;AAC7C,QAAI,IAAI,IAAI,IAAI,IAAI,KAAM,QAAO,IAAI,IAAI,IAAI;AAAA,EAC/C;AACA,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,MAAM,GAAG,OAAO,KAAK;AAC5D;AAoBO,SAAS,UAAU,MAAc,UAA0B;AAChE,MAAI,KAAK;AACT,aAAW,aAAa,MAAM;AAC5B,UAAM,OAAO,UAAU,YAAY,CAAC,KAAK;AACzC,QAAI,OAAO,OAAQ;AAEjB,YAAM;AAAA,IACR,WAAW,cAAc,KAAK;AAC5B,YAAM;AAAA,IACR,WAAW,0BAA0B,KAAK,SAAS,GAAG;AACpD,YAAM;AAAA,IACR,WAAW,iBAAiB,KAAK,SAAS,GAAG;AAC3C,YAAM;AAAA,IACR,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO,KAAK;AACd;AAeO,SAAS,SACd,MACA,UACA,UACA,WAAW,GACD;AACV,MAAI,UAAU,MAAM,QAAQ,KAAK,SAAU,QAAO,CAAC,IAAI;AAEvD,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AAId,QAAM,SAAS,KAAK,MAAM,4BAA4B,KAAK,CAAC,IAAI;AAEhE,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,UAAU;AAC5B,QAAI,YAAY,MAAM,UAAU,UAAU,QAAQ,GAAG,QAAQ,IAAI,UAAU;AACzE,YAAM,KAAK,QAAQ,QAAQ,CAAC;AAC5B,gBAAU,MAAM,UAAU;AAC1B,UAAI,MAAM,WAAW,SAAU;AAAA,IACjC,OAAO;AACL,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,YAAY,QAAQ,KAAK,MAAM,GAAI,OAAM,KAAK,QAAQ,QAAQ,CAAC;AAElF,MAAI,MAAM,WAAW,UAAU;AAG7B,UAAM,SAAS,MAAM,KAAK,EAAE,EAAE,QAAQ,QAAQ,EAAE;AAChD,UAAM,QAAQ,KAAK,QAAQ,QAAQ,EAAE;AACrC,QAAI,OAAO,SAAS,MAAM,QAAQ;AAChC,YAAM,OAAO,MAAM,WAAW,CAAC,KAAK;AACpC,YAAM,WAAW,CAAC,IAAI,GAAG,aAAa,MAAM,UAAU,WAAW,UAAU,UAAK,QAAQ,CAAC,CAAC;AAAA,IAC5F;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,aAAa,MAAc,UAAkB,UAA0B;AAC9E,MAAI,QAAQ;AACZ,MAAI,MAAM;AACV,aAAW,aAAa,MAAM;AAC5B,UAAM,OAAO,UAAU,WAAW,QAAQ;AAC1C,QAAI,QAAQ,OAAO,SAAU;AAC7B,aAAS;AACT,WAAO;AAAA,EACT;AACA,SAAO,IAAI,QAAQ;AACrB;AAUO,MAAM,OAAO;AAAA;AAAA,EAElB,OAAO;AAAA;AAAA,EAEP,KAAK;AAAA;AAAA,EAEL,MAAM;AAAA;AAAA,EAEN,MAAM;AAAA;AAAA,EAEN,MAAM;AACR;AAGO,MAAM,MAAM;AAAA,EACjB,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG;AAAA,EACtB,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG;AAAA,EACtB,aAAa,EAAE,GAAG,KAAK,GAAG,GAAG;AAC/B;AAWO,SAAS,WACd,YACA,QACA,SAAS,OACT,OAAe,IAAI,KAAK,GAChB;AACR,QAAM,UACJ,KAAK,cAAc,KAAK,QAAQ,SAAS,SAAS,KAAK,MAAM,MAAM,MAAM,SAAS,KAAK;AACzF,SAAO,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,CAAC;AAC1C;AAGO,SAAS,UAAU,KAAkB;AAC1C,SAAO,GAAG,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI,CAAC,CAAC;AACxE;AAUO,SAAS,MAAM,OAAuB;AAC3C,SAAO,KAAK,MAAM,QAAQ,EAAE,IAAI;AAClC;","names":[]}
@@ -0,0 +1,32 @@
1
+ import { NodeKind, LegendMode, LifecycleStateKind, Variant } from '../spec.js';
2
+
3
+ type LegendEntry = {
4
+ key: string;
5
+ label: string;
6
+ sample: React.ReactNode;
7
+ };
8
+ /**
9
+ * Which entries the key shows.
10
+ *
11
+ * `auto` — the default and the truthful one — lists only the kinds the figure
12
+ * actually drew. A key that names seven kinds beside a figure using three is
13
+ * not more informative; it is four claims the picture does not support.
14
+ */
15
+ declare function resolveLegend<T extends string>(used: T[], mode?: LegendMode, all?: T[], overrides?: Record<string, {
16
+ label?: string;
17
+ visible?: boolean;
18
+ }>): T[];
19
+ /** A key entry for each node kind, drawn with the same sigil the figure uses. */
20
+ declare function kindLegend(kinds: NodeKind[], overrides?: Record<string, {
21
+ label?: string;
22
+ }>): LegendEntry[];
23
+ /** A key entry for each relationship variant, drawn as the line itself. */
24
+ declare function variantLegend(variants: (Variant | 'return')[], overrides?: Record<string, {
25
+ label?: string;
26
+ }>): LegendEntry[];
27
+ /** A key entry for each lifecycle state kind, drawn as its plate. */
28
+ declare function stateLegend(kinds: LifecycleStateKind[], overrides?: Record<string, {
29
+ label?: string;
30
+ }>): LegendEntry[];
31
+
32
+ export { type LegendEntry, kindLegend, resolveLegend, stateLegend, variantLegend };