@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,62 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ /**
5
+ * A rung of the type scale, named for what it is FOR rather than for a pixel
6
+ * value. `base` is body copy; `lead` is the standfirst that carries a piece and
7
+ * is the only step here that touches the heading ladder (`--fs-item`, its
8
+ * bottom rung). Nothing above that: a paragraph larger than a record title is a
9
+ * heading that forgot to be one.
10
+ */
11
+ type TextSize = 'xs' | 'sm' | 'base' | 'lead';
12
+ /**
13
+ * A rung of the ink ladder. Three, because the ladder has three.
14
+ *
15
+ * `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper
16
+ * and are not the same token: `--ink-3` is a translucent tint that inherits
17
+ * whatever is under it, so it clears AA on the page ground and quietly fails on
18
+ * a card, a plate, or a code block.
19
+ */
20
+ type TextTone = 'body' | 'strong' | 'muted';
21
+ type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption';
22
+ interface TextProps extends HTMLAttributes<HTMLElement> {
23
+ children?: ReactNode;
24
+ /** Which rung of the type scale. See {@link TextSize}. */
25
+ size?: TextSize;
26
+ /** Which rung of the ink ladder. See {@link TextTone}. */
27
+ tone?: TextTone;
28
+ /**
29
+ * The element, and ONLY the element.
30
+ *
31
+ * Changing it changes what the markup means — a `span` inside a sentence, an
32
+ * `li` inside a list someone else opened — and changes nothing about the
33
+ * look. That separation is the whole point: the alternative is a `<p>` nested
34
+ * inside a `<p>`, which the HTML parser silently splits into two, or a
35
+ * paragraph faked out of a `<div>` because the real element brought a size
36
+ * with it.
37
+ */
38
+ as?: TextElement;
39
+ }
40
+ /**
41
+ * A paragraph, or a run of text that wants the system's voice.
42
+ *
43
+ * The step between `Article` and raw JSX. `Article` styles a whole reading
44
+ * column from element selectors and is the right answer for a post; this is for
45
+ * the single paragraph that is NOT in a column — a card's description, a
46
+ * dialog's explanation, the line under an empty state.
47
+ *
48
+ * The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs
49
+ * are all full-strength ink has spent the top of the ladder on its body copy
50
+ * and has nothing left for the headings, which is the single most common way a
51
+ * monochrome page loses its hierarchy.
52
+ *
53
+ * @example
54
+ * <Text>Twelve releases this quarter, none rolled back.</Text>
55
+ * @example
56
+ * <Text size="lead" tone="strong">A monochrome system for software and writing.</Text>
57
+ * @example
58
+ * <Text as="span" size="sm" tone="muted">Updated just now</Text>
59
+ */
60
+ declare function Text({ children, size, tone, as, className, ...rest }: TextProps): react.JSX.Element;
61
+
62
+ export { Text, type TextElement, type TextProps, type TextSize, type TextTone, Text as default };
@@ -0,0 +1,30 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ const SIZE = {
4
+ xs: "text-xs leading-[1.6]",
5
+ sm: "text-sm leading-[1.65]",
6
+ base: "text-base font-light leading-[1.75]",
7
+ lead: "text-[length:var(--fs-item)] font-light leading-[1.6]"
8
+ };
9
+ const TONE = {
10
+ body: "text-(--ink-2)",
11
+ strong: "text-(--ink)",
12
+ muted: "text-(--ink-3-aa)"
13
+ };
14
+ function Text({
15
+ children,
16
+ size = "base",
17
+ tone = "body",
18
+ as = "p",
19
+ className,
20
+ ...rest
21
+ }) {
22
+ const Comp = as;
23
+ return /* @__PURE__ */ jsx(Comp, { className: cn("m-0", SIZE[size], TONE[tone], className), ...rest, children });
24
+ }
25
+ var Text_default = Text;
26
+ export {
27
+ Text,
28
+ Text_default as default
29
+ };
30
+ //# sourceMappingURL=Text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/Text/Text.tsx"],"sourcesContent":["import type { ElementType, HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * A rung of the type scale, named for what it is FOR rather than for a pixel\n * value. `base` is body copy; `lead` is the standfirst that carries a piece and\n * is the only step here that touches the heading ladder (`--fs-item`, its\n * bottom rung). Nothing above that: a paragraph larger than a record title is a\n * heading that forgot to be one.\n */\nexport type TextSize = 'xs' | 'sm' | 'base' | 'lead'\n\n/**\n * A rung of the ink ladder. Three, because the ladder has three.\n *\n * `muted` is `--ink-3-aa` and never `--ink-3`. The two look identical on paper\n * and are not the same token: `--ink-3` is a translucent tint that inherits\n * whatever is under it, so it clears AA on the page ground and quietly fails on\n * a card, a plate, or a code block.\n */\nexport type TextTone = 'body' | 'strong' | 'muted'\n\nexport type TextElement = 'p' | 'span' | 'div' | 'li' | 'figcaption'\n\n/**\n * Weight travels with the size, deliberately.\n *\n * The system sets long-form copy at 300 — it is what gives a page of prose its\n * air. At 12 and 14px that same weight is a hairline: the strokes thin out\n * below the point where a light face is a choice and turn into a legibility\n * bug. So the two small steps step back up to 400, and a caller never has to\n * know that the trade exists.\n */\nconst SIZE: Record<TextSize, string> = {\n xs: 'text-xs leading-[1.6]',\n sm: 'text-sm leading-[1.65]',\n base: 'text-base font-light leading-[1.75]',\n lead: 'text-[length:var(--fs-item)] font-light leading-[1.6]',\n}\n\nconst TONE: Record<TextTone, string> = {\n body: 'text-(--ink-2)',\n strong: 'text-(--ink)',\n muted: 'text-(--ink-3-aa)',\n}\n\nexport interface TextProps extends HTMLAttributes<HTMLElement> {\n children?: ReactNode\n /** Which rung of the type scale. See {@link TextSize}. */\n size?: TextSize\n /** Which rung of the ink ladder. See {@link TextTone}. */\n tone?: TextTone\n /**\n * The element, and ONLY the element.\n *\n * Changing it changes what the markup means — a `span` inside a sentence, an\n * `li` inside a list someone else opened — and changes nothing about the\n * look. That separation is the whole point: the alternative is a `<p>` nested\n * inside a `<p>`, which the HTML parser silently splits into two, or a\n * paragraph faked out of a `<div>` because the real element brought a size\n * with it.\n */\n as?: TextElement\n}\n\n/**\n * A paragraph, or a run of text that wants the system's voice.\n *\n * The step between `Article` and raw JSX. `Article` styles a whole reading\n * column from element selectors and is the right answer for a post; this is for\n * the single paragraph that is NOT in a column — a card's description, a\n * dialog's explanation, the line under an empty state.\n *\n * The default tone is `body` (`--ink-2`), not `--ink`. A page whose paragraphs\n * are all full-strength ink has spent the top of the ladder on its body copy\n * and has nothing left for the headings, which is the single most common way a\n * monochrome page loses its hierarchy.\n *\n * @example\n * <Text>Twelve releases this quarter, none rolled back.</Text>\n * @example\n * <Text size=\"lead\" tone=\"strong\">A monochrome system for software and writing.</Text>\n * @example\n * <Text as=\"span\" size=\"sm\" tone=\"muted\">Updated just now</Text>\n */\nexport function Text({\n children,\n size = 'base',\n tone = 'body',\n as = 'p',\n className,\n ...rest\n}: TextProps) {\n const Comp = as as ElementType\n\n return (\n <Comp className={cn('m-0', SIZE[size], TONE[tone], className)} {...rest}>\n {children}\n </Comp>\n )\n}\n\nexport default Text\n"],"mappings":"AAgGI;AA/FJ,SAAS,UAAU;AAgCnB,MAAM,OAAiC;AAAA,EACrC,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,MAAM;AACR;AAEA,MAAM,OAAiC;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AACT;AAyCO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,EACP,OAAO;AAAA,EACP,KAAK;AAAA,EACL;AAAA,EACA,GAAG;AACL,GAAc;AACZ,QAAM,OAAO;AAEb,SACE,oBAAC,QAAK,WAAW,GAAG,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,GAAI,GAAG,MAChE,UACH;AAEJ;AAEA,IAAO,eAAQ;","names":[]}
@@ -0,0 +1,59 @@
1
+ import * as react from 'react';
2
+ import { TimeHTMLAttributes } from 'react';
3
+
4
+ /**
5
+ * How the instant reads.
6
+ *
7
+ * `auto` is relative while the gap is small enough to be useful and absolute
8
+ * once it is not — "3 hours ago" answers the question a reader is actually
9
+ * asking about a recent record, and "2 years ago" does not.
10
+ */
11
+ type TimestampFormat = 'auto' | 'relative' | 'absolute';
12
+ interface TimestampProps extends Omit<TimeHTMLAttributes<HTMLTimeElement>, 'dateTime' | 'children'> {
13
+ /** The instant. A `Date`, an ISO string, or epoch milliseconds. */
14
+ value: Date | string | number;
15
+ /** How the instant reads. See {@link TimestampFormat}. */
16
+ format?: TimestampFormat;
17
+ /**
18
+ * How far from now `auto` still prints a relative time, in milliseconds.
19
+ * Seven days by default — past a week the calendar date is the more useful
20
+ * fact, and it is also the one that stops changing.
21
+ */
22
+ relativeWithin?: number;
23
+ /** Adds the clock time to the absolute form. */
24
+ showTime?: boolean;
25
+ }
26
+ /**
27
+ * A date or a time, rendered the one way the system renders them.
28
+ *
29
+ * Every list of records needs this, and `new Date().toLocaleString()` at the
30
+ * call site is precisely how a product ends up with four date formats on one
31
+ * screen.
32
+ *
33
+ * **On hydration.** Both halves of a formatted date are environment-dependent:
34
+ * a relative time depends on when it is read, and even an absolute one depends
35
+ * on the reader's locale and time zone, none of which a static build knows. So
36
+ * the first paint — the one the server produces and the one the client must
37
+ * reproduce exactly — is the ISO calendar date in UTC, sliced straight out of
38
+ * the ISO string with no `Intl` anywhere near it. Both sides compute it from
39
+ * the same characters, so they cannot disagree. The locale-aware and relative
40
+ * forms are applied after mount, in an effect, where there is a reader to be
41
+ * local to. This package statically exports every page, so the alternative is a
42
+ * hydration mismatch on any page with a date on it.
43
+ *
44
+ * The `datetime` attribute is the full ISO instant from the first render
45
+ * onwards and never changes, so a screen reader, a crawler, or anything else
46
+ * parsing the markup gets the exact moment whether or not the effect has run.
47
+ *
48
+ * It formats once per mount. A hundred rows each holding a ticking interval to
49
+ * keep "3 minutes ago" honest is a cost nobody asked for; a list that must tick
50
+ * should re-key or re-render from above.
51
+ *
52
+ * @example
53
+ * <Timestamp value={deploy.finishedAt} />
54
+ * @example
55
+ * <Timestamp value="2026-01-14T09:30:00Z" format="absolute" showTime />
56
+ */
57
+ declare function Timestamp({ value, format, relativeWithin, showTime, className, ...rest }: TimestampProps): react.JSX.Element;
58
+
59
+ export { Timestamp, type TimestampFormat, type TimestampProps, Timestamp as default };
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ const UNITS = [
6
+ ["year", 31556952e3],
7
+ ["month", 2629746e3],
8
+ ["week", 6048e5],
9
+ ["day", 864e5],
10
+ ["hour", 36e5],
11
+ ["minute", 6e4]
12
+ ];
13
+ function relative(deltaMs) {
14
+ const format = new Intl.RelativeTimeFormat(void 0, { numeric: "auto" });
15
+ const gap = Math.abs(deltaMs);
16
+ for (const [unit, size] of UNITS) {
17
+ if (gap >= size) return format.format(Math.trunc(deltaMs / size), unit);
18
+ }
19
+ return format.format(0, "second");
20
+ }
21
+ function absolute(date, showTime) {
22
+ return new Intl.DateTimeFormat(void 0, {
23
+ dateStyle: "medium",
24
+ ...showTime ? { timeStyle: "short" } : {}
25
+ }).format(date);
26
+ }
27
+ function Timestamp({
28
+ value,
29
+ format = "auto",
30
+ relativeWithin = 6048e5,
31
+ showTime = false,
32
+ className,
33
+ ...rest
34
+ }) {
35
+ const date = value instanceof Date ? value : new Date(value);
36
+ const time = date.getTime();
37
+ const valid = !Number.isNaN(time);
38
+ const [local, setLocal] = useState(false);
39
+ useEffect(() => setLocal(true), []);
40
+ if (!valid) {
41
+ return /* @__PURE__ */ jsx("span", { className: cn("text-(--ink-3-aa)", className), ...rest, children: "\u2014" });
42
+ }
43
+ const iso = date.toISOString();
44
+ return /* @__PURE__ */ jsx("time", { dateTime: iso, className: cn("tabular-nums", className), ...rest, children: local ? read(date, format, relativeWithin, showTime) : iso.slice(0, 10) });
45
+ }
46
+ function read(date, format, relativeWithin, showTime) {
47
+ const delta = date.getTime() - Date.now();
48
+ const asRelative = format === "relative" || format === "auto" && Math.abs(delta) < relativeWithin;
49
+ return asRelative ? relative(delta) : absolute(date, showTime);
50
+ }
51
+ var Timestamp_default = Timestamp;
52
+ export {
53
+ Timestamp,
54
+ Timestamp_default as default
55
+ };
56
+ //# sourceMappingURL=Timestamp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/Timestamp/Timestamp.tsx"],"sourcesContent":["'use client'\n\nimport { useEffect, useState } from 'react'\nimport type { TimeHTMLAttributes } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * How the instant reads.\n *\n * `auto` is relative while the gap is small enough to be useful and absolute\n * once it is not — \"3 hours ago\" answers the question a reader is actually\n * asking about a recent record, and \"2 years ago\" does not.\n */\nexport type TimestampFormat = 'auto' | 'relative' | 'absolute'\n\nexport interface TimestampProps\n extends Omit<TimeHTMLAttributes<HTMLTimeElement>, 'dateTime' | 'children'> {\n /** The instant. A `Date`, an ISO string, or epoch milliseconds. */\n value: Date | string | number\n /** How the instant reads. See {@link TimestampFormat}. */\n format?: TimestampFormat\n /**\n * How far from now `auto` still prints a relative time, in milliseconds.\n * Seven days by default — past a week the calendar date is the more useful\n * fact, and it is also the one that stops changing.\n */\n relativeWithin?: number\n /** Adds the clock time to the absolute form. */\n showTime?: boolean\n}\n\n/**\n * The units, largest first, with the milliseconds in one of each.\n *\n * The month and year lengths are the average ones — 30.44 and 365.24 days —\n * because a relative time is a rounded statement about a gap, not a calendar\n * calculation, and \"2 months ago\" must not become \"1 month ago\" because\n * February was short.\n */\nconst UNITS = [\n ['year', 31_556_952_000],\n ['month', 2_629_746_000],\n ['week', 604_800_000],\n ['day', 86_400_000],\n ['hour', 3_600_000],\n ['minute', 60_000],\n] as const\n\n/**\n * The gap in words, in the reader's own language.\n *\n * `Intl.RelativeTimeFormat` rather than a table of English strings: it is in\n * every runtime this package targets, costs nothing to ship, and `numeric:\n * 'auto'` is what turns \"1 day ago\" into \"yesterday\".\n *\n * Truncated, not rounded — ninety seconds is \"1 minute ago\", because a reader\n * who has just watched something happen is not helped by being told it was two\n * minutes. Anything under a minute is \"now\": the seconds are noise, and they\n * are also the only part that would be wrong a moment later.\n */\nfunction relative(deltaMs: number): string {\n const format = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })\n const gap = Math.abs(deltaMs)\n\n for (const [unit, size] of UNITS) {\n if (gap >= size) return format.format(Math.trunc(deltaMs / size), unit)\n }\n return format.format(0, 'second')\n}\n\n/** The calendar date, in the reader's own locale and time zone. */\nfunction absolute(date: Date, showTime: boolean): string {\n return new Intl.DateTimeFormat(undefined, {\n dateStyle: 'medium',\n ...(showTime ? { timeStyle: 'short' as const } : {}),\n }).format(date)\n}\n\n/**\n * A date or a time, rendered the one way the system renders them.\n *\n * Every list of records needs this, and `new Date().toLocaleString()` at the\n * call site is precisely how a product ends up with four date formats on one\n * screen.\n *\n * **On hydration.** Both halves of a formatted date are environment-dependent:\n * a relative time depends on when it is read, and even an absolute one depends\n * on the reader's locale and time zone, none of which a static build knows. So\n * the first paint — the one the server produces and the one the client must\n * reproduce exactly — is the ISO calendar date in UTC, sliced straight out of\n * the ISO string with no `Intl` anywhere near it. Both sides compute it from\n * the same characters, so they cannot disagree. The locale-aware and relative\n * forms are applied after mount, in an effect, where there is a reader to be\n * local to. This package statically exports every page, so the alternative is a\n * hydration mismatch on any page with a date on it.\n *\n * The `datetime` attribute is the full ISO instant from the first render\n * onwards and never changes, so a screen reader, a crawler, or anything else\n * parsing the markup gets the exact moment whether or not the effect has run.\n *\n * It formats once per mount. A hundred rows each holding a ticking interval to\n * keep \"3 minutes ago\" honest is a cost nobody asked for; a list that must tick\n * should re-key or re-render from above.\n *\n * @example\n * <Timestamp value={deploy.finishedAt} />\n * @example\n * <Timestamp value=\"2026-01-14T09:30:00Z\" format=\"absolute\" showTime />\n */\nexport function Timestamp({\n value,\n format = 'auto',\n relativeWithin = 604_800_000,\n showTime = false,\n className,\n ...rest\n}: TimestampProps) {\n const date = value instanceof Date ? value : new Date(value)\n const time = date.getTime()\n const valid = !Number.isNaN(time)\n\n // False through the server render and the hydrating render, true from the\n // first effect on. That is the whole hydration contract in one flag.\n const [local, setLocal] = useState(false)\n useEffect(() => setLocal(true), [])\n\n if (!valid) {\n // Not \"Invalid Date\" — that is the browser's internal string and an\n // engineering artefact in front of a reader. A value nothing can parse is a\n // missing value, and a record UI already has a glyph for one. There is no\n // <time> here either: an element whose datetime cannot be written is not a\n // time.\n return (\n <span className={cn('text-(--ink-3-aa)', className)} {...rest}>\n —\n </span>\n )\n }\n\n const iso = date.toISOString()\n\n return (\n <time dateTime={iso} className={cn('tabular-nums', className)} {...rest}>\n {local ? read(date, format, relativeWithin, showTime) : iso.slice(0, 10)}\n </time>\n )\n}\n\n/**\n * The text a reader who has a clock and a locale gets. Only ever called after\n * mount — everything in here reads `Date.now()` or the ambient locale, which is\n * exactly what the server cannot know.\n */\nfunction read(\n date: Date,\n format: TimestampFormat,\n relativeWithin: number,\n showTime: boolean,\n): string {\n const delta = date.getTime() - Date.now()\n const asRelative = format === 'relative' || (format === 'auto' && Math.abs(delta) < relativeWithin)\n return asRelative ? relative(delta) : absolute(date, showTime)\n}\n\nexport default Timestamp\n"],"mappings":";AAqIM;AAnIN,SAAS,WAAW,gBAAgB;AAEpC,SAAS,UAAU;AAmCnB,MAAM,QAAQ;AAAA,EACZ,CAAC,QAAQ,UAAc;AAAA,EACvB,CAAC,SAAS,SAAa;AAAA,EACvB,CAAC,QAAQ,MAAW;AAAA,EACpB,CAAC,OAAO,KAAU;AAAA,EAClB,CAAC,QAAQ,IAAS;AAAA,EAClB,CAAC,UAAU,GAAM;AACnB;AAcA,SAAS,SAAS,SAAyB;AACzC,QAAM,SAAS,IAAI,KAAK,mBAAmB,QAAW,EAAE,SAAS,OAAO,CAAC;AACzE,QAAM,MAAM,KAAK,IAAI,OAAO;AAE5B,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO;AAChC,QAAI,OAAO,KAAM,QAAO,OAAO,OAAO,KAAK,MAAM,UAAU,IAAI,GAAG,IAAI;AAAA,EACxE;AACA,SAAO,OAAO,OAAO,GAAG,QAAQ;AAClC;AAGA,SAAS,SAAS,MAAY,UAA2B;AACvD,SAAO,IAAI,KAAK,eAAe,QAAW;AAAA,IACxC,WAAW;AAAA,IACX,GAAI,WAAW,EAAE,WAAW,QAAiB,IAAI,CAAC;AAAA,EACpD,CAAC,EAAE,OAAO,IAAI;AAChB;AAiCO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,QAAM,OAAO,iBAAiB,OAAO,QAAQ,IAAI,KAAK,KAAK;AAC3D,QAAM,OAAO,KAAK,QAAQ;AAC1B,QAAM,QAAQ,CAAC,OAAO,MAAM,IAAI;AAIhC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AACxC,YAAU,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AAElC,MAAI,CAAC,OAAO;AAMV,WACE,oBAAC,UAAK,WAAW,GAAG,qBAAqB,SAAS,GAAI,GAAG,MAAM,oBAE/D;AAAA,EAEJ;AAEA,QAAM,MAAM,KAAK,YAAY;AAE7B,SACE,oBAAC,UAAK,UAAU,KAAK,WAAW,GAAG,gBAAgB,SAAS,GAAI,GAAG,MAChE,kBAAQ,KAAK,MAAM,QAAQ,gBAAgB,QAAQ,IAAI,IAAI,MAAM,GAAG,EAAE,GACzE;AAEJ;AAOA,SAAS,KACP,MACA,QACA,gBACA,UACQ;AACR,QAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,IAAI;AACxC,QAAM,aAAa,WAAW,cAAe,WAAW,UAAU,KAAK,IAAI,KAAK,IAAI;AACpF,SAAO,aAAa,SAAS,KAAK,IAAI,SAAS,MAAM,QAAQ;AAC/D;AAEA,IAAO,oBAAQ;","names":[]}
@@ -9,6 +9,14 @@ export { toast } from 'sonner';
9
9
  * reader must act on belongs in the page — a toast is dismissed by time, and
10
10
  * time is not an acknowledgement.
11
11
  *
12
+ * `theme` follows `data-mode`. sonner defaults to `light` and hard-codes the
13
+ * description's colour per theme — `#3f3f3f`, overridden only under
14
+ * `[data-sonner-theme=dark]` — so a Toaster that never passed `theme` put dark
15
+ * grey text on this system's `--paper: #0d0d0d` and every
16
+ * `toast(title, { description })` lost its second half. Pass `theme` yourself
17
+ * and that wins; sonner's own `system` is the one value not to reach for, since
18
+ * it reads the OS rather than the attribute the page is actually painted from.
19
+ *
12
20
  * `richColors` stays off by default: sonner's rich palette is not this system's
13
21
  * status scale, and turning it on reintroduces chroma the White Reset spends
14
22
  * only on state.
@@ -19,6 +27,6 @@ export { toast } from 'sonner';
19
27
  * // anywhere
20
28
  * toast.success('Saved')
21
29
  */
22
- declare function Toaster({ position, closeButton, richColors, style, ...rest }: ToasterProps): react.JSX.Element;
30
+ declare function Toaster({ position, closeButton, richColors, theme, style, ...rest }: ToasterProps): react.JSX.Element;
23
31
 
24
32
  export { Toaster, Toaster as default };
@@ -1,33 +1,56 @@
1
1
  "use client";
2
2
  import { jsx } from "react/jsx-runtime";
3
+ import { useSyncExternalStore } from "react";
3
4
  import { Toaster as SonnerToaster, toast } from "sonner";
4
5
  const TOKEN_STYLE = {
5
6
  "--normal-bg": "var(--paper)",
6
7
  "--normal-text": "var(--ink)",
7
8
  "--normal-border": "var(--rule-2)",
9
+ "--border-radius": "var(--radius)",
10
+ fontFamily: "var(--sans)"
11
+ };
12
+ const RICH_STYLE = {
8
13
  "--success-bg": "var(--paper)",
9
14
  "--success-text": "var(--ok)",
10
15
  "--success-border": "var(--rule-2)",
11
16
  "--error-bg": "var(--paper)",
12
17
  "--error-text": "var(--danger)",
13
- "--error-border": "var(--rule-2)",
14
- "--border-radius": "var(--radius)",
15
- fontFamily: "var(--sans)"
18
+ "--error-border": "var(--rule-2)"
16
19
  };
20
+ function readMode() {
21
+ if (typeof document === "undefined") return "light";
22
+ return document.documentElement.dataset.mode === "dark" ? "dark" : "light";
23
+ }
24
+ function readModeOnServer() {
25
+ return "light";
26
+ }
27
+ function subscribeToMode(onChange) {
28
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return () => {
29
+ };
30
+ const observer = new MutationObserver(onChange);
31
+ observer.observe(document.documentElement, { attributes: true, attributeFilter: ["data-mode"] });
32
+ return () => observer.disconnect();
33
+ }
34
+ function useMode() {
35
+ return useSyncExternalStore(subscribeToMode, readMode, readModeOnServer);
36
+ }
17
37
  function Toaster({
18
38
  position = "bottom-right",
19
39
  closeButton = true,
20
40
  richColors = false,
41
+ theme,
21
42
  style,
22
43
  ...rest
23
44
  }) {
45
+ const mode = useMode();
24
46
  return /* @__PURE__ */ jsx(
25
47
  SonnerToaster,
26
48
  {
27
49
  position,
28
50
  closeButton,
29
51
  richColors,
30
- style: { ...TOKEN_STYLE, ...style },
52
+ theme: theme ?? mode,
53
+ style: { ...TOKEN_STYLE, ...richColors ? RICH_STYLE : null, ...style },
31
54
  ...rest
32
55
  }
33
56
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["'use client'\n\nimport { Toaster as SonnerToaster, toast } from 'sonner'\nimport type { ToasterProps } from 'sonner'\nimport type { CSSProperties } from 'react'\n\n/**\n * Sonner's own custom properties, pointed at this system's tokens.\n *\n * Set as inline style on the Toaster rather than in a stylesheet: sonner\n * renders its list into a portal at the end of `<body>`, outside whatever\n * element a consumer's CSS is scoped to, and the inline style is the one place\n * guaranteed to reach it.\n *\n * Cast because this `@types/react` `CSSProperties` has no custom-property index\n * signature.\n */\nconst TOKEN_STYLE = {\n '--normal-bg': 'var(--paper)',\n '--normal-text': 'var(--ink)',\n '--normal-border': 'var(--rule-2)',\n '--success-bg': 'var(--paper)',\n '--success-text': 'var(--ok)',\n '--success-border': 'var(--rule-2)',\n '--error-bg': 'var(--paper)',\n '--error-text': 'var(--danger)',\n '--error-border': 'var(--rule-2)',\n '--border-radius': 'var(--radius)',\n fontFamily: 'var(--sans)',\n} as CSSProperties\n\n/**\n * Transient confirmations, mounted once near the app root.\n *\n * A toast is for something that succeeded and needs no response. Anything the\n * reader must act on belongs in the page — a toast is dismissed by time, and\n * time is not an acknowledgement.\n *\n * `richColors` stays off by default: sonner's rich palette is not this system's\n * status scale, and turning it on reintroduces chroma the White Reset spends\n * only on state.\n *\n * @example\n * // app root\n * <Toaster />\n * // anywhere\n * toast.success('Saved')\n */\nexport function Toaster({\n position = 'bottom-right',\n closeButton = true,\n richColors = false,\n style,\n ...rest\n}: ToasterProps) {\n return (\n <SonnerToaster\n position={position}\n closeButton={closeButton}\n richColors={richColors}\n style={{ ...TOKEN_STYLE, ...style }}\n {...rest}\n />\n )\n}\n\nexport { toast }\nexport default Toaster\n"],"mappings":";AAwDI;AAtDJ,SAAS,WAAW,eAAe,aAAa;AAehD,MAAM,cAAc;AAAA,EAClB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,YAAY;AACd;AAmBO,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAAiB;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,GAAG,aAAa,GAAG,MAAM;AAAA,MACjC,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,IAAO,gBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/Toast/Toast.tsx"],"sourcesContent":["'use client'\n\nimport { useSyncExternalStore } from 'react'\nimport { Toaster as SonnerToaster, toast } from 'sonner'\nimport type { ToasterProps } from 'sonner'\nimport type { CSSProperties } from 'react'\n\n/**\n * Sonner's own custom properties, pointed at this system's tokens.\n *\n * Set as inline style on the Toaster rather than in a stylesheet: sonner\n * renders its list into a portal at the end of `<body>`, outside whatever\n * element a consumer's CSS is scoped to, and the inline style is the one place\n * guaranteed to reach it.\n *\n * These four are the ones sonner reads unconditionally. The status pairs are\n * separate, below, because sonner does not.\n *\n * Cast because this `@types/react` `CSSProperties` has no custom-property index\n * signature.\n */\nconst TOKEN_STYLE = {\n '--normal-bg': 'var(--paper)',\n '--normal-text': 'var(--ink)',\n '--normal-border': 'var(--rule-2)',\n '--border-radius': 'var(--radius)',\n fontFamily: 'var(--sans)',\n} as CSSProperties\n\n/**\n * The status pairs, emitted only when something will read them.\n *\n * sonner scopes `--success-*` and `--error-*` to `[data-rich-colors=true]`, so\n * at this package's default they are four declarations that do nothing while\n * sitting in the element's style attribute looking like the source of a success\n * toast's colour. Conditional rather than deleted: a consumer who turns\n * `richColors` on should still get this system's status scale rather than\n * sonner's.\n */\nconst RICH_STYLE = {\n '--success-bg': 'var(--paper)',\n '--success-text': 'var(--ok)',\n '--success-border': 'var(--rule-2)',\n '--error-bg': 'var(--paper)',\n '--error-text': 'var(--danger)',\n '--error-border': 'var(--rule-2)',\n} as CSSProperties\n\n/**\n * The mode the APP is in, which is not the mode the operating system is in.\n *\n * `data-mode` on `<html>` is this system's switch: a pre-paint script resolves\n * it from storage, falling back to `prefers-color-scheme`, and a reader can\n * override the OS from the page. sonner's own `theme=\"system\"` reads\n * `prefers-color-scheme` directly, so a reader on a dark machine reading a\n * light page would get a dark toast over a white page — the same defect as the\n * one this exists to fix, pointing the other way.\n */\ntype Mode = 'light' | 'dark'\n\nfunction readMode(): Mode {\n if (typeof document === 'undefined') return 'light'\n return document.documentElement.dataset.mode === 'dark' ? 'dark' : 'light'\n}\n\n/** Light on a server, which is what the pre-paint script also assumes. */\nfunction readModeOnServer(): Mode {\n return 'light'\n}\n\nfunction subscribeToMode(onChange: () => void): () => void {\n if (typeof document === 'undefined' || typeof MutationObserver === 'undefined') return () => {}\n const observer = new MutationObserver(onChange)\n observer.observe(document.documentElement, { attributes: true, attributeFilter: ['data-mode'] })\n return () => observer.disconnect()\n}\n\n/**\n * Observed rather than read once: the Toaster is mounted at the app root and\n * outlives every theme switch a reader makes under it.\n */\nfunction useMode(): Mode {\n return useSyncExternalStore(subscribeToMode, readMode, readModeOnServer)\n}\n\n/**\n * Transient confirmations, mounted once near the app root.\n *\n * A toast is for something that succeeded and needs no response. Anything the\n * reader must act on belongs in the page — a toast is dismissed by time, and\n * time is not an acknowledgement.\n *\n * `theme` follows `data-mode`. sonner defaults to `light` and hard-codes the\n * description's colour per theme — `#3f3f3f`, overridden only under\n * `[data-sonner-theme=dark]` — so a Toaster that never passed `theme` put dark\n * grey text on this system's `--paper: #0d0d0d` and every\n * `toast(title, { description })` lost its second half. Pass `theme` yourself\n * and that wins; sonner's own `system` is the one value not to reach for, since\n * it reads the OS rather than the attribute the page is actually painted from.\n *\n * `richColors` stays off by default: sonner's rich palette is not this system's\n * status scale, and turning it on reintroduces chroma the White Reset spends\n * only on state.\n *\n * @example\n * // app root\n * <Toaster />\n * // anywhere\n * toast.success('Saved')\n */\nexport function Toaster({\n position = 'bottom-right',\n closeButton = true,\n richColors = false,\n theme,\n style,\n ...rest\n}: ToasterProps) {\n const mode = useMode()\n\n return (\n <SonnerToaster\n position={position}\n closeButton={closeButton}\n richColors={richColors}\n theme={theme ?? mode}\n style={{ ...TOKEN_STYLE, ...(richColors ? RICH_STYLE : null), ...style }}\n {...rest}\n />\n )\n}\n\nexport { toast }\nexport default Toaster\n"],"mappings":";AAyHI;AAvHJ,SAAS,4BAA4B;AACrC,SAAS,WAAW,eAAe,aAAa;AAkBhD,MAAM,cAAc;AAAA,EAClB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,YAAY;AACd;AAYA,MAAM,aAAa;AAAA,EACjB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,oBAAoB;AAAA,EACpB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,kBAAkB;AACpB;AAcA,SAAS,WAAiB;AACxB,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO,SAAS,gBAAgB,QAAQ,SAAS,SAAS,SAAS;AACrE;AAGA,SAAS,mBAAyB;AAChC,SAAO;AACT;AAEA,SAAS,gBAAgB,UAAkC;AACzD,MAAI,OAAO,aAAa,eAAe,OAAO,qBAAqB,YAAa,QAAO,MAAM;AAAA,EAAC;AAC9F,QAAM,WAAW,IAAI,iBAAiB,QAAQ;AAC9C,WAAS,QAAQ,SAAS,iBAAiB,EAAE,YAAY,MAAM,iBAAiB,CAAC,WAAW,EAAE,CAAC;AAC/F,SAAO,MAAM,SAAS,WAAW;AACnC;AAMA,SAAS,UAAgB;AACvB,SAAO,qBAAqB,iBAAiB,UAAU,gBAAgB;AACzE;AA2BO,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,aAAa;AAAA,EACb;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiB;AACf,QAAM,OAAO,QAAQ;AAErB,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,OAAO,EAAE,GAAG,aAAa,GAAI,aAAa,aAAa,MAAO,GAAG,MAAM;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAGA,IAAO,gBAAQ;","names":[]}
@@ -21,13 +21,18 @@ type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>;
21
21
  * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.
22
22
  * A toggle group changes a value.
23
23
  *
24
+ * Inside a `Field` the strip takes its name from that label, by pointing back at
25
+ * it — the root is a div, and `<label for>` does not bind to one, so the words
26
+ * above it do not click through. Standing alone it still needs its own
27
+ * `aria-label`.
28
+ *
24
29
  * @example
25
30
  * <ToggleGroup type="single" defaultValue="grid" aria-label="Layout">
26
31
  * <ToggleGroupItem value="grid">Grid</ToggleGroupItem>
27
32
  * <ToggleGroupItem value="list">List</ToggleGroupItem>
28
33
  * </ToggleGroup>
29
34
  */
30
- declare function ToggleGroup({ className, children, ...props }: ToggleGroupProps): react.JSX.Element;
35
+ declare function ToggleGroup({ className, children, 'aria-required': ariaRequired, ...props }: ToggleGroupProps): react.JSX.Element;
31
36
  type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>;
32
37
  /**
33
38
  * One segment.
@@ -3,9 +3,17 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
4
4
  import { createContext, useContext, useState } from "react";
5
5
  import { cn } from "../../lib/cn.js";
6
+ import { useFieldControl } from "../Field/field-control.js";
6
7
  import { useSelectionIndicator } from "../../lib/useSelectionIndicator.js";
7
8
  const SingleValueContext = createContext(null);
8
- function ToggleGroup({ className, children, ...props }) {
9
+ function ToggleGroup({
10
+ className,
11
+ children,
12
+ "aria-required": ariaRequired,
13
+ ...props
14
+ }) {
15
+ const field = useFieldControl();
16
+ const named = props["aria-label"] != null || props["aria-labelledby"] != null;
9
17
  const single = props.type === "single";
10
18
  const [uncontrolled, setUncontrolled] = useState(
11
19
  (single ? props.defaultValue : void 0) ?? ""
@@ -16,6 +24,8 @@ function ToggleGroup({ className, children, ...props }) {
16
24
  ToggleGroupPrimitive.Root,
17
25
  {
18
26
  ref,
27
+ "aria-labelledby": named ? void 0 : field?.labelId,
28
+ "aria-required": props.type === "single" ? ariaRequired : void 0,
19
29
  className: cn(
20
30
  // `w-fit` as well as `inline-flex`: a flex or grid parent stretches its
21
31
  // children to the track by default, and `inline-flex` does not opt out
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["'use client'\n\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useSelectionIndicator } from '../../lib/useSelectionIndicator'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>\n\n/** Lets an item know whether the group tracks one value or several. */\nconst SingleValueContext = createContext<string | null>(null)\n\n/**\n * A segmented control: several options, one strip.\n *\n * `type=\"single\"` is a choice — Radix gives it radio semantics, and it is the\n * right shape for a view switcher or a density setting. `type=\"multiple\"` is a\n * set of independent toggles, which is a different thing announced differently;\n * choosing the wrong one is how a \"filter by tag\" control ends up telling a\n * screen reader that picking one tag unpicks the others.\n *\n * The two look different on purpose. A single-value strip moves ONE filled pill\n * between its options, so the eye follows a thing travelling; a multiple-value\n * strip fills each pressed option separately, because there is no single\n * selection to travel. Two people looking at a screenshot should be able to\n * tell which kind they are looking at, and before this they could not.\n *\n * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.\n * A toggle group changes a value.\n *\n * @example\n * <ToggleGroup type=\"single\" defaultValue=\"grid\" aria-label=\"Layout\">\n * <ToggleGroupItem value=\"grid\">Grid</ToggleGroupItem>\n * <ToggleGroupItem value=\"list\">List</ToggleGroupItem>\n * </ToggleGroup>\n */\nexport function ToggleGroup({ className, children, ...props }: ToggleGroupProps) {\n // Tracked here rather than left to Radix alone, because the sliding pill has\n // to know which item to measure — and an uncontrolled group never tells\n // anyone what it picked.\n const single = props.type === 'single'\n const [uncontrolled, setUncontrolled] = useState<string>(\n (single ? (props.defaultValue as string | undefined) : undefined) ?? '',\n )\n const value = single ? ((props.value as string | undefined) ?? uncontrolled) : null\n const [ref, indicator] = useSelectionIndicator<HTMLDivElement>(value)\n\n const root = (\n <ToggleGroupPrimitive.Root\n ref={ref}\n className={cn(\n // `w-fit` as well as `inline-flex`: a flex or grid parent stretches its\n // children to the track by default, and `inline-flex` does not opt out\n // of that. Without it the strip grew to whatever the widest sibling was\n // — a label above it — and left dead space after the last segment.\n 'relative inline-flex w-fit items-center gap-1 rounded-(--radius-pill) border border-(--rule-2) p-1',\n className,\n )}\n {...props}\n onValueChange={(next: never) => {\n if (single) setUncontrolled((next as string) ?? '')\n ;(props.onValueChange as ((v: never) => void) | undefined)?.(next)\n }}\n >\n {single && indicator.ready && (\n <span\n aria-hidden\n data-m22-animated\n className=\"absolute rounded-(--radius-pill) bg-(--accent) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) motion-reduce:transition-none\"\n style={{\n transform: `translate(${indicator.offset}px, ${indicator.top}px)`,\n width: indicator.width,\n height: indicator.height,\n insetInlineStart: 0,\n top: 0,\n }}\n />\n )}\n {children}\n </ToggleGroupPrimitive.Root>\n )\n\n return single ? (\n <SingleValueContext.Provider value={value}>{root}</SingleValueContext.Provider>\n ) : (\n root\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>\n\n/**\n * One segment.\n *\n * In a single-value group the item draws no background of its own — the\n * travelling pill behind it does — so it only changes ink. In a multiple-value\n * group it fills, because there is nothing travelling.\n */\nexport function ToggleGroupItem({ className, value, ...props }: ToggleGroupItemProps) {\n const selected = useContext(SingleValueContext)\n const isSingle = selected !== null\n const active = isSingle && selected === value\n\n return (\n <ToggleGroupPrimitive.Item\n value={value}\n data-indicator-active={active ? 'true' : undefined}\n className={cn(\n 'relative z-1 inline-flex min-h-(--control-h-sm) items-center justify-center gap-2 rounded-(--radius-pill) px-3.5 text-sm transition-colors duration-(--duration-fast) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n isSingle\n ? active\n ? 'text-(--accent-foreground)'\n : 'text-(--ink-3-aa) hover:text-(--ink)'\n : 'text-(--ink-3-aa) hover:text-(--ink) data-[state=on]:bg-(--accent) data-[state=on]:text-(--accent-foreground)',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport default ToggleGroup\n"],"mappings":";AAgDI,SAiBI,KAjBJ;AA9CJ,YAAY,0BAA0B;AACtC,SAAS,eAAe,YAAY,gBAAqC;AACzE,SAAS,UAAU;AACnB,SAAS,6BAA6B;AAKtC,MAAM,qBAAqB,cAA6B,IAAI;AA0BrD,SAAS,YAAY,EAAE,WAAW,UAAU,GAAG,MAAM,GAAqB;AAI/E,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,CAAC,cAAc,eAAe,IAAI;AAAA,KACrC,SAAU,MAAM,eAAsC,WAAc;AAAA,EACvE;AACA,QAAM,QAAQ,SAAW,MAAM,SAAgC,eAAgB;AAC/E,QAAM,CAAC,KAAK,SAAS,IAAI,sBAAsC,KAAK;AAEpE,QAAM,OACJ;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MACJ,eAAe,CAAC,SAAgB;AAC9B,YAAI,OAAQ,iBAAiB,QAAmB,EAAE;AACjD,QAAC,MAAM,gBAAqD,IAAI;AAAA,MACnE;AAAA,MAEC;AAAA,kBAAU,UAAU,SACnB;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,qBAAiB;AAAA,YACjB,WAAU;AAAA,YACV,OAAO;AAAA,cACL,WAAW,aAAa,UAAU,MAAM,OAAO,UAAU,GAAG;AAAA,cAC5D,OAAO,UAAU;AAAA,cACjB,QAAQ,UAAU;AAAA,cAClB,kBAAkB;AAAA,cAClB,KAAK;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QAED;AAAA;AAAA;AAAA,EACH;AAGF,SAAO,SACL,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,gBAAK,IAEjD;AAEJ;AAWO,SAAS,gBAAgB,EAAE,WAAW,OAAO,GAAG,MAAM,GAAyB;AACpF,QAAM,WAAW,WAAW,kBAAkB;AAC9C,QAAM,WAAW,aAAa;AAC9B,QAAM,SAAS,YAAY,aAAa;AAExC,SACE;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,yBAAuB,SAAS,SAAS;AAAA,MACzC,WAAW;AAAA,QACT;AAAA,QACA,WACI,SACE,+BACA,yCACF;AAAA,QACJ;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,sBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ToggleGroup/ToggleGroup.tsx"],"sourcesContent":["'use client'\n\nimport * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group'\nimport { createContext, useContext, useState, type ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useFieldControl } from '../Field/field-control'\nimport { useSelectionIndicator } from '../../lib/useSelectionIndicator'\n\nexport type ToggleGroupProps = ComponentProps<typeof ToggleGroupPrimitive.Root>\n\n/** Lets an item know whether the group tracks one value or several. */\nconst SingleValueContext = createContext<string | null>(null)\n\n/**\n * A segmented control: several options, one strip.\n *\n * `type=\"single\"` is a choice — Radix gives it radio semantics, and it is the\n * right shape for a view switcher or a density setting. `type=\"multiple\"` is a\n * set of independent toggles, which is a different thing announced differently;\n * choosing the wrong one is how a \"filter by tag\" control ends up telling a\n * screen reader that picking one tag unpicks the others.\n *\n * The two look different on purpose. A single-value strip moves ONE filled pill\n * between its options, so the eye follows a thing travelling; a multiple-value\n * strip fills each pressed option separately, because there is no single\n * selection to travel. Two people looking at a screenshot should be able to\n * tell which kind they are looking at, and before this they could not.\n *\n * Distinct from `Tabs`, which switches PANELS and owns a tabpanel relationship.\n * A toggle group changes a value.\n *\n * Inside a `Field` the strip takes its name from that label, by pointing back at\n * it — the root is a div, and `<label for>` does not bind to one, so the words\n * above it do not click through. Standing alone it still needs its own\n * `aria-label`.\n *\n * @example\n * <ToggleGroup type=\"single\" defaultValue=\"grid\" aria-label=\"Layout\">\n * <ToggleGroupItem value=\"grid\">Grid</ToggleGroupItem>\n * <ToggleGroupItem value=\"list\">List</ToggleGroupItem>\n * </ToggleGroup>\n */\nexport function ToggleGroup({\n className,\n children,\n 'aria-required': ariaRequired,\n ...props\n}: ToggleGroupProps) {\n const field = useFieldControl()\n const named = props['aria-label'] != null || props['aria-labelledby'] != null\n\n // Tracked here rather than left to Radix alone, because the sliding pill has\n // to know which item to measure — and an uncontrolled group never tells\n // anyone what it picked.\n const single = props.type === 'single'\n const [uncontrolled, setUncontrolled] = useState<string>(\n (single ? (props.defaultValue as string | undefined) : undefined) ?? '',\n )\n const value = single ? ((props.value as string | undefined) ?? uncontrolled) : null\n const [ref, indicator] = useSelectionIndicator<HTMLDivElement>(value)\n\n const root = (\n <ToggleGroupPrimitive.Root\n ref={ref}\n aria-labelledby={named ? undefined : field?.labelId}\n // Only on the single-value strip. Radix gives that one role=\"radiogroup\",\n // which takes aria-required; a multiple-value strip is a role=\"toolbar\",\n // where the attribute is not allowed at all — so a Field's `required`\n // reaches one shape of this control and not the other.\n aria-required={props.type === 'single' ? ariaRequired : undefined}\n className={cn(\n // `w-fit` as well as `inline-flex`: a flex or grid parent stretches its\n // children to the track by default, and `inline-flex` does not opt out\n // of that. Without it the strip grew to whatever the widest sibling was\n // — a label above it — and left dead space after the last segment.\n 'relative inline-flex w-fit items-center gap-1 rounded-(--radius-pill) border border-(--rule-2) p-1',\n className,\n )}\n {...props}\n onValueChange={(next: never) => {\n if (single) setUncontrolled((next as string) ?? '')\n ;(props.onValueChange as ((v: never) => void) | undefined)?.(next)\n }}\n >\n {single && indicator.ready && (\n <span\n aria-hidden\n data-m22-animated\n className=\"absolute rounded-(--radius-pill) bg-(--accent) transition-[transform,width] duration-(--duration-base) ease-(--ease-out-expo) motion-reduce:transition-none\"\n style={{\n transform: `translate(${indicator.offset}px, ${indicator.top}px)`,\n width: indicator.width,\n height: indicator.height,\n insetInlineStart: 0,\n top: 0,\n }}\n />\n )}\n {children}\n </ToggleGroupPrimitive.Root>\n )\n\n return single ? (\n <SingleValueContext.Provider value={value}>{root}</SingleValueContext.Provider>\n ) : (\n root\n )\n}\n\nexport type ToggleGroupItemProps = ComponentProps<typeof ToggleGroupPrimitive.Item>\n\n/**\n * One segment.\n *\n * In a single-value group the item draws no background of its own — the\n * travelling pill behind it does — so it only changes ink. In a multiple-value\n * group it fills, because there is nothing travelling.\n */\nexport function ToggleGroupItem({ className, value, ...props }: ToggleGroupItemProps) {\n const selected = useContext(SingleValueContext)\n const isSingle = selected !== null\n const active = isSingle && selected === value\n\n return (\n <ToggleGroupPrimitive.Item\n value={value}\n data-indicator-active={active ? 'true' : undefined}\n className={cn(\n 'relative z-1 inline-flex min-h-(--control-h-sm) items-center justify-center gap-2 rounded-(--radius-pill) px-3.5 text-sm transition-colors duration-(--duration-fast) disabled:opacity-(--disabled-opacity) disabled:pointer-events-none',\n isSingle\n ? active\n ? 'text-(--accent-foreground)'\n : 'text-(--ink-3-aa) hover:text-(--ink)'\n : 'text-(--ink-3-aa) hover:text-(--ink) data-[state=on]:bg-(--accent) data-[state=on]:text-(--accent-foreground)',\n className,\n )}\n {...props}\n />\n )\n}\n\nexport default ToggleGroup\n"],"mappings":";AA8DI,SAuBI,KAvBJ;AA5DJ,YAAY,0BAA0B;AACtC,SAAS,eAAe,YAAY,gBAAqC;AACzE,SAAS,UAAU;AACnB,SAAS,uBAAuB;AAChC,SAAS,6BAA6B;AAKtC,MAAM,qBAAqB,cAA6B,IAAI;AA+BrD,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,iBAAiB;AAAA,EACjB,GAAG;AACL,GAAqB;AACnB,QAAM,QAAQ,gBAAgB;AAC9B,QAAM,QAAQ,MAAM,YAAY,KAAK,QAAQ,MAAM,iBAAiB,KAAK;AAKzE,QAAM,SAAS,MAAM,SAAS;AAC9B,QAAM,CAAC,cAAc,eAAe,IAAI;AAAA,KACrC,SAAU,MAAM,eAAsC,WAAc;AAAA,EACvE;AACA,QAAM,QAAQ,SAAW,MAAM,SAAgC,eAAgB;AAC/E,QAAM,CAAC,KAAK,SAAS,IAAI,sBAAsC,KAAK;AAEpE,QAAM,OACJ;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,mBAAiB,QAAQ,SAAY,OAAO;AAAA,MAK5C,iBAAe,MAAM,SAAS,WAAW,eAAe;AAAA,MACxD,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,QAKT;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MACJ,eAAe,CAAC,SAAgB;AAC9B,YAAI,OAAQ,iBAAiB,QAAmB,EAAE;AACjD,QAAC,MAAM,gBAAqD,IAAI;AAAA,MACnE;AAAA,MAEC;AAAA,kBAAU,UAAU,SACnB;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,qBAAiB;AAAA,YACjB,WAAU;AAAA,YACV,OAAO;AAAA,cACL,WAAW,aAAa,UAAU,MAAM,OAAO,UAAU,GAAG;AAAA,cAC5D,OAAO,UAAU;AAAA,cACjB,QAAQ,UAAU;AAAA,cAClB,kBAAkB;AAAA,cAClB,KAAK;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QAED;AAAA;AAAA;AAAA,EACH;AAGF,SAAO,SACL,oBAAC,mBAAmB,UAAnB,EAA4B,OAAe,gBAAK,IAEjD;AAEJ;AAWO,SAAS,gBAAgB,EAAE,WAAW,OAAO,GAAG,MAAM,GAAyB;AACpF,QAAM,WAAW,WAAW,kBAAkB;AAC9C,QAAM,WAAW,aAAa;AAC9B,QAAM,SAAS,YAAY,aAAa;AAExC,SACE;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC;AAAA,MACA,yBAAuB,SAAS,SAAS;AAAA,MACzC,WAAW;AAAA,QACT;AAAA,QACA,WACI,SACE,+BACA,yCACF;AAAA,QACJ;AAAA,MACF;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,sBAAQ;","names":[]}
@@ -0,0 +1,55 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ /**
5
+ * Which edge the bar sticks to, or neither.
6
+ *
7
+ * `bottom` is the form footer — the actions stay in reach while a long form
8
+ * scrolls under them. `top` is the filter bar over a list. `static` is the same
9
+ * bar with no stickiness, for a short page or a bar inside a dialog that is
10
+ * already the height of its content.
11
+ */
12
+ type ToolbarPosition = 'bottom' | 'top' | 'static';
13
+ type ToolbarAlign = 'start' | 'center' | 'end' | 'between';
14
+ interface ToolbarProps extends HTMLAttributes<HTMLDivElement> {
15
+ /**
16
+ * Names the bar for a screen reader — "Form actions", "List filters".
17
+ * Required, because a group with no name is announced as "group" and a page
18
+ * with two of them is a page with two identical announcements.
19
+ */
20
+ label: string;
21
+ /** Which edge the bar sticks to. See {@link ToolbarPosition}. */
22
+ position?: ToolbarPosition;
23
+ /** Where the contents sit along the inline axis. */
24
+ align?: ToolbarAlign;
25
+ children: ReactNode;
26
+ }
27
+ /**
28
+ * The bar of actions at the edge of a working surface.
29
+ *
30
+ * Two page templates built the same thing independently — a sticky strip on
31
+ * `--paper` with a rule along the edge it sticks to — which is the signal that
32
+ * it belongs here rather than in each of them.
33
+ *
34
+ * The ground is opaque `--paper` and not a blur. Content scrolls UNDER this
35
+ * bar, so anything translucent puts the last row of a table behind the submit
36
+ * button and makes both unreadable; `FloatingIconButton` blurs because it
37
+ * floats over a gap, which is a different problem.
38
+ *
39
+ * It is not `role="toolbar"`. That role's contract is a single tab stop with
40
+ * arrow keys moving between the controls inside it, and this implements no such
41
+ * thing — declaring the role without the behaviour tells a screen-reader user
42
+ * to press arrow keys that do nothing. It is a named `group`, so the controls
43
+ * keep their own places in the tab order and the bar is still announced.
44
+ *
45
+ * @example
46
+ * <Toolbar label="Form actions">
47
+ * <Button variant="secondary">Cancel</Button>
48
+ * <Button type="submit">Save changes</Button>
49
+ * </Toolbar>
50
+ * @example
51
+ * <Toolbar label="List filters" position="top" align="between">…</Toolbar>
52
+ */
53
+ declare function Toolbar({ label, position, align, className, children, ...rest }: ToolbarProps): react.JSX.Element;
54
+
55
+ export { Toolbar, type ToolbarAlign, type ToolbarPosition, type ToolbarProps, Toolbar as default };
@@ -0,0 +1,43 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/cn.js";
3
+ const POSITION = {
4
+ bottom: "sticky bottom-0 z-(--z-sticky) border-t border-(--rule-2)",
5
+ top: "sticky top-0 z-(--z-sticky) border-b border-(--rule-2)",
6
+ static: "border-t border-(--rule-2)"
7
+ };
8
+ const ALIGN = {
9
+ start: "justify-start",
10
+ center: "justify-center",
11
+ end: "justify-end",
12
+ between: "justify-between"
13
+ };
14
+ function Toolbar({
15
+ label,
16
+ position = "bottom",
17
+ align = "end",
18
+ className,
19
+ children,
20
+ ...rest
21
+ }) {
22
+ return /* @__PURE__ */ jsx(
23
+ "div",
24
+ {
25
+ role: "group",
26
+ "aria-label": label,
27
+ className: cn(
28
+ "flex flex-wrap items-center gap-3 bg-(--paper) px-4 py-3",
29
+ POSITION[position],
30
+ ALIGN[align],
31
+ className
32
+ ),
33
+ ...rest,
34
+ children
35
+ }
36
+ );
37
+ }
38
+ var Toolbar_default = Toolbar;
39
+ export {
40
+ Toolbar,
41
+ Toolbar_default as default
42
+ };
43
+ //# sourceMappingURL=Toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/Toolbar/Toolbar.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/**\n * Which edge the bar sticks to, or neither.\n *\n * `bottom` is the form footer — the actions stay in reach while a long form\n * scrolls under them. `top` is the filter bar over a list. `static` is the same\n * bar with no stickiness, for a short page or a bar inside a dialog that is\n * already the height of its content.\n */\nexport type ToolbarPosition = 'bottom' | 'top' | 'static'\n\nexport type ToolbarAlign = 'start' | 'center' | 'end' | 'between'\n\nexport interface ToolbarProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * Names the bar for a screen reader — \"Form actions\", \"List filters\".\n * Required, because a group with no name is announced as \"group\" and a page\n * with two of them is a page with two identical announcements.\n */\n label: string\n /** Which edge the bar sticks to. See {@link ToolbarPosition}. */\n position?: ToolbarPosition\n /** Where the contents sit along the inline axis. */\n align?: ToolbarAlign\n children: ReactNode\n}\n\nconst POSITION: Record<ToolbarPosition, string> = {\n bottom: 'sticky bottom-0 z-(--z-sticky) border-t border-(--rule-2)',\n top: 'sticky top-0 z-(--z-sticky) border-b border-(--rule-2)',\n static: 'border-t border-(--rule-2)',\n}\n\nconst ALIGN: Record<ToolbarAlign, string> = {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n between: 'justify-between',\n}\n\n/**\n * The bar of actions at the edge of a working surface.\n *\n * Two page templates built the same thing independently — a sticky strip on\n * `--paper` with a rule along the edge it sticks to — which is the signal that\n * it belongs here rather than in each of them.\n *\n * The ground is opaque `--paper` and not a blur. Content scrolls UNDER this\n * bar, so anything translucent puts the last row of a table behind the submit\n * button and makes both unreadable; `FloatingIconButton` blurs because it\n * floats over a gap, which is a different problem.\n *\n * It is not `role=\"toolbar\"`. That role's contract is a single tab stop with\n * arrow keys moving between the controls inside it, and this implements no such\n * thing — declaring the role without the behaviour tells a screen-reader user\n * to press arrow keys that do nothing. It is a named `group`, so the controls\n * keep their own places in the tab order and the bar is still announced.\n *\n * @example\n * <Toolbar label=\"Form actions\">\n * <Button variant=\"secondary\">Cancel</Button>\n * <Button type=\"submit\">Save changes</Button>\n * </Toolbar>\n * @example\n * <Toolbar label=\"List filters\" position=\"top\" align=\"between\">…</Toolbar>\n */\nexport function Toolbar({\n label,\n position = 'bottom',\n align = 'end',\n className,\n children,\n ...rest\n}: ToolbarProps) {\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={cn(\n 'flex flex-wrap items-center gap-3 bg-(--paper) px-4 py-3',\n POSITION[position],\n ALIGN[align],\n className,\n )}\n {...rest}\n >\n {children}\n </div>\n )\n}\n\nexport default Toolbar\n"],"mappings":"AA6EI;AA5EJ,SAAS,UAAU;AA4BnB,MAAM,WAA4C;AAAA,EAChD,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,QAAQ;AACV;AAEA,MAAM,QAAsC;AAAA,EAC1C,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,SAAS;AACX;AA4BO,SAAS,QAAQ;AAAA,EACtB;AAAA,EACA,WAAW;AAAA,EACX,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiB;AACf,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,WAAW;AAAA,QACT;AAAA,QACA,SAAS,QAAQ;AAAA,QACjB,MAAM,KAAK;AAAA,QACX;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,kBAAQ;","names":[]}
@@ -0,0 +1,55 @@
1
+ import * as react from 'react';
2
+ import { FigureChrome } from '../lib/frame.js';
3
+ import { ArchitectureSpec } from '../spec.js';
4
+ import '../lib/geometry.js';
5
+
6
+ interface ArchitectureFigureProps extends FigureChrome {
7
+ spec: ArchitectureSpec;
8
+ }
9
+ /**
10
+ * A component map: services, datastores, boundaries, and what talks to what.
11
+ *
12
+ * Takes the same JSON an archify `architecture` specification carries —
13
+ * `components`, `boundaries`, `connections` — and draws it in this system's own
14
+ * terms: paper plates on a hairline, one reversed plate for the component the
15
+ * diagram is about, and seven drawn sigils where archify uses seven hues.
16
+ *
17
+ * IT RENDERS ON A SERVER because every position is already in the
18
+ * specification. A component gives a `row` and a `col` into a grid whose cell
19
+ * size is either declared or defaulted, or it gives an absolute `pos` — nothing
20
+ * here is solved for, relaxed, or measured. So the markup is a pure function of
21
+ * the input, it is identical on the server and in the browser, and there is no
22
+ * layout shift on hydration because there is no layout to do.
23
+ *
24
+ * A component that declares NEITHER flows: it takes the next free cell in
25
+ * declaration order, wrapping at `layout.cols`. That is still arithmetic on
26
+ * numbers the specification carries rather than a solver — and the alternative
27
+ * was every unplaced component defaulting to row 0, column 0 and stacking into
28
+ * one plate.
29
+ *
30
+ * BOUNDARIES ARE DRAWN FIRST, AND DRAWN DIFFERENTLY. A `region` is where
31
+ * something RUNS — a VPC, a zone, a cluster — and is a solid frame. A
32
+ * `security-group` is what may REACH it, and is dashed. That is not decoration:
33
+ * an infrastructure diagram is very often read for exactly one of those two
34
+ * questions, and a reader should be able to tell which line answers which
35
+ * without reading either label.
36
+ *
37
+ * @example
38
+ * <ArchitectureFigure
39
+ * spec={{
40
+ * meta: { title: 'Request path' },
41
+ * components: [
42
+ * { id: 'cdn', type: 'cloud', label: 'CloudFront', row: 0, col: 0 },
43
+ * { id: 'api', type: 'backend', label: 'FastAPI', sublabel: 'ECS', row: 0, col: 1 },
44
+ * { id: 'db', type: 'database', label: 'Postgres', row: 0, col: 2 },
45
+ * ],
46
+ * connections: [
47
+ * { from: 'cdn', to: 'api', label: 'HTTPS' },
48
+ * { from: 'api', to: 'db', label: 'SQL' },
49
+ * ],
50
+ * }}
51
+ * />
52
+ */
53
+ declare function ArchitectureFigure({ spec, className, legend, cards, heading, activeIds, onSelectNode, }: ArchitectureFigureProps): react.JSX.Element;
54
+
55
+ export { ArchitectureFigure, type ArchitectureFigureProps, ArchitectureFigure as default };