@misoto22/design 0.7.0 → 0.9.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 (398) hide show
  1. package/AGENTS.md +87 -0
  2. package/CLAUDE.md +1 -0
  3. package/README.md +50 -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 +25 -2
  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/ColorPicker.md +75 -0
  28. package/dist/agent/Combobox.md +29 -3
  29. package/dist/agent/Command.md +25 -2
  30. package/dist/agent/ComposedChart.md +26 -2
  31. package/dist/agent/ContextMenu.md +37 -4
  32. package/dist/agent/DataflowFigure.md +22 -1
  33. package/dist/agent/DatePicker.md +34 -6
  34. package/dist/agent/DescriptionList.md +68 -0
  35. package/dist/agent/Diagram.md +27 -3
  36. package/dist/agent/DiagramCanvas.md +24 -1
  37. package/dist/agent/DiagramExportMenu.md +29 -3
  38. package/dist/agent/DiagramInspector.md +23 -1
  39. package/dist/agent/DiagramLegend.md +22 -1
  40. package/dist/agent/DiagramMinimap.md +24 -4
  41. package/dist/agent/DiagramToolbar.md +23 -1
  42. package/dist/agent/Dialog.md +26 -3
  43. package/dist/agent/DropdownMenu.md +45 -6
  44. package/dist/agent/EmptyState.md +26 -1
  45. package/dist/agent/ErrorState.md +27 -2
  46. package/dist/agent/Facet.md +25 -1
  47. package/dist/agent/Field.md +45 -4
  48. package/dist/agent/FigureBand.md +24 -1
  49. package/dist/agent/FloatingIconButton.md +23 -1
  50. package/dist/agent/FunnelChart.md +23 -1
  51. package/dist/agent/Heading.md +64 -0
  52. package/dist/agent/Heatmap.md +25 -1
  53. package/dist/agent/Histogram.md +26 -2
  54. package/dist/agent/Input.md +22 -1
  55. package/dist/agent/Kbd.md +19 -1
  56. package/dist/agent/LifecycleFigure.md +22 -1
  57. package/dist/agent/LineChart.md +26 -2
  58. package/dist/agent/LinkArrow.md +20 -1
  59. package/dist/agent/Markdown.md +68 -0
  60. package/dist/agent/NativeSelect.md +23 -2
  61. package/dist/agent/NavItem.md +21 -1
  62. package/dist/agent/NumberField.md +72 -0
  63. package/dist/agent/Pagination.md +28 -2
  64. package/dist/agent/PieChart.md +26 -2
  65. package/dist/agent/Popover.md +23 -1
  66. package/dist/agent/Progress.md +27 -3
  67. package/dist/agent/RadarChart.md +26 -2
  68. package/dist/agent/RadialChart.md +26 -3
  69. package/dist/agent/RadioGroup.md +23 -2
  70. package/dist/agent/SankeyChart.md +25 -2
  71. package/dist/agent/ScatterChart.md +27 -2
  72. package/dist/agent/ScrollArea.md +24 -3
  73. package/dist/agent/SearchableMenu.md +23 -1
  74. package/dist/agent/Select.md +29 -3
  75. package/dist/agent/Separator.md +28 -4
  76. package/dist/agent/SequenceFigure.md +23 -1
  77. package/dist/agent/Sheet.md +25 -2
  78. package/dist/agent/Sidebar.md +193 -0
  79. package/dist/agent/Skeleton.md +24 -2
  80. package/dist/agent/Slider.md +31 -4
  81. package/dist/agent/Sparkline.md +23 -1
  82. package/dist/agent/Spinner.md +24 -2
  83. package/dist/agent/StatusDot.md +20 -1
  84. package/dist/agent/StatusPill.md +28 -2
  85. package/dist/agent/Steps.md +24 -1
  86. package/dist/agent/Switch.md +21 -1
  87. package/dist/agent/Table.md +28 -3
  88. package/dist/agent/Tabs.md +24 -2
  89. package/dist/agent/Tag.md +40 -9
  90. package/dist/agent/Text.md +65 -0
  91. package/dist/agent/Textarea.md +20 -1
  92. package/dist/agent/Timestamp.md +64 -0
  93. package/dist/agent/Toast.md +26 -2
  94. package/dist/agent/ToggleGroup.md +24 -2
  95. package/dist/agent/Toolbar.md +71 -0
  96. package/dist/agent/Tooltip.md +23 -1
  97. package/dist/agent/TreemapChart.md +24 -1
  98. package/dist/agent/WaterfallChart.md +24 -1
  99. package/dist/agent/WorkflowFigure.md +24 -2
  100. package/dist/agent/catalog.json +5915 -699
  101. package/dist/agent/index.md +20 -8
  102. package/dist/article.css +16 -4
  103. package/dist/charts/AreaChart/AreaChart.d.ts +9 -2
  104. package/dist/charts/AreaChart/AreaChart.js +12 -13
  105. package/dist/charts/AreaChart/AreaChart.js.map +1 -1
  106. package/dist/charts/BarChart/BarChart.d.ts +14 -3
  107. package/dist/charts/BarChart/BarChart.js +20 -12
  108. package/dist/charts/BarChart/BarChart.js.map +1 -1
  109. package/dist/charts/BarList/BarList.d.ts +9 -1
  110. package/dist/charts/BarList/BarList.js +9 -1
  111. package/dist/charts/BarList/BarList.js.map +1 -1
  112. package/dist/charts/BigNumber/BigNumber.d.ts +19 -3
  113. package/dist/charts/BigNumber/BigNumber.js +25 -5
  114. package/dist/charts/BigNumber/BigNumber.js.map +1 -1
  115. package/dist/charts/BoxPlot/BoxPlot.js +4 -2
  116. package/dist/charts/BoxPlot/BoxPlot.js.map +1 -1
  117. package/dist/charts/BulletChart/BulletChart.js +44 -9
  118. package/dist/charts/BulletChart/BulletChart.js.map +1 -1
  119. package/dist/charts/ComposedChart/ComposedChart.d.ts +9 -2
  120. package/dist/charts/ComposedChart/ComposedChart.js +10 -10
  121. package/dist/charts/ComposedChart/ComposedChart.js.map +1 -1
  122. package/dist/charts/FunnelChart/FunnelChart.d.ts +7 -2
  123. package/dist/charts/FunnelChart/FunnelChart.js +6 -16
  124. package/dist/charts/FunnelChart/FunnelChart.js.map +1 -1
  125. package/dist/charts/Heatmap/Heatmap.d.ts +17 -3
  126. package/dist/charts/Heatmap/Heatmap.js +20 -11
  127. package/dist/charts/Heatmap/Heatmap.js.map +1 -1
  128. package/dist/charts/Histogram/Histogram.d.ts +24 -1
  129. package/dist/charts/Histogram/Histogram.js +43 -11
  130. package/dist/charts/Histogram/Histogram.js.map +1 -1
  131. package/dist/charts/LineChart/LineChart.d.ts +9 -2
  132. package/dist/charts/LineChart/LineChart.js +11 -12
  133. package/dist/charts/LineChart/LineChart.js.map +1 -1
  134. package/dist/charts/PieChart/PieChart.d.ts +15 -3
  135. package/dist/charts/PieChart/PieChart.js +14 -6
  136. package/dist/charts/PieChart/PieChart.js.map +1 -1
  137. package/dist/charts/RadarChart/RadarChart.d.ts +15 -3
  138. package/dist/charts/RadarChart/RadarChart.js +15 -11
  139. package/dist/charts/RadarChart/RadarChart.js.map +1 -1
  140. package/dist/charts/RadialChart/RadialChart.d.ts +22 -4
  141. package/dist/charts/RadialChart/RadialChart.js +28 -6
  142. package/dist/charts/RadialChart/RadialChart.js.map +1 -1
  143. package/dist/charts/SankeyChart/SankeyChart.d.ts +16 -4
  144. package/dist/charts/SankeyChart/SankeyChart.js +14 -6
  145. package/dist/charts/SankeyChart/SankeyChart.js.map +1 -1
  146. package/dist/charts/ScatterChart/ScatterChart.d.ts +24 -3
  147. package/dist/charts/ScatterChart/ScatterChart.js +21 -15
  148. package/dist/charts/ScatterChart/ScatterChart.js.map +1 -1
  149. package/dist/charts/Sparkline/Sparkline.js +5 -3
  150. package/dist/charts/Sparkline/Sparkline.js.map +1 -1
  151. package/dist/charts/TreemapChart/TreemapChart.d.ts +7 -2
  152. package/dist/charts/TreemapChart/TreemapChart.js +20 -11
  153. package/dist/charts/TreemapChart/TreemapChart.js.map +1 -1
  154. package/dist/charts/WaterfallChart/WaterfallChart.js +4 -2
  155. package/dist/charts/WaterfallChart/WaterfallChart.js.map +1 -1
  156. package/dist/charts/lib/export.d.ts +1 -0
  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/ColorPicker/ColorPicker.d.ts +67 -0
  204. package/dist/components/ColorPicker/ColorPicker.js +334 -0
  205. package/dist/components/ColorPicker/ColorPicker.js.map +1 -0
  206. package/dist/components/Combobox/Combobox.d.ts +15 -1
  207. package/dist/components/Combobox/Combobox.js +25 -5
  208. package/dist/components/Combobox/Combobox.js.map +1 -1
  209. package/dist/components/Command/Command.d.ts +4 -2
  210. package/dist/components/Command/Command.js +14 -2
  211. package/dist/components/Command/Command.js.map +1 -1
  212. package/dist/components/ContextMenu/ContextMenu.d.ts +30 -5
  213. package/dist/components/ContextMenu/ContextMenu.js +33 -3
  214. package/dist/components/ContextMenu/ContextMenu.js.map +1 -1
  215. package/dist/components/DatePicker/DatePicker.d.ts +36 -4
  216. package/dist/components/DatePicker/DatePicker.js +55 -12
  217. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  218. package/dist/components/DescriptionList/DescriptionList.d.ts +73 -0
  219. package/dist/components/DescriptionList/DescriptionList.js +35 -0
  220. package/dist/components/DescriptionList/DescriptionList.js.map +1 -0
  221. package/dist/components/Diagram/Diagram.d.ts +8 -3
  222. package/dist/components/Diagram/Diagram.js +82 -10
  223. package/dist/components/Diagram/Diagram.js.map +1 -1
  224. package/dist/components/Dialog/Dialog.d.ts +18 -3
  225. package/dist/components/Dialog/Dialog.js +21 -3
  226. package/dist/components/Dialog/Dialog.js.map +1 -1
  227. package/dist/components/DropdownMenu/DropdownMenu.d.ts +49 -11
  228. package/dist/components/DropdownMenu/DropdownMenu.js +33 -3
  229. package/dist/components/DropdownMenu/DropdownMenu.js.map +1 -1
  230. package/dist/components/EmptyState/EmptyState.d.ts +25 -1
  231. package/dist/components/EmptyState/EmptyState.js +3 -1
  232. package/dist/components/EmptyState/EmptyState.js.map +1 -1
  233. package/dist/components/ErrorState/ErrorState.d.ts +22 -1
  234. package/dist/components/ErrorState/ErrorState.js +12 -3
  235. package/dist/components/ErrorState/ErrorState.js.map +1 -1
  236. package/dist/components/Field/Field.d.ts +70 -3
  237. package/dist/components/Field/Field.js +53 -12
  238. package/dist/components/Field/Field.js.map +1 -1
  239. package/dist/components/Field/field-control.d.ts +31 -0
  240. package/dist/components/Field/field-control.js +12 -0
  241. package/dist/components/Field/field-control.js.map +1 -0
  242. package/dist/components/FloatingIconButton/FloatingIconButton.js +2 -0
  243. package/dist/components/FloatingIconButton/FloatingIconButton.js.map +1 -1
  244. package/dist/components/Heading/Heading.d.ts +62 -0
  245. package/dist/components/Heading/Heading.js +44 -0
  246. package/dist/components/Heading/Heading.js.map +1 -0
  247. package/dist/components/Markdown/Markdown.d.ts +139 -0
  248. package/dist/components/Markdown/Markdown.js +135 -0
  249. package/dist/components/Markdown/Markdown.js.map +1 -0
  250. package/dist/components/Markdown/inline.d.ts +29 -0
  251. package/dist/components/Markdown/inline.js +74 -0
  252. package/dist/components/Markdown/inline.js.map +1 -0
  253. package/dist/components/Markdown/nodes.d.ts +65 -0
  254. package/dist/components/Markdown/nodes.js +1 -0
  255. package/dist/components/Markdown/nodes.js.map +1 -0
  256. package/dist/components/Markdown/parse.d.ts +24 -0
  257. package/dist/components/Markdown/parse.js +110 -0
  258. package/dist/components/Markdown/parse.js.map +1 -0
  259. package/dist/components/Markdown/slug.d.ts +15 -0
  260. package/dist/components/Markdown/slug.js +7 -0
  261. package/dist/components/Markdown/slug.js.map +1 -0
  262. package/dist/components/NativeSelect/NativeSelect.d.ts +6 -0
  263. package/dist/components/NativeSelect/NativeSelect.js +2 -3
  264. package/dist/components/NativeSelect/NativeSelect.js.map +1 -1
  265. package/dist/components/NavItem/NavItem.js +1 -1
  266. package/dist/components/NavItem/NavItem.js.map +1 -1
  267. package/dist/components/NumberField/NumberField.d.ts +69 -0
  268. package/dist/components/NumberField/NumberField.js +162 -0
  269. package/dist/components/NumberField/NumberField.js.map +1 -0
  270. package/dist/components/Pagination/Pagination.d.ts +24 -1
  271. package/dist/components/Pagination/Pagination.js +6 -3
  272. package/dist/components/Pagination/Pagination.js.map +1 -1
  273. package/dist/components/Popover/Popover.js +1 -1
  274. package/dist/components/Popover/Popover.js.map +1 -1
  275. package/dist/components/Progress/Progress.d.ts +17 -5
  276. package/dist/components/Progress/Progress.js +18 -6
  277. package/dist/components/Progress/Progress.js.map +1 -1
  278. package/dist/components/RadioGroup/RadioGroup.d.ts +6 -0
  279. package/dist/components/RadioGroup/RadioGroup.js +11 -1
  280. package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
  281. package/dist/components/ScrollArea/ScrollArea.d.ts +15 -0
  282. package/dist/components/ScrollArea/ScrollArea.js +2 -2
  283. package/dist/components/ScrollArea/ScrollArea.js.map +1 -1
  284. package/dist/components/SearchableMenu/SearchableMenu.d.ts +11 -2
  285. package/dist/components/SearchableMenu/SearchableMenu.js +24 -2
  286. package/dist/components/SearchableMenu/SearchableMenu.js.map +1 -1
  287. package/dist/components/Select/Select.d.ts +18 -2
  288. package/dist/components/Select/Select.js +21 -4
  289. package/dist/components/Select/Select.js.map +1 -1
  290. package/dist/components/Separator/Separator.d.ts +21 -3
  291. package/dist/components/Separator/Separator.js +9 -1
  292. package/dist/components/Separator/Separator.js.map +1 -1
  293. package/dist/components/Sheet/Sheet.d.ts +3 -0
  294. package/dist/components/Sheet/Sheet.js +12 -3
  295. package/dist/components/Sheet/Sheet.js.map +1 -1
  296. package/dist/components/Sidebar/Sidebar.d.ts +349 -0
  297. package/dist/components/Sidebar/Sidebar.js +455 -0
  298. package/dist/components/Sidebar/Sidebar.js.map +1 -0
  299. package/dist/components/Skeleton/Skeleton.d.ts +8 -1
  300. package/dist/components/Skeleton/Skeleton.js +1 -1
  301. package/dist/components/Skeleton/Skeleton.js.map +1 -1
  302. package/dist/components/Slider/Slider.d.ts +42 -3
  303. package/dist/components/Slider/Slider.js +121 -30
  304. package/dist/components/Slider/Slider.js.map +1 -1
  305. package/dist/components/Spinner/Spinner.d.ts +8 -0
  306. package/dist/components/Spinner/Spinner.js +3 -2
  307. package/dist/components/Spinner/Spinner.js.map +1 -1
  308. package/dist/components/StatusPill/StatusPill.d.ts +5 -0
  309. package/dist/components/StatusPill/StatusPill.js +6 -0
  310. package/dist/components/StatusPill/StatusPill.js.map +1 -1
  311. package/dist/components/Table/Table.d.ts +20 -0
  312. package/dist/components/Table/Table.js +3 -1
  313. package/dist/components/Table/Table.js.map +1 -1
  314. package/dist/components/Tabs/Tabs.js +7 -1
  315. package/dist/components/Tabs/Tabs.js.map +1 -1
  316. package/dist/components/Tag/Tag.d.ts +68 -9
  317. package/dist/components/Tag/Tag.js +50 -10
  318. package/dist/components/Tag/Tag.js.map +1 -1
  319. package/dist/components/Text/Text.d.ts +62 -0
  320. package/dist/components/Text/Text.js +30 -0
  321. package/dist/components/Text/Text.js.map +1 -0
  322. package/dist/components/Timestamp/Timestamp.d.ts +59 -0
  323. package/dist/components/Timestamp/Timestamp.js +56 -0
  324. package/dist/components/Timestamp/Timestamp.js.map +1 -0
  325. package/dist/components/Toast/Toast.d.ts +9 -1
  326. package/dist/components/Toast/Toast.js +27 -4
  327. package/dist/components/Toast/Toast.js.map +1 -1
  328. package/dist/components/ToggleGroup/ToggleGroup.d.ts +6 -1
  329. package/dist/components/ToggleGroup/ToggleGroup.js +11 -1
  330. package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
  331. package/dist/components/Toolbar/Toolbar.d.ts +55 -0
  332. package/dist/components/Toolbar/Toolbar.js +43 -0
  333. package/dist/components/Toolbar/Toolbar.js.map +1 -0
  334. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.d.ts +6 -0
  335. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js +48 -8
  336. package/dist/diagrams/ArchitectureFigure/ArchitectureFigure.js.map +1 -1
  337. package/dist/diagrams/DataflowFigure/DataflowFigure.js +21 -2
  338. package/dist/diagrams/DataflowFigure/DataflowFigure.js.map +1 -1
  339. package/dist/diagrams/DiagramCanvas/DiagramCanvas.d.ts +14 -0
  340. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js +14 -7
  341. package/dist/diagrams/DiagramCanvas/DiagramCanvas.js.map +1 -1
  342. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.d.ts +38 -4
  343. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js +14 -16
  344. package/dist/diagrams/DiagramExportMenu/DiagramExportMenu.js.map +1 -1
  345. package/dist/diagrams/DiagramInspector/DiagramInspector.js +2 -2
  346. package/dist/diagrams/DiagramInspector/DiagramInspector.js.map +1 -1
  347. package/dist/diagrams/DiagramMinimap/DiagramMinimap.d.ts +23 -7
  348. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js +45 -18
  349. package/dist/diagrams/DiagramMinimap/DiagramMinimap.js.map +1 -1
  350. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js +44 -12
  351. package/dist/diagrams/LifecycleFigure/LifecycleFigure.js.map +1 -1
  352. package/dist/diagrams/SequenceFigure/SequenceFigure.js +35 -5
  353. package/dist/diagrams/SequenceFigure/SequenceFigure.js.map +1 -1
  354. package/dist/diagrams/WorkflowFigure/WorkflowFigure.d.ts +3 -1
  355. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js +76 -28
  356. package/dist/diagrams/WorkflowFigure/WorkflowFigure.js.map +1 -1
  357. package/dist/diagrams/index.d.ts +1 -0
  358. package/dist/diagrams/index.js +10 -0
  359. package/dist/diagrams/index.js.map +1 -1
  360. package/dist/diagrams/lib/dev.d.ts +61 -0
  361. package/dist/diagrams/lib/dev.js +96 -0
  362. package/dist/diagrams/lib/dev.js.map +1 -0
  363. package/dist/diagrams/lib/frame.d.ts +48 -7
  364. package/dist/diagrams/lib/frame.js +17 -2
  365. package/dist/diagrams/lib/frame.js.map +1 -1
  366. package/dist/diagrams/lib/route.d.ts +22 -1
  367. package/dist/diagrams/lib/route.js +24 -1
  368. package/dist/diagrams/lib/route.js.map +1 -1
  369. package/dist/diagrams/lib/wires.js +9 -5
  370. package/dist/diagrams/lib/wires.js.map +1 -1
  371. package/dist/diagrams/spec.d.ts +64 -12
  372. package/dist/index.d.ts +19 -4
  373. package/dist/index.js +12 -0
  374. package/dist/index.js.map +1 -1
  375. package/dist/keyframes.css +57 -3
  376. package/dist/lib/color.d.ts +80 -0
  377. package/dist/lib/color.js +189 -0
  378. package/dist/lib/color.js.map +1 -0
  379. package/dist/lib/numeric.d.ts +35 -0
  380. package/dist/lib/numeric.js +29 -0
  381. package/dist/lib/numeric.js.map +1 -0
  382. package/dist/lib/overlay-container.d.ts +14 -4
  383. package/dist/lib/overlay-container.js.map +1 -1
  384. package/dist/lib/warn.d.ts +73 -0
  385. package/dist/lib/warn.js +38 -0
  386. package/dist/lib/warn.js.map +1 -0
  387. package/dist/semantic.css +17 -6
  388. package/dist/styles.css +1 -1
  389. package/dist/themes.css +8 -0
  390. package/dist/tokens.css +86 -5
  391. package/dist/tokens.d.ts +4 -1
  392. package/dist/tokens.js +56 -36
  393. package/dist/tokens.json +56 -36
  394. package/llms.txt +35 -0
  395. package/package.json +5 -2
  396. package/skills/misoto22-design/evals/evals.json +84 -0
  397. package/skills/misoto22-design/rules/a11y.md +55 -3
  398. package/skills/misoto22-design/rules/forms.md +8 -1
@@ -3,6 +3,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as DialogPrimitive from "@radix-ui/react-dialog";
4
4
  import { X } from "lucide-react";
5
5
  import { cn } from "../../lib/cn.js";
6
+ import { useOverlayContainer } from "../../lib/overlay-container.js";
7
+ import { DEV, warn } from "../../lib/warn.js";
6
8
  const Dialog = DialogPrimitive.Root;
7
9
  const DialogTrigger = DialogPrimitive.Trigger;
8
10
  const DialogClose = DialogPrimitive.Close;
@@ -26,12 +28,25 @@ function DialogContent({
26
28
  hideTitle = false,
27
29
  ...rest
28
30
  }) {
29
- return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { children: [
31
+ const container = useOverlayContainer();
32
+ if (DEV && title === void 0) {
33
+ warn({
34
+ code: "DIALOG_TITLE_MISSING",
35
+ problem: 'DialogContent has no title, so its accessible name is the fallback string "Dialog". Every unnamed modal in the app announces identically, and the check that would have caught it passes.',
36
+ field: "title",
37
+ fix: "Give it a title that says what the dialog asks. Add hideTitle when the heading would be furniture on screen.",
38
+ component: "Dialog"
39
+ });
40
+ }
41
+ return /* @__PURE__ */ jsxs(DialogPrimitive.Portal, { container: container ?? void 0, children: [
30
42
  /* @__PURE__ */ jsx(
31
43
  DialogPrimitive.Overlay,
32
44
  {
33
45
  "data-m22-animated": true,
34
- className: "fixed inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]"
46
+ className: cn(
47
+ "inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]",
48
+ container ? "absolute" : "fixed"
49
+ )
35
50
  }
36
51
  ),
37
52
  /* @__PURE__ */ jsxs(
@@ -39,8 +54,11 @@ function DialogContent({
39
54
  {
40
55
  "data-m22-animated": true,
41
56
  className: cn(
42
- "fixed left-1/2 top-1/2 z-(--z-modal) max-h-[85vh] w-[min(92vw,32rem)] -translate-x-1/2 -translate-y-1/2 overflow-auto rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-6 panel-blur scroll-slim",
57
+ "fixed left-1/2 top-1/2 z-(--z-modal) max-h-[85vh] w-[min(92vw,32rem)] -translate-x-1/2 -translate-y-1/2 overflow-auto rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-6 shadow-(--panel-lift) panel-blur scroll-slim",
43
58
  "data-[state=open]:animate-[m22-panel-in_var(--duration-base)_var(--ease)]",
59
+ // Against the container's box rather than the viewport's, and capped
60
+ // by it: 92vw inside a 400px frame is not a cap at all.
61
+ container && "absolute max-h-[calc(100%-2rem)] max-w-[calc(100%-2rem)]",
44
62
  className
45
63
  ),
46
64
  ...rest,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["'use client'\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\n/** Radix Dialog root + trigger + close, re-exported as typed passthroughs. */\nexport const Dialog = DialogPrimitive.Root\nexport const DialogTrigger = DialogPrimitive.Trigger\nexport const DialogClose = DialogPrimitive.Close\n\n/** Title + description stack; renders nothing when both are omitted. */\nfunction DialogHeader({\n title,\n description,\n hidden,\n}: {\n title?: ReactNode\n description?: ReactNode\n hidden: boolean\n}) {\n if (title === undefined && description === undefined) return null\n return (\n <div className={cn('mb-4 flex flex-col gap-1 pe-8', hidden && 'sr-only')}>\n {title !== undefined && (\n <DialogPrimitive.Title className=\"m-0 font-heading text-[length:var(--fs-item)] font-normal text-(--ink)\">\n {title}\n </DialogPrimitive.Title>\n )}\n {description !== undefined && (\n <DialogPrimitive.Description className=\"m-0 text-sm leading-relaxed text-(--ink-3-aa)\">\n {description}\n </DialogPrimitive.Description>\n )}\n </div>\n )\n}\n\nexport interface DialogContentProps\n extends Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title' | 'className'> {\n /** Heading text. When omitted, a visually-hidden title is rendered for a11y. */\n title?: ReactNode\n /** Sub-heading under the title. */\n description?: ReactNode\n className?: string\n /** Show the top-right close control (default true). */\n showClose?: boolean\n /**\n * Keeps the title for assistive tech and hides it visually.\n *\n * For a surface whose purpose is obvious to anyone who can see it — a command\n * palette, a media lightbox — where a printed heading would be furniture. The\n * title itself is never optional: Radix requires one, and a modal with no\n * accessible name drops a screen reader into an unnamed region.\n */\n hideTitle?: boolean\n}\n\n/**\n * A modal surface: portal → scrim → centred panel.\n *\n * Radix owns the focus trap, the escape key, the scroll lock and the\n * `aria-modal` wiring — all of which a hand-rolled dialog gets subtly wrong,\n * usually by leaving focus behind in the page underneath.\n *\n * Radix requires a `Dialog.Title` whether or not one is shown, so a dialog\n * without a visible heading still renders a hidden one rather than logging a\n * warning and shipping an unnamed modal.\n *\n * @example\n * <Dialog>\n * <DialogTrigger asChild><Button>Delete</Button></DialogTrigger>\n * <DialogContent title=\"Delete file\" description=\"This cannot be undone.\">\n * <DialogClose asChild><Button variant=\"secondary\">Cancel</Button></DialogClose>\n * </DialogContent>\n * </Dialog>\n */\nexport function DialogContent({\n title,\n description,\n children,\n className,\n showClose = true,\n hideTitle = false,\n ...rest\n}: DialogContentProps) {\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay\n data-m22-animated\n className=\"fixed inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]\"\n />\n <DialogPrimitive.Content\n data-m22-animated\n className={cn(\n 'fixed left-1/2 top-1/2 z-(--z-modal) max-h-[85vh] w-[min(92vw,32rem)] -translate-x-1/2 -translate-y-1/2 overflow-auto rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-6 panel-blur scroll-slim',\n 'data-[state=open]:animate-[m22-panel-in_var(--duration-base)_var(--ease)]',\n className,\n )}\n {...rest}\n >\n <DialogHeader title={title} description={description} hidden={hideTitle} />\n\n {title === undefined && (\n <DialogPrimitive.Title className=\"sr-only\">Dialog</DialogPrimitive.Title>\n )}\n\n {showClose && (\n <DialogPrimitive.Close\n aria-label=\"Close\"\n className=\"absolute end-3 top-3 grid size-9 place-items-center rounded-(--radius-pill) text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:bg-(--stone) hover:text-(--ink)\"\n >\n <X size={16} strokeWidth={1.5} aria-hidden />\n </DialogPrimitive.Close>\n )}\n\n {children}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n )\n}\n\nexport default Dialog\n"],"mappings":";AAwBI,SAEI,KAFJ;AAtBJ,YAAY,qBAAqB;AACjC,SAAS,SAAS;AAElB,SAAS,UAAU;AAGZ,MAAM,SAAS,gBAAgB;AAC/B,MAAM,gBAAgB,gBAAgB;AACtC,MAAM,cAAc,gBAAgB;AAG3C,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,UAAU,UAAa,gBAAgB,OAAW,QAAO;AAC7D,SACE,qBAAC,SAAI,WAAW,GAAG,iCAAiC,UAAU,SAAS,GACpE;AAAA,cAAU,UACT,oBAAC,gBAAgB,OAAhB,EAAsB,WAAU,0EAC9B,iBACH;AAAA,IAED,gBAAgB,UACf,oBAAC,gBAAgB,aAAhB,EAA4B,WAAU,iDACpC,uBACH;AAAA,KAEJ;AAEJ;AAyCO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,GAAG;AACL,GAAuB;AACrB,SACE,qBAAC,gBAAgB,QAAhB,EACC;AAAA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAU;AAAA;AAAA,IACZ;AAAA,IACA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ;AAAA,8BAAC,gBAAa,OAAc,aAA0B,QAAQ,WAAW;AAAA,UAExE,UAAU,UACT,oBAAC,gBAAgB,OAAhB,EAAsB,WAAU,WAAU,oBAAM;AAAA,UAGlD,aACC;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,cAAW;AAAA,cACX,WAAU;AAAA,cAEV,8BAAC,KAAE,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC;AAAA;AAAA,UAC7C;AAAA,UAGD;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAEA,IAAO,iBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/Dialog/Dialog.tsx"],"sourcesContent":["'use client'\n\nimport * as DialogPrimitive from '@radix-ui/react-dialog'\nimport { X } from 'lucide-react'\nimport type { ComponentProps, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\nimport { DEV, warn } from '../../lib/warn'\n\n/** Radix Dialog root + trigger + close, re-exported as typed passthroughs. */\nexport const Dialog = DialogPrimitive.Root\nexport const DialogTrigger = DialogPrimitive.Trigger\nexport const DialogClose = DialogPrimitive.Close\n\n/** Title + description stack; renders nothing when both are omitted. */\nfunction DialogHeader({\n title,\n description,\n hidden,\n}: {\n title?: ReactNode\n description?: ReactNode\n hidden: boolean\n}) {\n if (title === undefined && description === undefined) return null\n return (\n <div className={cn('mb-4 flex flex-col gap-1 pe-8', hidden && 'sr-only')}>\n {title !== undefined && (\n <DialogPrimitive.Title className=\"m-0 font-heading text-[length:var(--fs-item)] font-normal text-(--ink)\">\n {title}\n </DialogPrimitive.Title>\n )}\n {description !== undefined && (\n <DialogPrimitive.Description className=\"m-0 text-sm leading-relaxed text-(--ink-3-aa)\">\n {description}\n </DialogPrimitive.Description>\n )}\n </div>\n )\n}\n\nexport interface DialogContentProps\n extends Omit<ComponentProps<typeof DialogPrimitive.Content>, 'title' | 'className'> {\n /**\n * Heading text.\n *\n * Pass one even when `hideTitle` is set. Radix requires a title, so omitting\n * it renders a hidden fallback reading the literal word \"Dialog\" — which\n * satisfies an automated accessibility check and announces every unnamed\n * modal in the application as the same thing. Development says so out loud.\n */\n title?: ReactNode\n /** Sub-heading under the title. */\n description?: ReactNode\n className?: string\n /** Show the top-right close control (default true). */\n showClose?: boolean\n /**\n * Keeps the title for assistive tech and hides it visually.\n *\n * For a surface whose purpose is obvious to anyone who can see it — a command\n * palette, a media lightbox — where a printed heading would be furniture. The\n * title itself is never optional: Radix requires one, and a modal with no\n * accessible name drops a screen reader into an unnamed region.\n */\n hideTitle?: boolean\n}\n\n/**\n * A modal surface: portal → scrim → centred panel.\n *\n * Radix owns the focus trap, the escape key, the scroll lock and the\n * `aria-modal` wiring — all of which a hand-rolled dialog gets subtly wrong,\n * usually by leaving focus behind in the page underneath.\n *\n * Radix requires a `Dialog.Title` whether or not one is shown, so a dialog\n * without a visible heading still renders a hidden one rather than shipping an\n * unnamed modal — and warns in development, because the fallback it renders is\n * the literal word \"Dialog\" and a placeholder that passes an accessibility\n * check is how the problem survives a review.\n *\n * Portals into the element an enclosing `OverlayContainer` names, and switches\n * from viewport positioning to container positioning when there is one. A\n * `fixed` panel covers the page whatever it is portalled into, so honouring\n * the container without that swap would have moved the markup and left the\n * picture unchanged.\n *\n * @example\n * <Dialog>\n * <DialogTrigger asChild><Button>Delete</Button></DialogTrigger>\n * <DialogContent title=\"Delete file\" description=\"This cannot be undone.\">\n * <DialogClose asChild><Button variant=\"secondary\">Cancel</Button></DialogClose>\n * </DialogContent>\n * </Dialog>\n */\nexport function DialogContent({\n title,\n description,\n children,\n className,\n showClose = true,\n hideTitle = false,\n ...rest\n}: DialogContentProps) {\n const container = useOverlayContainer()\n\n if (DEV && title === undefined) {\n warn({\n code: 'DIALOG_TITLE_MISSING',\n problem:\n 'DialogContent has no title, so its accessible name is the fallback string \"Dialog\". Every unnamed modal in the app announces identically, and the check that would have caught it passes.',\n field: 'title',\n fix: 'Give it a title that says what the dialog asks. Add hideTitle when the heading would be furniture on screen.',\n component: 'Dialog',\n })\n }\n\n return (\n <DialogPrimitive.Portal container={container ?? undefined}>\n <DialogPrimitive.Overlay\n data-m22-animated\n className={cn(\n 'inset-0 z-(--z-overlay) bg-(--scrim) data-[state=open]:animate-[m22-fade-in_var(--duration-fast)_var(--ease)]',\n container ? 'absolute' : 'fixed',\n )}\n />\n <DialogPrimitive.Content\n data-m22-animated\n className={cn(\n 'fixed left-1/2 top-1/2 z-(--z-modal) max-h-[85vh] w-[min(92vw,32rem)] -translate-x-1/2 -translate-y-1/2 overflow-auto rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-6 shadow-(--panel-lift) panel-blur scroll-slim',\n 'data-[state=open]:animate-[m22-panel-in_var(--duration-base)_var(--ease)]',\n // Against the container's box rather than the viewport's, and capped\n // by it: 92vw inside a 400px frame is not a cap at all.\n container && 'absolute max-h-[calc(100%-2rem)] max-w-[calc(100%-2rem)]',\n className,\n )}\n {...rest}\n >\n <DialogHeader title={title} description={description} hidden={hideTitle} />\n\n {title === undefined && (\n <DialogPrimitive.Title className=\"sr-only\">Dialog</DialogPrimitive.Title>\n )}\n\n {showClose && (\n <DialogPrimitive.Close\n aria-label=\"Close\"\n className=\"absolute end-3 top-3 grid size-9 place-items-center rounded-(--radius-pill) text-(--ink-3-aa) transition-colors duration-(--duration-fast) hover:bg-(--stone) hover:text-(--ink)\"\n >\n <X size={16} strokeWidth={1.5} aria-hidden />\n </DialogPrimitive.Close>\n )}\n\n {children}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n )\n}\n\nexport default Dialog\n"],"mappings":";AA0BI,SAEI,KAFJ;AAxBJ,YAAY,qBAAqB;AACjC,SAAS,SAAS;AAElB,SAAS,UAAU;AACnB,SAAS,2BAA2B;AACpC,SAAS,KAAK,YAAY;AAGnB,MAAM,SAAS,gBAAgB;AAC/B,MAAM,gBAAgB,gBAAgB;AACtC,MAAM,cAAc,gBAAgB;AAG3C,SAAS,aAAa;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,MAAI,UAAU,UAAa,gBAAgB,OAAW,QAAO;AAC7D,SACE,qBAAC,SAAI,WAAW,GAAG,iCAAiC,UAAU,SAAS,GACpE;AAAA,cAAU,UACT,oBAAC,gBAAgB,OAAhB,EAAsB,WAAU,0EAC9B,iBACH;AAAA,IAED,gBAAgB,UACf,oBAAC,gBAAgB,aAAhB,EAA4B,WAAU,iDACpC,uBACH;AAAA,KAEJ;AAEJ;AAwDO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,GAAG;AACL,GAAuB;AACrB,QAAM,YAAY,oBAAoB;AAEtC,MAAI,OAAO,UAAU,QAAW;AAC9B,SAAK;AAAA,MACH,MAAM;AAAA,MACN,SACE;AAAA,MACF,OAAO;AAAA,MACP,KAAK;AAAA,MACL,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SACE,qBAAC,gBAAgB,QAAhB,EAAuB,WAAW,aAAa,QAC9C;AAAA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UACA,YAAY,aAAa;AAAA,QAC3B;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC,gBAAgB;AAAA,MAAhB;AAAA,QACC,qBAAiB;AAAA,QACjB,WAAW;AAAA,UACT;AAAA,UACA;AAAA;AAAA;AAAA,UAGA,aAAa;AAAA,UACb;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ;AAAA,8BAAC,gBAAa,OAAc,aAA0B,QAAQ,WAAW;AAAA,UAExE,UAAU,UACT,oBAAC,gBAAgB,OAAhB,EAAsB,WAAU,WAAU,oBAAM;AAAA,UAGlD,aACC;AAAA,YAAC,gBAAgB;AAAA,YAAhB;AAAA,cACC,cAAW;AAAA,cACX,WAAU;AAAA,cAEV,8BAAC,KAAE,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC;AAAA;AAAA,UAC7C;AAAA,UAGD;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;AAEA,IAAO,iBAAQ;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ComponentProps } from 'react';
2
+ import { ComponentProps, ReactNode } from 'react';
3
3
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
4
4
  import { LucideIcon } from 'lucide-react';
5
5
 
@@ -11,16 +11,17 @@ type DropdownMenuContentProps = ComponentProps<typeof DropdownMenuPrimitive.Cont
11
11
  * A menu surface.
12
12
  *
13
13
  * A menu is a list of ACTIONS. If the items navigate somewhere, they belong in
14
- * a nav; if they set a value, that is a `Select` or a `RadioGroup` — Radix has
15
- * menu variants for both, and a plain item pretending to be a choice loses the
16
- * checked state a screen reader needs.
14
+ * a nav; if they set a value, that is a `Select` or a `RadioGroup` — this
15
+ * package ships no checkbox or radio menu item, and a plain item pretending to
16
+ * be a choice loses the checked state a screen reader needs.
17
17
  *
18
18
  * @example
19
19
  * <DropdownMenu>
20
20
  * <DropdownMenuTrigger asChild><Button variant="secondary">Menu</Button></DropdownMenuTrigger>
21
21
  * <DropdownMenuContent>
22
- * <DropdownMenuLabel>Account</DropdownMenuLabel>
23
- * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
22
+ * <DropdownMenuGroup label="Account">
23
+ * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
24
+ * </DropdownMenuGroup>
24
25
  * <DropdownMenuSeparator />
25
26
  * <DropdownMenuItem icon={LogOut}>Sign out</DropdownMenuItem>
26
27
  * </DropdownMenuContent>
@@ -28,8 +29,16 @@ type DropdownMenuContentProps = ComponentProps<typeof DropdownMenuPrimitive.Cont
28
29
  */
29
30
  declare function DropdownMenuContent({ className, sideOffset, children, ...rest }: DropdownMenuContentProps): react.JSX.Element;
30
31
  interface DropdownMenuItemProps extends ComponentProps<typeof DropdownMenuPrimitive.Item> {
31
- /** Optional leading icon, rendered before the label. */
32
- icon?: LucideIcon;
32
+ /**
33
+ * Optional leading icon, rendered before the label.
34
+ *
35
+ * Either spelling: `icon={Settings}` passes the component and this sizes it,
36
+ * `icon={<Settings size={16} />}` passes the element and this places it. The
37
+ * two used to mean opposite things one import apart — `CommandItem.icon` took
38
+ * the element while this took the component — and the wrong one did not fail
39
+ * a type check into anything actionable, it failed at render.
40
+ */
41
+ icon?: LucideIcon | ReactNode;
33
42
  /** Paints the row as destructive. Use for delete, revoke, disconnect. */
34
43
  destructive?: boolean;
35
44
  }
@@ -40,10 +49,39 @@ interface DropdownMenuItemProps extends ComponentProps<typeof DropdownMenuPrimit
40
49
  * hover and keyboard focus — styling `:hover` alone leaves the keyboard user
41
50
  * unable to see where they are.
42
51
  */
43
- declare function DropdownMenuItem({ icon: Icon, destructive, className, children, ...rest }: DropdownMenuItemProps): react.JSX.Element;
52
+ declare function DropdownMenuItem({ icon, destructive, className, children, ...rest }: DropdownMenuItemProps): react.JSX.Element;
44
53
  /** Hairline divider between menu groups. */
45
54
  declare function DropdownMenuSeparator({ className, ...rest }: ComponentProps<typeof DropdownMenuPrimitive.Separator>): react.JSX.Element;
46
- /** Mono eyebrow heading for a group of items. */
55
+ /**
56
+ * Mono eyebrow heading, on its own.
57
+ *
58
+ * Visual only: Radix renders it as a bare `<div>` with no role, so it segments
59
+ * the menu for a reader who can see it and for nobody else. Reach for
60
+ * `DropdownMenuGroup` when the eyebrow is a HEADING over rows; this is right
61
+ * for a line that heads nothing — the signed-in address at the top of an
62
+ * account menu.
63
+ */
47
64
  declare function DropdownMenuLabel({ className, ...rest }: ComponentProps<typeof DropdownMenuPrimitive.Label>): react.JSX.Element;
65
+ interface DropdownMenuGroupProps extends ComponentProps<typeof DropdownMenuPrimitive.Group> {
66
+ /** The eyebrow over the rows, and the group's accessible name. */
67
+ label?: ReactNode;
68
+ }
69
+ /**
70
+ * A named section of a menu.
71
+ *
72
+ * The eyebrow alone was a picture of a heading. Radix's `MenuLabel` carries no
73
+ * role and no `aria-labelledby` wiring, and `MenuGroup` — which does carry
74
+ * `role="group"` — was not re-exported by this package at all, so a sighted
75
+ * reader saw three labelled sections and a screen-reader user got one
76
+ * undifferentiated list. This renders the group, renders the label inside it,
77
+ * and points the one at the other, which is the whole of the fix and not
78
+ * something a caller should have to remember.
79
+ *
80
+ * @example
81
+ * <DropdownMenuGroup label="Account">
82
+ * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>
83
+ * </DropdownMenuGroup>
84
+ */
85
+ declare function DropdownMenuGroup({ label, children, ...rest }: DropdownMenuGroupProps): react.JSX.Element;
48
86
 
49
- export { DropdownMenu, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenu as default };
87
+ export { DropdownMenu, DropdownMenuContent, type DropdownMenuContentProps, DropdownMenuGroup, type DropdownMenuGroupProps, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, DropdownMenu as default };
@@ -1,8 +1,23 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
4
+ import { isValidElement, useId } from "react";
4
5
  import { cn } from "../../lib/cn.js";
5
6
  import { useOverlayContainer } from "../../lib/overlay-container.js";
7
+ function isIconComponent(icon) {
8
+ if (isValidElement(icon)) return false;
9
+ if (typeof icon === "function") return true;
10
+ if (typeof icon !== "object" || icon === null) return false;
11
+ return !Array.isArray(icon) && !(Symbol.iterator in icon) && !("then" in icon);
12
+ }
13
+ function iconNode(icon) {
14
+ if (icon === void 0 || icon === null || icon === false) return null;
15
+ if (!isIconComponent(icon)) {
16
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "grid size-4 shrink-0 place-items-center [&_svg]:size-4", children: icon });
17
+ }
18
+ const Icon = icon;
19
+ return /* @__PURE__ */ jsx(Icon, { size: 16, strokeWidth: 1.5, className: "shrink-0", "aria-hidden": true });
20
+ }
6
21
  const DropdownMenu = DropdownMenuPrimitive.Root;
7
22
  const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
8
23
  function DropdownMenuContent({
@@ -20,7 +35,7 @@ function DropdownMenuContent({
20
35
  sideOffset,
21
36
  "data-m22-animated": true,
22
37
  className: cn(
23
- "z-(--z-dropdown) min-w-44 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-1.5 panel-blur",
38
+ "z-(--z-dropdown) min-w-44 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-1.5 shadow-(--panel-lift) panel-blur",
24
39
  "data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)",
25
40
  className
26
41
  ),
@@ -30,7 +45,7 @@ function DropdownMenuContent({
30
45
  ) });
31
46
  }
32
47
  function DropdownMenuItem({
33
- icon: Icon,
48
+ icon,
34
49
  destructive = false,
35
50
  className,
36
51
  children,
@@ -46,7 +61,7 @@ function DropdownMenuItem({
46
61
  ),
47
62
  ...rest,
48
63
  children: [
49
- Icon && /* @__PURE__ */ jsx(Icon, { size: 16, strokeWidth: 1.5, className: "shrink-0", "aria-hidden": true }),
64
+ iconNode(icon),
50
65
  children
51
66
  ]
52
67
  }
@@ -76,10 +91,25 @@ function DropdownMenuLabel({
76
91
  }
77
92
  );
78
93
  }
94
+ function DropdownMenuGroup({ label, children, ...rest }) {
95
+ const id = useId();
96
+ return /* @__PURE__ */ jsxs(
97
+ DropdownMenuPrimitive.Group,
98
+ {
99
+ "aria-labelledby": label === void 0 ? void 0 : id,
100
+ ...rest,
101
+ children: [
102
+ label !== void 0 && /* @__PURE__ */ jsx(DropdownMenuLabel, { id, children: label }),
103
+ children
104
+ ]
105
+ }
106
+ );
107
+ }
79
108
  var DropdownMenu_default = DropdownMenu;
80
109
  export {
81
110
  DropdownMenu,
82
111
  DropdownMenuContent,
112
+ DropdownMenuGroup,
83
113
  DropdownMenuItem,
84
114
  DropdownMenuLabel,
85
115
  DropdownMenuSeparator,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client'\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport type { LucideIcon } from 'lucide-react'\nimport type { ComponentProps } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/** Radix DropdownMenu root + trigger, re-exported as typed passthroughs. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nexport type DropdownMenuContentProps = ComponentProps<typeof DropdownMenuPrimitive.Content>\n\n/**\n * A menu surface.\n *\n * A menu is a list of ACTIONS. If the items navigate somewhere, they belong in\n * a nav; if they set a value, that is a `Select` or a `RadioGroup` — Radix has\n * menu variants for both, and a plain item pretending to be a choice loses the\n * checked state a screen reader needs.\n *\n * @example\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild><Button variant=\"secondary\">Menu</Button></DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuLabel>Account</DropdownMenuLabel>\n * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>\n * <DropdownMenuSeparator />\n * <DropdownMenuItem icon={LogOut}>Sign out</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n */\nexport function DropdownMenuContent({\n className,\n sideOffset = 6,\n children,\n ...rest\n}: DropdownMenuContentProps) {\n const container = useOverlayContainer()\n\n return (\n <DropdownMenuPrimitive.Portal container={container ?? undefined}>\n <DropdownMenuPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) min-w-44 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-1.5 panel-blur',\n 'data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)',\n className,\n )}\n {...rest}\n >\n {children}\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n )\n}\n\nexport interface DropdownMenuItemProps extends ComponentProps<typeof DropdownMenuPrimitive.Item> {\n /** Optional leading icon, rendered before the label. */\n icon?: LucideIcon\n /** Paints the row as destructive. Use for delete, revoke, disconnect. */\n destructive?: boolean\n}\n\n/**\n * A menu row.\n *\n * Highlight is driven by Radix's `data-highlighted`, which covers both pointer\n * hover and keyboard focus — styling `:hover` alone leaves the keyboard user\n * unable to see where they are.\n */\nexport function DropdownMenuItem({\n icon: Icon,\n destructive = false,\n className,\n children,\n ...rest\n}: DropdownMenuItemProps) {\n return (\n <DropdownMenuPrimitive.Item\n className={cn(\n 'flex cursor-pointer items-center gap-2.5 rounded-(--radius-row) px-2.5 py-2 text-sm outline-none transition-colors duration-(--duration-fast) data-[highlighted]:bg-(--stone) data-[disabled]:pointer-events-none data-[disabled]:opacity-(--disabled-opacity)',\n destructive ? 'text-(--danger)' : 'text-(--ink-2) data-[highlighted]:text-(--ink)',\n className,\n )}\n {...rest}\n >\n {Icon && <Icon size={16} strokeWidth={1.5} className=\"shrink-0\" aria-hidden />}\n {children}\n </DropdownMenuPrimitive.Item>\n )\n}\n\n/** Hairline divider between menu groups. */\nexport function DropdownMenuSeparator({\n className,\n ...rest\n}: ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n className={cn('my-1 h-px bg-(--rule)', className)}\n {...rest}\n />\n )\n}\n\n/** Mono eyebrow heading for a group of items. */\nexport function DropdownMenuLabel({\n className,\n ...rest\n}: ComponentProps<typeof DropdownMenuPrimitive.Label>) {\n return (\n <DropdownMenuPrimitive.Label\n className={cn('px-2.5 py-1.5 eyebrow text-(--ink-3-aa)', className)}\n {...rest}\n />\n )\n}\n\nexport default DropdownMenu\n"],"mappings":";AA2CM,cAwCF,YAxCE;AAzCN,YAAY,2BAA2B;AAGvC,SAAS,UAAU;AACnB,SAAS,2BAA2B;AAG7B,MAAM,eAAe,sBAAsB;AAC3C,MAAM,sBAAsB,sBAAsB;AAuBlD,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAA6B;AAC3B,QAAM,YAAY,oBAAoB;AAEtC,SACE,oBAAC,sBAAsB,QAAtB,EAA6B,WAAW,aAAa,QACpD;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,mBAAmB,aAAa;AAAA,MAChC,kBAAkB;AAAA,MAClB;AAAA,MACA,qBAAiB;AAAA,MACjB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH,GACF;AAEJ;AAgBO,SAAS,iBAAiB;AAAA,EAC/B,MAAM;AAAA,EACN,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA0B;AACxB,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,cAAc,oBAAoB;AAAA,QAClC;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA,gBAAQ,oBAAC,QAAK,MAAM,IAAI,aAAa,KAAK,WAAU,YAAW,eAAW,MAAC;AAAA,QAC3E;AAAA;AAAA;AAAA,EACH;AAEJ;AAGO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,GAAG;AACL,GAA2D;AACzD,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW,GAAG,yBAAyB,SAAS;AAAA,MAC/C,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,GAAG;AACL,GAAuD;AACrD,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA;AAAA,EACN;AAEJ;AAEA,IAAO,uBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/DropdownMenu/DropdownMenu.tsx"],"sourcesContent":["'use client'\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport type { LucideIcon } from 'lucide-react'\nimport { isValidElement, useId, type ComponentProps, type ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\nimport { useOverlayContainer } from '../../lib/overlay-container'\n\n/**\n * True for a component type — `icon={Settings}` — rather than a rendered element.\n *\n * Everything a `ReactNode` can be is an element, a primitive, an array, another\n * iterable or a promise; a Lucide icon is none of those, it is a `forwardRef`\n * object. So both spellings are tellable apart at runtime, which is what lets\n * one prop take either — and it has to, because this prop meant the opposite\n * thing one import away and the wrong spelling failed at render, not at the\n * type.\n */\nfunction isIconComponent(icon: LucideIcon | ReactNode): icon is LucideIcon {\n if (isValidElement(icon)) return false\n if (typeof icon === 'function') return true\n if (typeof icon !== 'object' || icon === null) return false\n return !Array.isArray(icon) && !(Symbol.iterator in icon) && !('then' in icon)\n}\n\n/** The leading glyph, sized by this component when it was handed a component. */\nfunction iconNode(icon: LucideIcon | ReactNode): ReactNode {\n if (icon === undefined || icon === null || icon === false) return null\n if (!isIconComponent(icon)) {\n return (\n <span aria-hidden className=\"grid size-4 shrink-0 place-items-center [&_svg]:size-4\">\n {icon}\n </span>\n )\n }\n const Icon = icon\n return <Icon size={16} strokeWidth={1.5} className=\"shrink-0\" aria-hidden />\n}\n\n/** Radix DropdownMenu root + trigger, re-exported as typed passthroughs. */\nexport const DropdownMenu = DropdownMenuPrimitive.Root\nexport const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nexport type DropdownMenuContentProps = ComponentProps<typeof DropdownMenuPrimitive.Content>\n\n/**\n * A menu surface.\n *\n * A menu is a list of ACTIONS. If the items navigate somewhere, they belong in\n * a nav; if they set a value, that is a `Select` or a `RadioGroup` — this\n * package ships no checkbox or radio menu item, and a plain item pretending to\n * be a choice loses the checked state a screen reader needs.\n *\n * @example\n * <DropdownMenu>\n * <DropdownMenuTrigger asChild><Button variant=\"secondary\">Menu</Button></DropdownMenuTrigger>\n * <DropdownMenuContent>\n * <DropdownMenuGroup label=\"Account\">\n * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>\n * </DropdownMenuGroup>\n * <DropdownMenuSeparator />\n * <DropdownMenuItem icon={LogOut}>Sign out</DropdownMenuItem>\n * </DropdownMenuContent>\n * </DropdownMenu>\n */\nexport function DropdownMenuContent({\n className,\n sideOffset = 6,\n children,\n ...rest\n}: DropdownMenuContentProps) {\n const container = useOverlayContainer()\n\n return (\n <DropdownMenuPrimitive.Portal container={container ?? undefined}>\n <DropdownMenuPrimitive.Content\n collisionBoundary={container ?? undefined}\n collisionPadding={8}\n sideOffset={sideOffset}\n data-m22-animated\n className={cn(\n 'z-(--z-dropdown) min-w-44 rounded-(--radius-lg) border border-(--panel-border) bg-(--panel-bg) p-1.5 shadow-(--panel-lift) panel-blur',\n 'data-[state=open]:animate-[m22-pop-in_var(--duration-fast)_var(--ease-out-expo)] data-[state=closed]:animate-[m22-pop-out_var(--duration-fast)_var(--ease)] origin-(--radix-popper-transform-origin)',\n className,\n )}\n {...rest}\n >\n {children}\n </DropdownMenuPrimitive.Content>\n </DropdownMenuPrimitive.Portal>\n )\n}\n\nexport interface DropdownMenuItemProps extends ComponentProps<typeof DropdownMenuPrimitive.Item> {\n /**\n * Optional leading icon, rendered before the label.\n *\n * Either spelling: `icon={Settings}` passes the component and this sizes it,\n * `icon={<Settings size={16} />}` passes the element and this places it. The\n * two used to mean opposite things one import apart — `CommandItem.icon` took\n * the element while this took the component — and the wrong one did not fail\n * a type check into anything actionable, it failed at render.\n */\n icon?: LucideIcon | ReactNode\n /** Paints the row as destructive. Use for delete, revoke, disconnect. */\n destructive?: boolean\n}\n\n/**\n * A menu row.\n *\n * Highlight is driven by Radix's `data-highlighted`, which covers both pointer\n * hover and keyboard focus — styling `:hover` alone leaves the keyboard user\n * unable to see where they are.\n */\nexport function DropdownMenuItem({\n icon,\n destructive = false,\n className,\n children,\n ...rest\n}: DropdownMenuItemProps) {\n return (\n <DropdownMenuPrimitive.Item\n className={cn(\n 'flex cursor-pointer items-center gap-2.5 rounded-(--radius-row) px-2.5 py-2 text-sm outline-none transition-colors duration-(--duration-fast) data-[highlighted]:bg-(--stone) data-[disabled]:pointer-events-none data-[disabled]:opacity-(--disabled-opacity)',\n destructive ? 'text-(--danger)' : 'text-(--ink-2) data-[highlighted]:text-(--ink)',\n className,\n )}\n {...rest}\n >\n {iconNode(icon)}\n {children}\n </DropdownMenuPrimitive.Item>\n )\n}\n\n/** Hairline divider between menu groups. */\nexport function DropdownMenuSeparator({\n className,\n ...rest\n}: ComponentProps<typeof DropdownMenuPrimitive.Separator>) {\n return (\n <DropdownMenuPrimitive.Separator\n className={cn('my-1 h-px bg-(--rule)', className)}\n {...rest}\n />\n )\n}\n\n/**\n * Mono eyebrow heading, on its own.\n *\n * Visual only: Radix renders it as a bare `<div>` with no role, so it segments\n * the menu for a reader who can see it and for nobody else. Reach for\n * `DropdownMenuGroup` when the eyebrow is a HEADING over rows; this is right\n * for a line that heads nothing — the signed-in address at the top of an\n * account menu.\n */\nexport function DropdownMenuLabel({\n className,\n ...rest\n}: ComponentProps<typeof DropdownMenuPrimitive.Label>) {\n return (\n <DropdownMenuPrimitive.Label\n className={cn('px-2.5 py-1.5 eyebrow text-(--ink-3-aa)', className)}\n {...rest}\n />\n )\n}\n\nexport interface DropdownMenuGroupProps\n extends ComponentProps<typeof DropdownMenuPrimitive.Group> {\n /** The eyebrow over the rows, and the group's accessible name. */\n label?: ReactNode\n}\n\n/**\n * A named section of a menu.\n *\n * The eyebrow alone was a picture of a heading. Radix's `MenuLabel` carries no\n * role and no `aria-labelledby` wiring, and `MenuGroup` — which does carry\n * `role=\"group\"` — was not re-exported by this package at all, so a sighted\n * reader saw three labelled sections and a screen-reader user got one\n * undifferentiated list. This renders the group, renders the label inside it,\n * and points the one at the other, which is the whole of the fix and not\n * something a caller should have to remember.\n *\n * @example\n * <DropdownMenuGroup label=\"Account\">\n * <DropdownMenuItem icon={Settings}>Settings</DropdownMenuItem>\n * </DropdownMenuGroup>\n */\nexport function DropdownMenuGroup({ label, children, ...rest }: DropdownMenuGroupProps) {\n const id = useId()\n\n return (\n <DropdownMenuPrimitive.Group\n aria-labelledby={label === undefined ? undefined : id}\n {...rest}\n >\n {label !== undefined && <DropdownMenuLabel id={id}>{label}</DropdownMenuLabel>}\n {children}\n </DropdownMenuPrimitive.Group>\n )\n}\n\nexport default DropdownMenu\n"],"mappings":";AA8BM,cA6FF,YA7FE;AA5BN,YAAY,2BAA2B;AAEvC,SAAS,gBAAgB,aAAkD;AAC3E,SAAS,UAAU;AACnB,SAAS,2BAA2B;AAYpC,SAAS,gBAAgB,MAAkD;AACzE,MAAI,eAAe,IAAI,EAAG,QAAO;AACjC,MAAI,OAAO,SAAS,WAAY,QAAO;AACvC,MAAI,OAAO,SAAS,YAAY,SAAS,KAAM,QAAO;AACtD,SAAO,CAAC,MAAM,QAAQ,IAAI,KAAK,EAAE,OAAO,YAAY,SAAS,EAAE,UAAU;AAC3E;AAGA,SAAS,SAAS,MAAyC;AACzD,MAAI,SAAS,UAAa,SAAS,QAAQ,SAAS,MAAO,QAAO;AAClE,MAAI,CAAC,gBAAgB,IAAI,GAAG;AAC1B,WACE,oBAAC,UAAK,eAAW,MAAC,WAAU,0DACzB,gBACH;AAAA,EAEJ;AACA,QAAM,OAAO;AACb,SAAO,oBAAC,QAAK,MAAM,IAAI,aAAa,KAAK,WAAU,YAAW,eAAW,MAAC;AAC5E;AAGO,MAAM,eAAe,sBAAsB;AAC3C,MAAM,sBAAsB,sBAAsB;AAwBlD,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,GAAG;AACL,GAA6B;AAC3B,QAAM,YAAY,oBAAoB;AAEtC,SACE,oBAAC,sBAAsB,QAAtB,EAA6B,WAAW,aAAa,QACpD;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,mBAAmB,aAAa;AAAA,MAChC,kBAAkB;AAAA,MAClB;AAAA,MACA,qBAAiB;AAAA,MACjB,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,EACH,GACF;AAEJ;AAwBO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,cAAc;AAAA,EACd;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAA0B;AACxB,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,cAAc,oBAAoB;AAAA,QAClC;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA,iBAAS,IAAI;AAAA,QACb;AAAA;AAAA;AAAA,EACH;AAEJ;AAGO,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,GAAG;AACL,GAA2D;AACzD,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW,GAAG,yBAAyB,SAAS;AAAA,MAC/C,GAAG;AAAA;AAAA,EACN;AAEJ;AAWO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA,GAAG;AACL,GAAuD;AACrD,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,WAAW,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA;AAAA,EACN;AAEJ;AAwBO,SAAS,kBAAkB,EAAE,OAAO,UAAU,GAAG,KAAK,GAA2B;AACtF,QAAM,KAAK,MAAM;AAEjB,SACE;AAAA,IAAC,sBAAsB;AAAA,IAAtB;AAAA,MACC,mBAAiB,UAAU,SAAY,SAAY;AAAA,MAClD,GAAG;AAAA,MAEH;AAAA,kBAAU,UAAa,oBAAC,qBAAkB,IAAS,iBAAM;AAAA,QACzD;AAAA;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,uBAAQ;","names":[]}
@@ -1,6 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { HTMLAttributes, ReactNode } from 'react';
3
3
  import { LucideIcon } from 'lucide-react';
4
+ import { HeadingLevel } from '../Heading/Heading.js';
4
5
 
5
6
  interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
6
7
  /** Optional lucide icon, shown muted inside a quiet circle. */
@@ -9,6 +10,26 @@ interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>
9
10
  description?: ReactNode;
10
11
  /** The one thing to do next. An empty state without an action is a dead end. */
11
12
  action?: ReactNode;
13
+ /**
14
+ * The heading level `title` opens, in the document the empty state lands in.
15
+ *
16
+ * Defaults to `2`, which is the placement this component is sized for: it
17
+ * stands in for a whole view inside a page that already has an `h1`, so the
18
+ * level below that one is the level that does not leave a hole in heading
19
+ * navigation. Under a section that already has its own `h2`, pass `3`.
20
+ *
21
+ * The default was `3` and fixed, which was wrong in the ordinary case and
22
+ * impossible to correct — the documentation could name the rule but a caller
23
+ * had no prop to follow it with. `2` is the common case rather than a
24
+ * compromise, and it is optional rather than required because the correct
25
+ * placement has one answer often enough that making every existing call site
26
+ * restate it would buy nothing.
27
+ *
28
+ * The size does not follow the level. `title` renders at `--fs-sub` at every
29
+ * level, because moving a state down the outline is a fact about the document
30
+ * and not a request for smaller type.
31
+ */
32
+ level?: HeadingLevel;
12
33
  }
13
34
  /**
14
35
  * A collection with nothing in it — yet.
@@ -25,7 +46,10 @@ interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'>
25
46
  * description="Create your first project to get started."
26
47
  * action={<Button>New project</Button>}
27
48
  * />
49
+ * @example
50
+ * // Inside a section that already has its own heading.
51
+ * <EmptyState level={3} title="No invoices yet" />
28
52
  */
29
- declare function EmptyState({ icon: Icon, title, description, action, className, ...rest }: EmptyStateProps): react.JSX.Element;
53
+ declare function EmptyState({ icon: Icon, title, description, action, level, className, ...rest }: EmptyStateProps): react.JSX.Element;
30
54
 
31
55
  export { EmptyState, type EmptyStateProps, EmptyState as default };
@@ -1,10 +1,12 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Heading } from "../Heading/Heading.js";
2
3
  import { cn } from "../../lib/cn.js";
3
4
  function EmptyState({
4
5
  icon: Icon,
5
6
  title,
6
7
  description,
7
8
  action,
9
+ level = 2,
8
10
  className,
9
11
  ...rest
10
12
  }) {
@@ -15,7 +17,7 @@ function EmptyState({
15
17
  ...rest,
16
18
  children: [
17
19
  Icon && /* @__PURE__ */ jsx("span", { className: "mb-6 flex size-14 items-center justify-center rounded-(--radius-pill) bg-(--stone) text-(--ink-3-aa)", children: /* @__PURE__ */ jsx(Icon, { size: 24, strokeWidth: 1.5, "aria-hidden": true }) }),
18
- /* @__PURE__ */ jsx("h3", { className: "m-0 font-heading text-[length:var(--fs-sub)] font-normal text-(--ink)", children: title }),
20
+ /* @__PURE__ */ jsx(Heading, { level, size: "sub", children: title }),
19
21
  description && /* @__PURE__ */ jsx("p", { className: "m-0 mt-2 max-w-sm text-sm leading-relaxed text-(--ink-3-aa)", children: description }),
20
22
  action && /* @__PURE__ */ jsx("div", { className: "mt-8", children: action })
21
23
  ]
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react'\nimport type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Optional lucide icon, shown muted inside a quiet circle. */\n icon?: LucideIcon\n title: ReactNode\n description?: ReactNode\n /** The one thing to do next. An empty state without an action is a dead end. */\n action?: ReactNode\n}\n\n/**\n * A collection with nothing in it — yet.\n *\n * Distinct from `ErrorState`: nothing went wrong here, so the copy says what to\n * do rather than what failed. The two are different components because the\n * shared temptation — one component with a `variant` — produces error pages\n * that read like empty folders.\n *\n * @example\n * <EmptyState\n * icon={Inbox}\n * title=\"No projects yet\"\n * description=\"Create your first project to get started.\"\n * action={<Button>New project</Button>}\n * />\n */\nexport function EmptyState({\n icon: Icon,\n title,\n description,\n action,\n className,\n ...rest\n}: EmptyStateProps) {\n return (\n <div\n className={cn('flex flex-col items-center px-(--page-pad) py-20 text-center', className)}\n {...rest}\n >\n {Icon && (\n <span className=\"mb-6 flex size-14 items-center justify-center rounded-(--radius-pill) bg-(--stone) text-(--ink-3-aa)\">\n <Icon size={24} strokeWidth={1.5} aria-hidden />\n </span>\n )}\n <h3 className=\"m-0 font-heading text-[length:var(--fs-sub)] font-normal text-(--ink)\">\n {title}\n </h3>\n {description && (\n <p className=\"m-0 mt-2 max-w-sm text-sm leading-relaxed text-(--ink-3-aa)\">{description}</p>\n )}\n {action && <div className=\"mt-8\">{action}</div>}\n </div>\n )\n}\n\nexport default EmptyState\n"],"mappings":"AAsCI,SAMM,KANN;AApCJ,SAAS,UAAU;AA2BZ,SAAS,WAAW;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,gEAAgE,SAAS;AAAA,MACtF,GAAG;AAAA,MAEH;AAAA,gBACC,oBAAC,UAAK,WAAU,wGACd,8BAAC,QAAK,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC,GAChD;AAAA,QAEF,oBAAC,QAAG,WAAU,yEACX,iBACH;AAAA,QACC,eACC,oBAAC,OAAE,WAAU,+DAA+D,uBAAY;AAAA,QAEzF,UAAU,oBAAC,SAAI,WAAU,QAAQ,kBAAO;AAAA;AAAA;AAAA,EAC3C;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/EmptyState/EmptyState.tsx"],"sourcesContent":["import type { LucideIcon } from 'lucide-react'\nimport type { HTMLAttributes, ReactNode } from 'react'\nimport { Heading, type HeadingLevel } from '../Heading/Heading'\nimport { cn } from '../../lib/cn'\n\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n /** Optional lucide icon, shown muted inside a quiet circle. */\n icon?: LucideIcon\n title: ReactNode\n description?: ReactNode\n /** The one thing to do next. An empty state without an action is a dead end. */\n action?: ReactNode\n /**\n * The heading level `title` opens, in the document the empty state lands in.\n *\n * Defaults to `2`, which is the placement this component is sized for: it\n * stands in for a whole view inside a page that already has an `h1`, so the\n * level below that one is the level that does not leave a hole in heading\n * navigation. Under a section that already has its own `h2`, pass `3`.\n *\n * The default was `3` and fixed, which was wrong in the ordinary case and\n * impossible to correct — the documentation could name the rule but a caller\n * had no prop to follow it with. `2` is the common case rather than a\n * compromise, and it is optional rather than required because the correct\n * placement has one answer often enough that making every existing call site\n * restate it would buy nothing.\n *\n * The size does not follow the level. `title` renders at `--fs-sub` at every\n * level, because moving a state down the outline is a fact about the document\n * and not a request for smaller type.\n */\n level?: HeadingLevel\n}\n\n/**\n * A collection with nothing in it — yet.\n *\n * Distinct from `ErrorState`: nothing went wrong here, so the copy says what to\n * do rather than what failed. The two are different components because the\n * shared temptation — one component with a `variant` — produces error pages\n * that read like empty folders.\n *\n * @example\n * <EmptyState\n * icon={Inbox}\n * title=\"No projects yet\"\n * description=\"Create your first project to get started.\"\n * action={<Button>New project</Button>}\n * />\n * @example\n * // Inside a section that already has its own heading.\n * <EmptyState level={3} title=\"No invoices yet\" />\n */\nexport function EmptyState({\n icon: Icon,\n title,\n description,\n action,\n level = 2,\n className,\n ...rest\n}: EmptyStateProps) {\n return (\n <div\n className={cn('flex flex-col items-center px-(--page-pad) py-20 text-center', className)}\n {...rest}\n >\n {Icon && (\n <span className=\"mb-6 flex size-14 items-center justify-center rounded-(--radius-pill) bg-(--stone) text-(--ink-3-aa)\">\n <Icon size={24} strokeWidth={1.5} aria-hidden />\n </span>\n )}\n <Heading level={level} size=\"sub\">\n {title}\n </Heading>\n {description && (\n <p className=\"m-0 mt-2 max-w-sm text-sm leading-relaxed text-(--ink-3-aa)\">{description}</p>\n )}\n {action && <div className=\"mt-8\">{action}</div>}\n </div>\n )\n}\n\nexport default EmptyState\n"],"mappings":"AA+DI,SAMM,KANN;AA7DJ,SAAS,eAAkC;AAC3C,SAAS,UAAU;AAkDZ,SAAS,WAAW;AAAA,EACzB,MAAM;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,gEAAgE,SAAS;AAAA,MACtF,GAAG;AAAA,MAEH;AAAA,gBACC,oBAAC,UAAK,WAAU,wGACd,8BAAC,QAAK,MAAM,IAAI,aAAa,KAAK,eAAW,MAAC,GAChD;AAAA,QAEF,oBAAC,WAAQ,OAAc,MAAK,OACzB,iBACH;AAAA,QACC,eACC,oBAAC,OAAE,WAAU,+DAA+D,uBAAY;AAAA,QAEzF,UAAU,oBAAC,SAAI,WAAU,QAAQ,kBAAO;AAAA;AAAA;AAAA,EAC3C;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
@@ -1,5 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { HTMLAttributes, ReactNode } from 'react';
3
+ import { HeadingLevel } from '../Heading/Heading.js';
3
4
 
4
5
  interface ErrorStateProps extends HTMLAttributes<HTMLElement> {
5
6
  /** The status, set large — "404", "500". Decorative; the heading carries the meaning. */
@@ -8,6 +9,23 @@ interface ErrorStateProps extends HTMLAttributes<HTMLElement> {
8
9
  message: ReactNode;
9
10
  /** The way back. Render it with {@link ERROR_ACTION_CLASS}. */
10
11
  action: ReactNode;
12
+ /**
13
+ * The heading level `heading` opens, in the document the error state lands in.
14
+ *
15
+ * Defaults to `1`, and that is not a compromise: this component replaces the
16
+ * page rather than sitting inside one — its own ground, its own viewport, its
17
+ * own top clearance — so the page's single `h1` is the one it renders. Kept
18
+ * as the default, existing call sites render exactly the markup they did.
19
+ *
20
+ * The prop exists because the level was previously fixed, and the one piece
21
+ * of advice this component's documentation gives about headings — do not put
22
+ * it inside a shell that already has an `h1` — was advice a caller had no way
23
+ * to take. Now they do: inside a shell that owns the page heading, pass `2`.
24
+ *
25
+ * The size does not follow the level. `heading` renders at `--fs-heading` at
26
+ * every level; a failure demoted in the outline is the same failure.
27
+ */
28
+ level?: HeadingLevel;
11
29
  }
12
30
  /**
13
31
  * The recovery affordance's look, exported so every error page offers the same
@@ -28,7 +46,10 @@ declare const ERROR_ACTION_CLASS = "text-sm text-(--ink) underline decoration-(-
28
46
  * message="The page you're looking for has moved, or never existed."
29
47
  * action={<a href="/" className={ERROR_ACTION_CLASS}>Back home</a>}
30
48
  * />
49
+ * @example
50
+ * // Inside a shell that already owns the page's h1.
51
+ * <ErrorState level={2} code="503" heading="Invoices could not be loaded" … />
31
52
  */
32
- declare function ErrorState({ code, heading, message, action, className, ...rest }: ErrorStateProps): react.JSX.Element;
53
+ declare function ErrorState({ code, heading, message, action, level, className, ...rest }: ErrorStateProps): react.JSX.Element;
33
54
 
34
55
  export { ERROR_ACTION_CLASS, ErrorState, type ErrorStateProps, ErrorState as default };
@@ -1,7 +1,16 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Heading } from "../Heading/Heading.js";
2
3
  import { cn } from "../../lib/cn.js";
3
4
  const ERROR_ACTION_CLASS = "text-sm text-(--ink) underline decoration-(--rule-2) underline-offset-4 transition-colors duration-(--duration-fast) hover:decoration-(--ink)";
4
- function ErrorState({ code, heading, message, action, className, ...rest }) {
5
+ function ErrorState({
6
+ code,
7
+ heading,
8
+ message,
9
+ action,
10
+ level = 1,
11
+ className,
12
+ ...rest
13
+ }) {
5
14
  return /* @__PURE__ */ jsx(
6
15
  "section",
7
16
  {
@@ -12,11 +21,11 @@ function ErrorState({ code, heading, message, action, className, ...rest }) {
12
21
  "p",
13
22
  {
14
23
  "aria-hidden": "true",
15
- className: "m-0 font-heading text-[length:var(--fs-title)] leading-none text-(--ink)",
24
+ className: "m-0 font-heading text-[length:var(--fs-title)] leading-tight text-(--ink)",
16
25
  children: code
17
26
  }
18
27
  ),
19
- /* @__PURE__ */ jsx("h1", { className: "mb-4 mt-6 font-heading text-[length:var(--fs-heading)] font-normal text-(--ink)", children: heading }),
28
+ /* @__PURE__ */ jsx(Heading, { level, size: "heading", className: "mb-4 mt-6", children: heading }),
20
29
  /* @__PURE__ */ jsx("p", { className: "mb-10 max-w-(--measure-record) text-base leading-relaxed text-(--ink-3-aa)", children: message }),
21
30
  action
22
31
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ErrorState/ErrorState.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { cn } from '../../lib/cn'\n\nexport interface ErrorStateProps extends HTMLAttributes<HTMLElement> {\n /** The status, set large — \"404\", \"500\". Decorative; the heading carries the meaning. */\n code: ReactNode\n heading: ReactNode\n message: ReactNode\n /** The way back. Render it with {@link ERROR_ACTION_CLASS}. */\n action: ReactNode\n}\n\n/**\n * The recovery affordance's look, exported so every error page offers the same\n * one rather than each inventing a link style.\n */\nexport const ERROR_ACTION_CLASS =\n 'text-sm text-(--ink) underline decoration-(--rule-2) underline-offset-4 transition-colors duration-(--duration-fast) hover:decoration-(--ink)'\n\n/**\n * A page that could not be shown.\n *\n * The code is set at the top of the type ladder and marked `aria-hidden` — read\n * aloud, \"404\" before the sentence explaining it is noise, and the heading\n * immediately after says the same thing in words.\n *\n * @example\n * <ErrorState\n * code=\"404\"\n * heading=\"Page not found\"\n * message=\"The page you're looking for has moved, or never existed.\"\n * action={<a href=\"/\" className={ERROR_ACTION_CLASS}>Back home</a>}\n * />\n */\nexport function ErrorState({ code, heading, message, action, className, ...rest }: ErrorStateProps) {\n return (\n <section\n className={cn('flex min-h-svh flex-col justify-center bg-(--paper) pt-24', className)}\n {...rest}\n >\n <div className=\"mx-auto w-full max-w-(--w-page) px-(--page-pad)\">\n <p\n aria-hidden=\"true\"\n className=\"m-0 font-heading text-[length:var(--fs-title)] leading-none text-(--ink)\"\n >\n {code}\n </p>\n <h1 className=\"mb-4 mt-6 font-heading text-[length:var(--fs-heading)] font-normal text-(--ink)\">\n {heading}\n </h1>\n <p className=\"mb-10 max-w-(--measure-record) text-base leading-relaxed text-(--ink-3-aa)\">\n {message}\n </p>\n {action}\n </div>\n </section>\n )\n}\n\nexport default ErrorState\n"],"mappings":"AAwCM,SACE,KADF;AAvCN,SAAS,UAAU;AAeZ,MAAM,qBACX;AAiBK,SAAS,WAAW,EAAE,MAAM,SAAS,SAAS,QAAQ,WAAW,GAAG,KAAK,GAAoB;AAClG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,6DAA6D,SAAS;AAAA,MACnF,GAAG;AAAA,MAEJ,+BAAC,SAAI,WAAU,mDACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAU;AAAA,YAET;AAAA;AAAA,QACH;AAAA,QACA,oBAAC,QAAG,WAAU,mFACX,mBACH;AAAA,QACA,oBAAC,OAAE,WAAU,8EACV,mBACH;AAAA,QACC;AAAA,SACH;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/ErrorState/ErrorState.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react'\nimport { Heading, type HeadingLevel } from '../Heading/Heading'\nimport { cn } from '../../lib/cn'\n\nexport interface ErrorStateProps extends HTMLAttributes<HTMLElement> {\n /** The status, set large — \"404\", \"500\". Decorative; the heading carries the meaning. */\n code: ReactNode\n heading: ReactNode\n message: ReactNode\n /** The way back. Render it with {@link ERROR_ACTION_CLASS}. */\n action: ReactNode\n /**\n * The heading level `heading` opens, in the document the error state lands in.\n *\n * Defaults to `1`, and that is not a compromise: this component replaces the\n * page rather than sitting inside one — its own ground, its own viewport, its\n * own top clearance — so the page's single `h1` is the one it renders. Kept\n * as the default, existing call sites render exactly the markup they did.\n *\n * The prop exists because the level was previously fixed, and the one piece\n * of advice this component's documentation gives about headings — do not put\n * it inside a shell that already has an `h1` — was advice a caller had no way\n * to take. Now they do: inside a shell that owns the page heading, pass `2`.\n *\n * The size does not follow the level. `heading` renders at `--fs-heading` at\n * every level; a failure demoted in the outline is the same failure.\n */\n level?: HeadingLevel\n}\n\n/**\n * The recovery affordance's look, exported so every error page offers the same\n * one rather than each inventing a link style.\n */\nexport const ERROR_ACTION_CLASS =\n 'text-sm text-(--ink) underline decoration-(--rule-2) underline-offset-4 transition-colors duration-(--duration-fast) hover:decoration-(--ink)'\n\n/**\n * A page that could not be shown.\n *\n * The code is set at the top of the type ladder and marked `aria-hidden` — read\n * aloud, \"404\" before the sentence explaining it is noise, and the heading\n * immediately after says the same thing in words.\n *\n * @example\n * <ErrorState\n * code=\"404\"\n * heading=\"Page not found\"\n * message=\"The page you're looking for has moved, or never existed.\"\n * action={<a href=\"/\" className={ERROR_ACTION_CLASS}>Back home</a>}\n * />\n * @example\n * // Inside a shell that already owns the page's h1.\n * <ErrorState level={2} code=\"503\" heading=\"Invoices could not be loaded\" … />\n */\nexport function ErrorState({\n code,\n heading,\n message,\n action,\n level = 1,\n className,\n ...rest\n}: ErrorStateProps) {\n return (\n <section\n className={cn('flex min-h-svh flex-col justify-center bg-(--paper) pt-24', className)}\n {...rest}\n >\n <div className=\"mx-auto w-full max-w-(--w-page) px-(--page-pad)\">\n {/* `leading-tight`, not `leading-none`. At the title step this face\n draws about 62px of ink, and a line box of exactly the font size is\n 47 — so the figures overflowed their own box by seven pixels at the\n top and seven at the bottom, pressing up against the eyebrow above\n and eating half the gap to the heading below. The box that says\n nothing is spaced from is the box the ink is actually in. */}\n <p\n aria-hidden=\"true\"\n className=\"m-0 font-heading text-[length:var(--fs-title)] leading-tight text-(--ink)\"\n >\n {code}\n </p>\n <Heading level={level} size=\"heading\" className=\"mb-4 mt-6\">\n {heading}\n </Heading>\n <p className=\"mb-10 max-w-(--measure-record) text-base leading-relaxed text-(--ink-3-aa)\">\n {message}\n </p>\n {action}\n </div>\n </section>\n )\n}\n\nexport default ErrorState\n"],"mappings":"AAqEM,SAOE,KAPF;AApEN,SAAS,eAAkC;AAC3C,SAAS,UAAU;AAgCZ,MAAM,qBACX;AAoBK,SAAS,WAAW;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA,GAAG;AACL,GAAoB;AAClB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,GAAG,6DAA6D,SAAS;AAAA,MACnF,GAAG;AAAA,MAEJ,+BAAC,SAAI,WAAU,mDAOb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAU;AAAA,YAET;AAAA;AAAA,QACH;AAAA,QACA,oBAAC,WAAQ,OAAc,MAAK,WAAU,WAAU,aAC7C,mBACH;AAAA,QACA,oBAAC,OAAE,WAAU,8EACV,mBACH;AAAA,QACC;AAAA,SACH;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,qBAAQ;","names":[]}
@@ -1,6 +1,18 @@
1
1
  import * as react from 'react';
2
2
  import { HTMLAttributes, ReactNode } from 'react';
3
3
 
4
+ /**
5
+ * Where the control sits relative to its label.
6
+ *
7
+ * `stacked` is the form row: label, control, message, down the page.
8
+ *
9
+ * `row` is the settings row: the label and its `description` in a column at the
10
+ * inline start, the control at the inline end, one rhythm down a settings
11
+ * screen. It is a layout, not a second component — the label wiring, the
12
+ * required marker and the message slot are the same three things either way,
13
+ * and a `SettingRow` beside this would be all three of them written twice.
14
+ */
15
+ type FieldLayout = 'stacked' | 'row';
4
16
  interface FieldProps extends HTMLAttributes<HTMLDivElement> {
5
17
  /** Visible label text; renders a `--danger` asterisk when `required`. */
6
18
  label?: ReactNode;
@@ -11,11 +23,23 @@ interface FieldProps extends HTMLAttributes<HTMLDivElement> {
11
23
  * — a form library referencing it by name, say.
12
24
  */
13
25
  htmlFor?: string;
26
+ /**
27
+ * A second line under the LABEL, explaining what the setting does.
28
+ *
29
+ * Distinct from `hint`, which sits under the control and belongs to the input
30
+ * — "We never share it". This belongs to the thing being switched on, and it
31
+ * is what makes a settings row a settings row. Both reach the control through
32
+ * `aria-describedby`, so a row that has a description and an error announces
33
+ * both.
34
+ */
35
+ description?: ReactNode;
14
36
  /** Helper copy shown below the control when there is no `error`. */
15
37
  hint?: ReactNode;
16
38
  /** Validation message; takes precedence over `hint` when present. */
17
39
  error?: ReactNode;
18
40
  required?: boolean;
41
+ /** Where the control sits relative to its label. See {@link FieldLayout}. */
42
+ layout?: FieldLayout;
19
43
  children: ReactNode;
20
44
  }
21
45
  /**
@@ -32,13 +56,56 @@ interface FieldProps extends HTMLAttributes<HTMLDivElement> {
32
56
  * reader. The id is now generated when it is not supplied.
33
57
  *
34
58
  * `hint` and `error` are one slot, not two stacked messages: when a field is
35
- * wrong, the thing to read is what is wrong with it.
59
+ * wrong, the thing to read is what is wrong with it. `description` is a
60
+ * different slot again — it explains the SETTING, not the input, and it is what
61
+ * `layout="row"` puts under the label to make a settings row.
62
+ *
63
+ * **How the wiring reaches the control.** `cloneElement` puts the four
64
+ * attributes on the single child, and each control forwards them to whatever
65
+ * element carries the role — which is the child itself for `Input`, `Textarea`,
66
+ * `NativeSelect`, `Checkbox`, `Switch` and any host element written by hand, and
67
+ * a trigger, a group or a thumb further down for `Select`, `Combobox`,
68
+ * `DatePicker`, `Slider`, `RadioGroup` and `ToggleGroup`. The composites used to
69
+ * drop them on the floor, which drew a hint under a control that never announced
70
+ * it; a wrapper that appears to wire things up and does not is worse than one
71
+ * that never claimed to.
72
+ *
73
+ * The label's own id travels separately, through context, because a name is the
74
+ * one thing a prop cannot carry: a trigger whose text is its VALUE is named by
75
+ * the label AND by itself, so `<Field label="Region"><Select/></Field>`
76
+ * announces "Region, Australia" rather than either half.
77
+ *
78
+ * Three things stay out of reach, and each of them is the control's own markup
79
+ * rather than a gap in this wiring. A `<label for>` binds only to a labellable
80
+ * element, so the words do not click through to a `RadioGroup`, a `ToggleGroup`
81
+ * or a `Slider`: the first two are a `role="radiogroup"` named by pointing back
82
+ * at the label instead, exactly as a `<legend>` is, and the third carries
83
+ * `role="slider"` on a thumb below a roleless root. `required` reaches a control
84
+ * as `aria-required`, which `DatePicker`'s plain `<button>` trigger and a
85
+ * multiple-value `ToggleGroup`'s `role="toolbar"` have nowhere to put; there the
86
+ * asterisk is the only marker. And `aria-invalid` reaches `Slider`'s root rather
87
+ * than its thumb, so an errored slider is drawn wrong without being announced
88
+ * wrong.
89
+ *
90
+ * Each composite still takes its own `label` prop — that is what names it
91
+ * standing outside a field, and `Select`, `Combobox` and `DatePicker` warn when
92
+ * it is blank. It is no longer used INSTEAD of this one's.
93
+ *
94
+ * What no wiring can reach, the field says out loud in development rather than
95
+ * failing silently: `FIELD_CONTROL_NOT_LABELLABLE` when the child is a host
96
+ * element a label cannot bind to — the `<div>` wrapper that takes the id and
97
+ * leaves the control inside it with nothing — and `FIELD_CONTROL_NOT_WIRED`
98
+ * when there is no single element to wire at all.
36
99
  *
37
100
  * @example
38
101
  * <Field label="Email" required hint="We never share it."><Input type="email" /></Field>
39
102
  * @example
40
103
  * <Field label="Name" error="Name is required."><Input /></Field>
104
+ * @example
105
+ * <Field layout="row" label="Email notifications" description="A digest every Monday.">
106
+ * <Switch defaultChecked />
107
+ * </Field>
41
108
  */
42
- declare function Field({ label, htmlFor, hint, error, required, children, className, ...rest }: FieldProps): react.JSX.Element;
109
+ declare function Field({ label, htmlFor, description, hint, error, required, layout, children, className, ...rest }: FieldProps): react.JSX.Element;
43
110
 
44
- export { Field, type FieldProps, Field as default };
111
+ export { Field, type FieldLayout, type FieldProps, Field as default };