@nanisoft/prism-ui 0.10.1 → 0.13.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 (334) hide show
  1. package/LICENSE +21 -21
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/blocks/app-shell-01/app-shell.js +4 -4
  4. package/dist/blocks/app-shell-01/index.d.ts +2 -2
  5. package/dist/blocks/app-shell-01/index.js +1 -1
  6. package/dist/blocks/auth-form-01/auth-form.d.ts +11 -1
  7. package/dist/blocks/auth-form-01/auth-form.d.ts.map +1 -1
  8. package/dist/blocks/auth-form-01/auth-form.js +11 -8
  9. package/dist/blocks/auth-form-01/index.d.ts +2 -2
  10. package/dist/blocks/auth-form-01/index.js +1 -1
  11. package/dist/blocks/cta-01/cta.d.ts +26 -21
  12. package/dist/blocks/cta-01/cta.d.ts.map +1 -1
  13. package/dist/blocks/cta-01/cta.js +2 -2
  14. package/dist/blocks/cta-01/index.d.ts +2 -2
  15. package/dist/blocks/cta-01/index.js +1 -1
  16. package/dist/blocks/data-table-01/data-table.js +7 -7
  17. package/dist/blocks/data-table-01/index.d.ts +2 -2
  18. package/dist/blocks/data-table-01/index.js +1 -1
  19. package/dist/blocks/empty-state-01/empty-state.d.ts +143 -0
  20. package/dist/blocks/empty-state-01/empty-state.d.ts.map +1 -0
  21. package/dist/blocks/empty-state-01/empty-state.js +104 -0
  22. package/dist/blocks/empty-state-01/index.d.ts +3 -0
  23. package/dist/blocks/empty-state-01/index.d.ts.map +1 -0
  24. package/dist/blocks/empty-state-01/index.js +1 -0
  25. package/dist/blocks/feature-grid-01/feature-grid.d.ts +28 -1
  26. package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
  27. package/dist/blocks/feature-grid-01/feature-grid.js +34 -3
  28. package/dist/blocks/feature-grid-01/index.d.ts +2 -2
  29. package/dist/blocks/feature-grid-01/index.js +1 -1
  30. package/dist/blocks/hero-01/hero.d.ts +49 -17
  31. package/dist/blocks/hero-01/hero.d.ts.map +1 -1
  32. package/dist/blocks/hero-01/hero.js +14 -9
  33. package/dist/blocks/hero-01/index.d.ts +2 -1
  34. package/dist/blocks/hero-01/index.d.ts.map +1 -1
  35. package/dist/blocks/hero-01/index.js +1 -1
  36. package/dist/blocks/index.d.ts +20 -20
  37. package/dist/blocks/index.js +19 -19
  38. package/dist/blocks/instrument-panel-01/index.d.ts +2 -2
  39. package/dist/blocks/instrument-panel-01/index.js +1 -1
  40. package/dist/blocks/instrument-panel-01/instrument-panel.js +1 -1
  41. package/dist/blocks/logo-strip-01/index.d.ts +2 -2
  42. package/dist/blocks/logo-strip-01/index.js +1 -1
  43. package/dist/blocks/logo-strip-01/logo-strip.d.ts +1 -1
  44. package/dist/blocks/logo-strip-01/logo-strip.js +2 -2
  45. package/dist/blocks/note-grid-01/index.d.ts +2 -2
  46. package/dist/blocks/note-grid-01/index.js +1 -1
  47. package/dist/blocks/note-grid-01/note-grid.d.ts +1 -1
  48. package/dist/blocks/note-grid-01/note-grid.js +1 -1
  49. package/dist/blocks/page-header-01/index.d.ts +2 -2
  50. package/dist/blocks/page-header-01/index.js +1 -1
  51. package/dist/blocks/page-header-01/page-header.d.ts +1 -1
  52. package/dist/blocks/page-header-01/page-header.js +4 -4
  53. package/dist/blocks/pricing-01/index.d.ts +1 -1
  54. package/dist/blocks/pricing-01/index.js +1 -1
  55. package/dist/blocks/pricing-01/pricing.d.ts +8 -1
  56. package/dist/blocks/pricing-01/pricing.d.ts.map +1 -1
  57. package/dist/blocks/pricing-01/pricing.js +15 -5
  58. package/dist/blocks/process-flow-01/index.d.ts +3 -0
  59. package/dist/blocks/process-flow-01/index.d.ts.map +1 -0
  60. package/dist/blocks/process-flow-01/index.js +1 -0
  61. package/dist/blocks/process-flow-01/process-flow.d.ts +118 -0
  62. package/dist/blocks/process-flow-01/process-flow.d.ts.map +1 -0
  63. package/dist/blocks/process-flow-01/process-flow.js +71 -0
  64. package/dist/blocks/process-rail-01/index.d.ts +2 -2
  65. package/dist/blocks/process-rail-01/index.js +1 -1
  66. package/dist/blocks/process-rail-01/process-rail.d.ts +1 -1
  67. package/dist/blocks/process-rail-01/process-rail.js +2 -2
  68. package/dist/blocks/product-grid-01/index.d.ts +2 -2
  69. package/dist/blocks/product-grid-01/index.js +1 -1
  70. package/dist/blocks/product-grid-01/product-grid.d.ts +37 -5
  71. package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -1
  72. package/dist/blocks/product-grid-01/product-grid.js +20 -6
  73. package/dist/blocks/run-console-01/index.d.ts +3 -0
  74. package/dist/blocks/run-console-01/index.d.ts.map +1 -0
  75. package/dist/blocks/run-console-01/index.js +1 -0
  76. package/dist/blocks/run-console-01/run-console.d.ts +111 -0
  77. package/dist/blocks/run-console-01/run-console.d.ts.map +1 -0
  78. package/dist/blocks/run-console-01/run-console.js +48 -0
  79. package/dist/blocks/settings-panel-01/index.d.ts +2 -2
  80. package/dist/blocks/settings-panel-01/index.js +1 -1
  81. package/dist/blocks/settings-panel-01/settings-panel.d.ts +11 -1
  82. package/dist/blocks/settings-panel-01/settings-panel.d.ts.map +1 -1
  83. package/dist/blocks/settings-panel-01/settings-panel.js +15 -10
  84. package/dist/blocks/site-footer/index.d.ts +2 -2
  85. package/dist/blocks/site-footer/index.js +1 -1
  86. package/dist/blocks/site-footer/site-footer.d.ts +1 -1
  87. package/dist/blocks/site-footer/site-footer.js +2 -2
  88. package/dist/blocks/site-header/index.d.ts +2 -2
  89. package/dist/blocks/site-header/index.js +1 -1
  90. package/dist/blocks/site-header/site-header.d.ts +2 -2
  91. package/dist/blocks/site-header/site-header.js +3 -3
  92. package/dist/blocks/site-navbar/index.d.ts +3 -0
  93. package/dist/blocks/site-navbar/index.d.ts.map +1 -0
  94. package/dist/blocks/site-navbar/index.js +1 -0
  95. package/dist/blocks/site-navbar/mobile-nav.d.ts +48 -0
  96. package/dist/blocks/site-navbar/mobile-nav.d.ts.map +1 -0
  97. package/dist/blocks/site-navbar/mobile-nav.js +35 -0
  98. package/dist/blocks/site-navbar/mode-toggle.d.ts +39 -0
  99. package/dist/blocks/site-navbar/mode-toggle.d.ts.map +1 -0
  100. package/dist/blocks/site-navbar/mode-toggle.js +39 -0
  101. package/dist/blocks/site-navbar/navbar-controls.d.ts +79 -0
  102. package/dist/blocks/site-navbar/navbar-controls.d.ts.map +1 -0
  103. package/dist/blocks/site-navbar/navbar-controls.js +40 -0
  104. package/dist/blocks/site-navbar/search-entry.d.ts +29 -0
  105. package/dist/blocks/site-navbar/search-entry.d.ts.map +1 -0
  106. package/dist/blocks/site-navbar/search-entry.js +52 -0
  107. package/dist/blocks/site-navbar/site-navbar.d.ts +212 -0
  108. package/dist/blocks/site-navbar/site-navbar.d.ts.map +1 -0
  109. package/dist/blocks/site-navbar/site-navbar.js +61 -0
  110. package/dist/blocks/site-navbar/sites-menu.d.ts +40 -0
  111. package/dist/blocks/site-navbar/sites-menu.d.ts.map +1 -0
  112. package/dist/blocks/site-navbar/sites-menu.js +48 -0
  113. package/dist/blocks/site-navbar/theme-menu.d.ts +47 -0
  114. package/dist/blocks/site-navbar/theme-menu.d.ts.map +1 -0
  115. package/dist/blocks/site-navbar/theme-menu.js +55 -0
  116. package/dist/blocks/stack-grid-01/index.d.ts +2 -2
  117. package/dist/blocks/stack-grid-01/index.js +1 -1
  118. package/dist/blocks/stack-grid-01/stack-grid.d.ts +42 -11
  119. package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -1
  120. package/dist/blocks/stack-grid-01/stack-grid.js +15 -7
  121. package/dist/blocks/stats-01/index.d.ts +9 -1
  122. package/dist/blocks/stats-01/index.d.ts.map +1 -1
  123. package/dist/blocks/stats-01/index.js +8 -1
  124. package/dist/blocks/stats-01/stats.d.ts +1 -1
  125. package/dist/blocks/stats-01/stats.js +2 -2
  126. package/dist/blocks/status-ledger-01/index.d.ts +2 -2
  127. package/dist/blocks/status-ledger-01/index.js +1 -1
  128. package/dist/blocks/status-ledger-01/status-ledger.d.ts +1 -1
  129. package/dist/blocks/status-ledger-01/status-ledger.js +2 -2
  130. package/dist/catalog.d.ts +1 -1
  131. package/dist/catalog.d.ts.map +1 -1
  132. package/dist/catalog.js +473 -1
  133. package/dist/components/index.d.ts +104 -66
  134. package/dist/components/index.d.ts.map +1 -1
  135. package/dist/components/index.js +74 -40
  136. package/dist/components/ui/accordion.js +1 -1
  137. package/dist/components/ui/alert-dialog.d.ts +119 -0
  138. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  139. package/dist/components/ui/alert-dialog.js +82 -0
  140. package/dist/components/ui/alert.js +1 -1
  141. package/dist/components/ui/aspect-ratio.d.ts +60 -0
  142. package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
  143. package/dist/components/ui/aspect-ratio.js +61 -0
  144. package/dist/components/ui/avatar.js +1 -1
  145. package/dist/components/ui/badge.js +1 -1
  146. package/dist/components/ui/breadcrumb.js +1 -1
  147. package/dist/components/ui/button-group.d.ts +68 -0
  148. package/dist/components/ui/button-group.d.ts.map +1 -0
  149. package/dist/components/ui/button-group.js +54 -0
  150. package/dist/components/ui/button.js +1 -1
  151. package/dist/components/ui/calendar.d.ts +158 -0
  152. package/dist/components/ui/calendar.d.ts.map +1 -0
  153. package/dist/components/ui/calendar.js +216 -0
  154. package/dist/components/ui/card.d.ts +18 -6
  155. package/dist/components/ui/card.d.ts.map +1 -1
  156. package/dist/components/ui/card.js +23 -8
  157. package/dist/components/ui/carousel.d.ts +118 -0
  158. package/dist/components/ui/carousel.d.ts.map +1 -0
  159. package/dist/components/ui/carousel.js +152 -0
  160. package/dist/components/ui/chart-frame.d.ts +216 -0
  161. package/dist/components/ui/chart-frame.d.ts.map +1 -0
  162. package/dist/components/ui/chart-frame.js +286 -0
  163. package/dist/components/ui/checkbox.js +1 -1
  164. package/dist/components/ui/collapsible.d.ts +97 -0
  165. package/dist/components/ui/collapsible.d.ts.map +1 -0
  166. package/dist/components/ui/collapsible.js +54 -0
  167. package/dist/components/ui/combobox.d.ts +141 -0
  168. package/dist/components/ui/combobox.d.ts.map +1 -0
  169. package/dist/components/ui/combobox.js +243 -0
  170. package/dist/components/ui/command-palette.d.ts +106 -0
  171. package/dist/components/ui/command-palette.d.ts.map +1 -0
  172. package/dist/components/ui/command-palette.js +176 -0
  173. package/dist/components/ui/command.d.ts +82 -0
  174. package/dist/components/ui/command.d.ts.map +1 -0
  175. package/dist/components/ui/command.js +37 -0
  176. package/dist/components/ui/context-menu.d.ts +151 -0
  177. package/dist/components/ui/context-menu.d.ts.map +1 -0
  178. package/dist/components/ui/context-menu.js +97 -0
  179. package/dist/components/ui/cta-link.js +1 -1
  180. package/dist/components/ui/date-picker.d.ts +111 -0
  181. package/dist/components/ui/date-picker.d.ts.map +1 -0
  182. package/dist/components/ui/date-picker.js +74 -0
  183. package/dist/components/ui/diagram.d.ts +84 -15
  184. package/dist/components/ui/diagram.d.ts.map +1 -1
  185. package/dist/components/ui/diagram.js +77 -7
  186. package/dist/components/ui/dialog.js +1 -1
  187. package/dist/components/ui/diff.d.ts +105 -0
  188. package/dist/components/ui/diff.d.ts.map +1 -0
  189. package/dist/components/ui/diff.js +113 -0
  190. package/dist/components/ui/dropdown-menu.d.ts +18 -0
  191. package/dist/components/ui/dropdown-menu.d.ts.map +1 -1
  192. package/dist/components/ui/dropdown-menu.js +1 -1
  193. package/dist/components/ui/fact-list.js +1 -1
  194. package/dist/components/ui/field.js +1 -1
  195. package/dist/components/ui/form.d.ts +151 -0
  196. package/dist/components/ui/form.d.ts.map +1 -0
  197. package/dist/components/ui/form.js +73 -0
  198. package/dist/components/ui/hover-card.d.ts +105 -0
  199. package/dist/components/ui/hover-card.d.ts.map +1 -0
  200. package/dist/components/ui/hover-card.js +49 -0
  201. package/dist/components/ui/input-group.d.ts +99 -0
  202. package/dist/components/ui/input-group.d.ts.map +1 -0
  203. package/dist/components/ui/input-group.js +83 -0
  204. package/dist/components/ui/input.js +1 -1
  205. package/dist/components/ui/item.d.ts +113 -0
  206. package/dist/components/ui/item.d.ts.map +1 -0
  207. package/dist/components/ui/item.js +61 -0
  208. package/dist/components/ui/kbd.js +1 -1
  209. package/dist/components/ui/label.d.ts +58 -0
  210. package/dist/components/ui/label.d.ts.map +1 -0
  211. package/dist/components/ui/label.js +29 -0
  212. package/dist/components/ui/live-region.d.ts +9 -0
  213. package/dist/components/ui/live-region.d.ts.map +1 -1
  214. package/dist/components/ui/live-region.js +10 -2
  215. package/dist/components/ui/mark.js +1 -1
  216. package/dist/components/ui/menubar.d.ts +197 -0
  217. package/dist/components/ui/menubar.d.ts.map +1 -0
  218. package/dist/components/ui/menubar.js +109 -0
  219. package/dist/components/ui/meter.d.ts +121 -0
  220. package/dist/components/ui/meter.d.ts.map +1 -0
  221. package/dist/components/ui/meter.js +82 -0
  222. package/dist/components/ui/native-select.d.ts +72 -0
  223. package/dist/components/ui/native-select.d.ts.map +1 -0
  224. package/dist/components/ui/native-select.js +55 -0
  225. package/dist/components/ui/navigation-menu.d.ts +186 -0
  226. package/dist/components/ui/navigation-menu.d.ts.map +1 -0
  227. package/dist/components/ui/navigation-menu.js +94 -0
  228. package/dist/components/ui/number-field.d.ts +111 -0
  229. package/dist/components/ui/number-field.d.ts.map +1 -0
  230. package/dist/components/ui/number-field.js +84 -0
  231. package/dist/components/ui/one-time-code.d.ts +127 -0
  232. package/dist/components/ui/one-time-code.d.ts.map +1 -0
  233. package/dist/components/ui/one-time-code.js +57 -0
  234. package/dist/components/ui/pagination.js +1 -1
  235. package/dist/components/ui/popover.js +1 -1
  236. package/dist/components/ui/product-mark.d.ts +1 -1
  237. package/dist/components/ui/product-mark.js +1 -1
  238. package/dist/components/ui/product-switcher.d.ts +1 -1
  239. package/dist/components/ui/product-switcher.js +2 -2
  240. package/dist/components/ui/progress.js +1 -1
  241. package/dist/components/ui/prose.js +1 -1
  242. package/dist/components/ui/pulse-graph.js +1 -1
  243. package/dist/components/ui/pulse-series.js +1 -1
  244. package/dist/components/ui/radio-group.js +1 -1
  245. package/dist/components/ui/resizable.d.ts +129 -0
  246. package/dist/components/ui/resizable.d.ts.map +1 -0
  247. package/dist/components/ui/resizable.js +205 -0
  248. package/dist/components/ui/scroll-area.d.ts +97 -0
  249. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  250. package/dist/components/ui/scroll-area.js +68 -0
  251. package/dist/components/ui/search-dialog.d.ts +139 -0
  252. package/dist/components/ui/search-dialog.d.ts.map +1 -0
  253. package/dist/components/ui/search-dialog.js +178 -0
  254. package/dist/components/ui/section.d.ts +26 -0
  255. package/dist/components/ui/section.d.ts.map +1 -1
  256. package/dist/components/ui/section.js +32 -1
  257. package/dist/components/ui/select.js +1 -1
  258. package/dist/components/ui/separator.js +1 -1
  259. package/dist/components/ui/sheet.d.ts +103 -0
  260. package/dist/components/ui/sheet.d.ts.map +1 -0
  261. package/dist/components/ui/sheet.js +58 -0
  262. package/dist/components/ui/sidebar.d.ts +228 -0
  263. package/dist/components/ui/sidebar.d.ts.map +1 -0
  264. package/dist/components/ui/sidebar.js +172 -0
  265. package/dist/components/ui/signal-field.js +1 -1
  266. package/dist/components/ui/skeleton.js +1 -1
  267. package/dist/components/ui/slider.js +1 -1
  268. package/dist/components/ui/spinner.d.ts +79 -0
  269. package/dist/components/ui/spinner.d.ts.map +1 -0
  270. package/dist/components/ui/spinner.js +79 -0
  271. package/dist/components/ui/switch.js +1 -1
  272. package/dist/components/ui/table-sort.d.ts +97 -0
  273. package/dist/components/ui/table-sort.d.ts.map +1 -0
  274. package/dist/components/ui/table-sort.js +102 -0
  275. package/dist/components/ui/table.js +1 -1
  276. package/dist/components/ui/tabs.js +1 -1
  277. package/dist/components/ui/textarea.js +1 -1
  278. package/dist/components/ui/timeline.d.ts +106 -0
  279. package/dist/components/ui/timeline.d.ts.map +1 -0
  280. package/dist/components/ui/timeline.js +111 -0
  281. package/dist/components/ui/toast.d.ts +219 -0
  282. package/dist/components/ui/toast.d.ts.map +1 -0
  283. package/dist/components/ui/toast.js +270 -0
  284. package/dist/components/ui/toggle-group.d.ts +118 -0
  285. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  286. package/dist/components/ui/toggle-group.js +194 -0
  287. package/dist/components/ui/toggle.d.ts +73 -0
  288. package/dist/components/ui/toggle.d.ts.map +1 -0
  289. package/dist/components/ui/toggle.js +44 -0
  290. package/dist/components/ui/tooltip.js +1 -1
  291. package/dist/components/ui/tree.js +1 -1
  292. package/dist/components/ui/typography.js +1 -1
  293. package/dist/fonts/Inter-OFL.txt +93 -93
  294. package/dist/index.d.ts +72 -70
  295. package/dist/index.d.ts.map +1 -1
  296. package/dist/index.js +61 -60
  297. package/dist/lib/rank.d.ts +69 -0
  298. package/dist/lib/rank.d.ts.map +1 -0
  299. package/dist/lib/rank.js +77 -0
  300. package/dist/live/index.d.ts +22 -0
  301. package/dist/live/index.d.ts.map +1 -0
  302. package/dist/live/index.js +20 -0
  303. package/dist/live/run-stream-01/index.d.ts +3 -0
  304. package/dist/live/run-stream-01/index.d.ts.map +1 -0
  305. package/dist/live/run-stream-01/index.js +1 -0
  306. package/dist/live/run-stream-01/run-stream.d.ts +125 -0
  307. package/dist/live/run-stream-01/run-stream.d.ts.map +1 -0
  308. package/dist/live/run-stream-01/run-stream.js +111 -0
  309. package/dist/pages/auth-page/index.d.ts +15 -2
  310. package/dist/pages/auth-page/index.d.ts.map +1 -1
  311. package/dist/pages/auth-page/index.js +8 -4
  312. package/dist/pages/blog-post-page/index.js +5 -5
  313. package/dist/pages/dashboard-page/index.d.ts +4 -4
  314. package/dist/pages/dashboard-page/index.js +4 -4
  315. package/dist/pages/docs-shell/docs-shell.d.ts +37 -4
  316. package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -1
  317. package/dist/pages/docs-shell/docs-shell.js +107 -16
  318. package/dist/pages/docs-shell/index.d.ts +2 -2
  319. package/dist/pages/docs-shell/index.js +1 -1
  320. package/dist/pages/index.d.ts +14 -14
  321. package/dist/pages/index.js +7 -7
  322. package/dist/pages/marketing-page/index.d.ts +6 -6
  323. package/dist/pages/marketing-page/index.js +5 -5
  324. package/dist/pages/not-found-page/index.js +4 -4
  325. package/dist/pages/settings-page/index.d.ts +3 -3
  326. package/dist/pages/settings-page/index.js +4 -4
  327. package/dist/provider/index.d.ts +4 -4
  328. package/dist/provider/index.js +2 -2
  329. package/dist/provider/provider.d.ts +1 -1
  330. package/dist/provider/provider.js +1 -1
  331. package/dist/provider/theme-script.d.ts +1 -1
  332. package/dist/provider/theme-script.js +1 -1
  333. package/dist/styles.css +689 -0
  334. package/package.json +9 -1
@@ -0,0 +1,219 @@
1
+ import { type VariantProps } from 'class-variance-authority';
2
+ import { type ComponentProps, type ReactNode } from 'react';
3
+ /**
4
+ * The surface and the four tones, and nothing else.
5
+ *
6
+ * Every tone states its own fill AND its own ink, and that is the
7
+ * `check-variant-ink` rule rather than a style preference. A toast is the one
8
+ * surface in this package that is a *coloured* surface with body text sitting
9
+ * on it, so an inherited ink is not the page's foreground by accident: it is
10
+ * whatever happened to be behind the viewport, and the failure `Cta01`
11
+ * measured was 1.01:1 on a filled `bg-primary` band. A tone that set only a
12
+ * fill would be the same button in a different colour.
13
+ */
14
+ declare const toastVariants: (props?: ({
15
+ variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
16
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
17
+ /**
18
+ * The props the Toast root accepts.
19
+ *
20
+ * Every reader-facing string on this surface is a prop, and the reason is the
21
+ * library's reason: this package is installed into four products in at least
22
+ * two languages, and a toast that shipped a close button named in English
23
+ * would be a control those products cannot localise.
24
+ */
25
+ export interface ToastProps extends Omit<ComponentProps<'div'>, 'children' | 'title'>, VariantProps<typeof toastVariants> {
26
+ /**
27
+ * The short line: what happened, in the fewest words that are still true.
28
+ *
29
+ * A `<p>` and not a heading, deliberately. A notification that appears and
30
+ * then disappears must not put an entry in the page outline, because a reader
31
+ * who navigates by heading lands on the document, selects "Saved", and finds
32
+ * nothing there any more. `Alert` is a heading for the same words because an
33
+ * Alert is on the page for as long as the condition is.
34
+ *
35
+ * A `ReactNode`, so a caller can put an emphasis or an icon inside it, and it
36
+ * is also why the native `title` attribute is removed from the pass-through
37
+ * rather than forwarded. The two names are the same words with opposite
38
+ * consequences: a toast's title is the notification itself, read by everyone
39
+ * at once, while `title` is a tooltip that appears under the pointer to
40
+ * whoever happens to hover, and nothing else. A toast that forwarded both
41
+ * would say the same sentence twice to a mouse reader and once to a keyboard
42
+ * reader, in a surface whose whole purpose is to say a thing once.
43
+ */
44
+ title?: ReactNode;
45
+ /**
46
+ * The sentence under the title, when there is one.
47
+ *
48
+ * Separate from the title for the same reason `Alert` separates them: a
49
+ * title is scanned and a sentence is read, and a toast that merged them
50
+ * forces a reader to read a heading.
51
+ */
52
+ description?: ReactNode;
53
+ /**
54
+ * The one control the toast offers, as a slot.
55
+ *
56
+ * A `ReactNode` rather than a label and a handler, and that is the design
57
+ * decision rather than a convenience: **a toast's action is never the only
58
+ * route to what it does.** A toast is transient by definition, and a reader
59
+ * who missed it, or whose screen reader had not finished announcing it when
60
+ * it went, cannot take an action that exists only inside it. So whatever the
61
+ * action does has to be reachable in the surface the reader is already
62
+ * looking at, and the toast is the shortcut rather than the gate.
63
+ */
64
+ action?: ReactNode;
65
+ /**
66
+ * Called when the toast wants to be taken off the page: the clock ran out, the
67
+ * reader pressed the dismiss control, or the reader pressed Escape while the
68
+ * toast held focus.
69
+ *
70
+ * **The caller unmounts; this Component never hides itself.** That is what
71
+ * makes the leave transition possible at all, and it is stated here because a
72
+ * caller who expects the toast to remove itself will write a no-op and leave
73
+ * a toast parked on the page forever.
74
+ *
75
+ * **Omitting it makes the toast permanent, and that is deliberate.** Without a
76
+ * handoff there is nobody to take the toast off the page, so a clock with
77
+ * nothing to fire and a dismiss control with nothing to do would both be
78
+ * controls that lie. A toast with no `onDismiss` therefore does not run its
79
+ * clock, renders no dismiss control and ignores Escape: it stays until the
80
+ * caller unmounts it. The alternative is worse, because a toast that faded out
81
+ * and was never removed is an invisible element still in the document, still
82
+ * in the live region and still taking the pointer.
83
+ */
84
+ onDismiss?: () => void;
85
+ /**
86
+ * How long the toast stays up before it asks to be dismissed, in milliseconds.
87
+ *
88
+ * **The default is a judgement about a reader, and it is deliberately longer
89
+ * than a toast usually wants to be.** The failure this number exists to avoid
90
+ * is a toast vanishing before a screen reader has finished announcing it,
91
+ * which is worse than no toast at all: the reader is told something happened
92
+ * and then told, by its absence, that they missed it. Four seconds clears a
93
+ * title and a sentence at a conservative assistive-technology speaking rate.
94
+ * The pause on hover and on focus covers the reader who is looking at the
95
+ * toast rather than hearing it.
96
+ *
97
+ * `0` turns the clock off, for the toast the reader must act on. That is a
98
+ * real case and it is the one case where a toast earns the name, because the
99
+ * reader's next step is the toast's entire purpose.
100
+ *
101
+ * @defaultValue 4000
102
+ */
103
+ duration?: number;
104
+ /**
105
+ * The accessible name of the dismiss control.
106
+ *
107
+ * **Required, with no default, and this is the one surface in the package
108
+ * where a default would be wrong rather than merely unhelpful.** Every other
109
+ * close button here sits inside a dialog the reader opened, so its name is
110
+ * already implied by the thing it is closing. A toast arrived on its own: an
111
+ * icon-only control the reader reaches towards has to say what it is before
112
+ * they press it, and four products in two languages cannot all be told the
113
+ * control says "Close".
114
+ */
115
+ closeLabel: string;
116
+ /**
117
+ * Whether the dismiss control is rendered.
118
+ *
119
+ * A prop and not a decision made here, because a toast the reader cannot
120
+ * dismiss is a toast that can only be waited out, and a toast the reader must
121
+ * not dismiss is a dialog. Neither is this Component's call.
122
+ *
123
+ * Set to `false` for a toast the reader must not dismiss, and note that it
124
+ * costs the toast its only keyboard route out: with no control and no Escape,
125
+ * the caller has to offer the way to leave somewhere else, or the toast is a
126
+ * dialog with the focus trap left out. The control is also not rendered when
127
+ * there is no `onDismiss` to call, because a control that cannot do anything
128
+ * is worse than no control.
129
+ *
130
+ * @defaultValue true
131
+ */
132
+ showCloseButton?: boolean;
133
+ /**
134
+ * Whether the clock is paused regardless of the pointer or focus.
135
+ *
136
+ * The escape hatch for a caller holding a toast open while something else is
137
+ * still in flight, which is the ordinary case for a batch of operations
138
+ * reporting one at a time.
139
+ *
140
+ * @defaultValue false
141
+ */
142
+ paused?: boolean;
143
+ }
144
+ /**
145
+ * A transient notification for something the reader did not have to be told.
146
+ *
147
+ * **What a toast is FOR, stated narrowly, because the broad reading is why
148
+ * toasts get used for the wrong things.** A toast reports a fact the reader
149
+ * would otherwise miss: work finished in the background, a document was shared
150
+ * with them, a setting took effect. It is deliberately NOT the place for an
151
+ * error the reader caused and must act on, because a message that requires an
152
+ * action cannot be allowed to expire before the action is taken. That is an
153
+ * `Alert` beside the control, or a `Dialog` when it blocks. A toast carrying a
154
+ * blocking message is a modal in a costume.
155
+ *
156
+ * **It never takes focus, and that is the load-bearing accessibility claim.** A
157
+ * surface that moves focus to itself has interrupted the reader, and being
158
+ * interrupted is the whole thing a toast exists to avoid: the reader is typing,
159
+ * or reading, or doing something else entirely. So the root is a
160
+ * `role="status"` region that is announced without being entered, the dismiss
161
+ * control is reachable by Tab from wherever the reader already was, and nothing
162
+ * in this Component calls `focus()`. A consumer who needs attention right now
163
+ * wants a `Dialog`; one who needs the reader to act before the message goes
164
+ * away wants `duration={0}`.
165
+ *
166
+ * **It is announced once, and that is why there is no countdown on screen.** A
167
+ * visible timer would have to be a text or an attribute that changes, and
168
+ * anything that changes inside a live region is something a screen reader may
169
+ * announce again. A toast that read out its remaining time every second would
170
+ * be read thirty times. So the clock lives in a ref, it changes no text, and
171
+ * the region speaks once on arrival and again only if the caller changes the
172
+ * words.
173
+ *
174
+ * **It pauses on hover and on focus, for the same reason the default is long.**
175
+ * A reader who has moved the pointer onto a toast is reading it, and one who
176
+ * has tabbed into it is about to press something; in both cases the clock is
177
+ * the enemy of what the reader is doing. The pause *holds* the remaining time
178
+ * rather than restarting it, so a reader who hovers for ten seconds and then
179
+ * leaves gets the four seconds they had left, not four more.
180
+ *
181
+ * **The enter and the leave are the one motion in this package that is
182
+ * legitimate, because they are a state change and not decoration.** A toast is
183
+ * arriving and a toast is leaving, the reader can watch both happen, and that
184
+ * is what state feedback is. It is a fade and a short rise on `duration-slow`
185
+ * with `ease-out`, expressed with utilities this package already uses and with
186
+ * no keyframe: a transition plus a `data-phase` attribute carries both
187
+ * directions. There is no slide, because a travelling toast is a transition
188
+ * between two positions rather than a transition of one element, and expressing
189
+ * that without a keyframe would mean a transform the element does not otherwise
190
+ * have.
191
+ *
192
+ * **It never removes its own transition, and the reason is the caller's
193
+ * unmount.** The exit hands over on the end of the root's own opacity
194
+ * transition, so under reduced motion the fade is *shortened* rather than
195
+ * removed and the handoff still happens. Removing the fade there would have
196
+ * needed this Component to read the media query and hand over at once instead,
197
+ * which would be the same rule written twice: once in the stylesheet and once in
198
+ * TypeScript, free to disagree the day the motion policy is retuned. Leaving
199
+ * the fade in and shortening it keeps the decision in one place, and it is the
200
+ * same choice `DESIGN.md` states for the package: motion is state feedback,
201
+ * shortened rather than removed under reduced motion. The travel is the part
202
+ * that is movement, so that is the part `motion-safe:` guards.
203
+ *
204
+ * **It is a client Component** because it holds a clock, runs effects, and
205
+ * attaches three handlers. The clock is a single `setTimeout` whose
206
+ * `clearTimeout` is the effect's own return, so nothing outlives the Component:
207
+ * unmounting a toast takes its timer with it rather than leaving one to fire
208
+ * against a component that is no longer on the page.
209
+ *
210
+ * **A toast with no `onDismiss` never leaves, and that is the safe answer.**
211
+ * Every way out of this Component hands over to the caller, so with nobody to
212
+ * hand to there is no clock to run, no dismiss control to render and no Escape
213
+ * to answer. The alternative would be a toast that faded to `opacity-0` and was
214
+ * never removed from the document: invisible, still in the live region, still
215
+ * taking the pointer, and gone in every way except the ones that matter.
216
+ */
217
+ declare function Toast({ className, variant, title, description, action, onDismiss, duration, closeLabel, showCloseButton, paused, ...props }: ToastProps): import("react").JSX.Element;
218
+ export { Toast };
219
+ //# sourceMappingURL=toast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../../../src/components/ui/toast.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEjE,OAAO,EAA4C,KAAK,cAAc,EAAsB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAIzH;;;;;;;;;;GAUG;AACH,QAAA,MAAM,aAAa;;8EAsBlB,CAAA;AAaD;;;;;;;GAOG;AACH,MAAM,WAAW,UACf,SAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,EACvD,YAAY,CAAC,OAAO,aAAa,CAAC;IACpC;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB;;;;;;;;;;;;;;;;;;OAkBG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;OAUG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;;;;;;;;;;;OAeG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,KAAK,EACL,WAAW,EACX,MAAM,EACN,SAAS,EACT,QAAe,EACf,UAAU,EACV,eAAsB,EACtB,MAAc,EACd,GAAG,KAAK,EACT,EAAE,UAAU,+BA4NZ;AAED,OAAO,EAAE,KAAK,EAAE,CAAA"}
@@ -0,0 +1,270 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { cva } from 'class-variance-authority';
4
+ import { XIcon } from 'lucide-react';
5
+ import { useCallback, useEffect, useRef, useState } from 'react';
6
+ import { cn } from '../../lib/utils.js';
7
+ /**
8
+ * The surface and the four tones, and nothing else.
9
+ *
10
+ * Every tone states its own fill AND its own ink, and that is the
11
+ * `check-variant-ink` rule rather than a style preference. A toast is the one
12
+ * surface in this package that is a *coloured* surface with body text sitting
13
+ * on it, so an inherited ink is not the page's foreground by accident: it is
14
+ * whatever happened to be behind the viewport, and the failure `Cta01`
15
+ * measured was 1.01:1 on a filled `bg-primary` band. A tone that set only a
16
+ * fill would be the same button in a different colour.
17
+ */
18
+ const toastVariants = cva(
19
+ // `pointer-events-auto` because the viewport that hosts a toast is a fixed
20
+ // layer over one corner of the page, and a toast that inherited
21
+ // `pointer-events-none` from that layer would be a toast nobody can click.
22
+ 'bg-popover text-popover-foreground pointer-events-auto relative flex w-full items-start gap-3 rounded-lg border p-4 pr-10 shadow-md', {
23
+ variants: {
24
+ variant: {
25
+ default: 'border-border',
26
+ success: 'border-transparent bg-success text-success-foreground',
27
+ warning: 'border-transparent bg-warning text-warning-foreground',
28
+ // A destructive toast is for a failure the reader did not cause and
29
+ // would not otherwise learn: a payment declined on the server, a session
30
+ // that expired, a deploy that failed. It is NOT for a mistake the reader
31
+ // made, which belongs in an `Alert` beside the control where they can
32
+ // see what to change. That distinction is the reason a destructive tone
33
+ // exists here at all.
34
+ destructive: 'border-transparent bg-destructive text-destructive-foreground',
35
+ },
36
+ },
37
+ defaultVariants: { variant: 'default' },
38
+ });
39
+ /**
40
+ * A transient notification for something the reader did not have to be told.
41
+ *
42
+ * **What a toast is FOR, stated narrowly, because the broad reading is why
43
+ * toasts get used for the wrong things.** A toast reports a fact the reader
44
+ * would otherwise miss: work finished in the background, a document was shared
45
+ * with them, a setting took effect. It is deliberately NOT the place for an
46
+ * error the reader caused and must act on, because a message that requires an
47
+ * action cannot be allowed to expire before the action is taken. That is an
48
+ * `Alert` beside the control, or a `Dialog` when it blocks. A toast carrying a
49
+ * blocking message is a modal in a costume.
50
+ *
51
+ * **It never takes focus, and that is the load-bearing accessibility claim.** A
52
+ * surface that moves focus to itself has interrupted the reader, and being
53
+ * interrupted is the whole thing a toast exists to avoid: the reader is typing,
54
+ * or reading, or doing something else entirely. So the root is a
55
+ * `role="status"` region that is announced without being entered, the dismiss
56
+ * control is reachable by Tab from wherever the reader already was, and nothing
57
+ * in this Component calls `focus()`. A consumer who needs attention right now
58
+ * wants a `Dialog`; one who needs the reader to act before the message goes
59
+ * away wants `duration={0}`.
60
+ *
61
+ * **It is announced once, and that is why there is no countdown on screen.** A
62
+ * visible timer would have to be a text or an attribute that changes, and
63
+ * anything that changes inside a live region is something a screen reader may
64
+ * announce again. A toast that read out its remaining time every second would
65
+ * be read thirty times. So the clock lives in a ref, it changes no text, and
66
+ * the region speaks once on arrival and again only if the caller changes the
67
+ * words.
68
+ *
69
+ * **It pauses on hover and on focus, for the same reason the default is long.**
70
+ * A reader who has moved the pointer onto a toast is reading it, and one who
71
+ * has tabbed into it is about to press something; in both cases the clock is
72
+ * the enemy of what the reader is doing. The pause *holds* the remaining time
73
+ * rather than restarting it, so a reader who hovers for ten seconds and then
74
+ * leaves gets the four seconds they had left, not four more.
75
+ *
76
+ * **The enter and the leave are the one motion in this package that is
77
+ * legitimate, because they are a state change and not decoration.** A toast is
78
+ * arriving and a toast is leaving, the reader can watch both happen, and that
79
+ * is what state feedback is. It is a fade and a short rise on `duration-slow`
80
+ * with `ease-out`, expressed with utilities this package already uses and with
81
+ * no keyframe: a transition plus a `data-phase` attribute carries both
82
+ * directions. There is no slide, because a travelling toast is a transition
83
+ * between two positions rather than a transition of one element, and expressing
84
+ * that without a keyframe would mean a transform the element does not otherwise
85
+ * have.
86
+ *
87
+ * **It never removes its own transition, and the reason is the caller's
88
+ * unmount.** The exit hands over on the end of the root's own opacity
89
+ * transition, so under reduced motion the fade is *shortened* rather than
90
+ * removed and the handoff still happens. Removing the fade there would have
91
+ * needed this Component to read the media query and hand over at once instead,
92
+ * which would be the same rule written twice: once in the stylesheet and once in
93
+ * TypeScript, free to disagree the day the motion policy is retuned. Leaving
94
+ * the fade in and shortening it keeps the decision in one place, and it is the
95
+ * same choice `DESIGN.md` states for the package: motion is state feedback,
96
+ * shortened rather than removed under reduced motion. The travel is the part
97
+ * that is movement, so that is the part `motion-safe:` guards.
98
+ *
99
+ * **It is a client Component** because it holds a clock, runs effects, and
100
+ * attaches three handlers. The clock is a single `setTimeout` whose
101
+ * `clearTimeout` is the effect's own return, so nothing outlives the Component:
102
+ * unmounting a toast takes its timer with it rather than leaving one to fire
103
+ * against a component that is no longer on the page.
104
+ *
105
+ * **A toast with no `onDismiss` never leaves, and that is the safe answer.**
106
+ * Every way out of this Component hands over to the caller, so with nobody to
107
+ * hand to there is no clock to run, no dismiss control to render and no Escape
108
+ * to answer. The alternative would be a toast that faded to `opacity-0` and was
109
+ * never removed from the document: invisible, still in the live region, still
110
+ * taking the pointer, and gone in every way except the ones that matter.
111
+ */
112
+ function Toast({ className, variant, title, description, action, onDismiss, duration = 4000, closeLabel, showCloseButton = true, paused = false, ...props }) {
113
+ const [phase, setPhase] = useState('entering');
114
+ const [hovered, setHovered] = useState(false);
115
+ const [focused, setFocused] = useState(false);
116
+ const rootRef = useRef(null);
117
+ // The remaining time, in a ref rather than in state, because it is written by
118
+ // this Component's own clock and read by nothing the reader can see. State
119
+ // would re-render the whole toast four times a second to update a number no
120
+ // reader is shown, and every re-render of a live region is a chance to be
121
+ // announced again.
122
+ const remaining = useRef(duration);
123
+ const startedAt = useRef(0);
124
+ // The three reasons the clock stops, and the reason the pointer and the
125
+ // keyboard are two of them rather than one: a reader who has tabbed into the
126
+ // dismiss control has not finished with the toast, and neither has a reader
127
+ // who is reading it.
128
+ const held = paused || hovered || focused;
129
+ // The one thing without which nothing can leave: without a handoff there is
130
+ // nobody to take the toast off the page, so the clock has nothing to fire and
131
+ // the dismiss control has nothing to do. Every way out is gated on it, so a
132
+ // toast rendered without an `onDismiss` is a toast that stays rather than one
133
+ // that fades to invisible and is never removed.
134
+ const canLeave = onDismiss !== undefined;
135
+ useEffect(() => {
136
+ // Entering is one frame and not a duration. A transition needs a rendered
137
+ // state to transition *from*, and the first frame is the one that has it.
138
+ // The frame is cancelled on unmount, so a toast removed before its first
139
+ // paint does not leave a request behind.
140
+ //
141
+ // Deliberately not awaited by anything. A frame is a frame: if the browser
142
+ // never delivers one, because the tab is in the background, the toast is
143
+ // still on the page, still dismissible and still on its clock. The enter is
144
+ // the only part of this Component that is allowed to be skipped, and it is
145
+ // skipped on its own.
146
+ if (phase !== 'entering')
147
+ return;
148
+ const frame = requestAnimationFrame(() => setPhase('open'));
149
+ return () => cancelAnimationFrame(frame);
150
+ }, [phase]);
151
+ useEffect(() => {
152
+ // A new duration is a new clock. Written before the clock effect below
153
+ // re-runs, because that effect reads this one on its first line.
154
+ remaining.current = duration;
155
+ startedAt.current = 0;
156
+ }, [duration]);
157
+ useEffect(() => {
158
+ // `duration === 0` is the "the reader must act on this" case, and a toast
159
+ // with the clock off is the one toast entitled to stay.
160
+ //
161
+ // The guard is `leaving` and not `open`, because the clock is about the
162
+ // reader's patience rather than about the animation: tying the clock to the
163
+ // visual phase would mean a backgrounded tab, which never gets a frame, kept
164
+ // a toast up forever for a reason the reader never saw.
165
+ if (phase === 'leaving' || held || duration === 0 || !canLeave)
166
+ return;
167
+ startedAt.current = Date.now();
168
+ const timer = setTimeout(() => setPhase('leaving'), remaining.current);
169
+ // The single place the clock is stopped. It runs on unmount as well as on
170
+ // every pause, which is what keeps a toast's timer from outliving it, and
171
+ // the subtraction is what makes a resume a *continuation* rather than a
172
+ // restart.
173
+ return () => {
174
+ clearTimeout(timer);
175
+ remaining.current = Math.max(0, remaining.current - (Date.now() - startedAt.current));
176
+ };
177
+ }, [phase, held, duration, canLeave]);
178
+ const dismiss = useCallback(() => {
179
+ // Already leaving does not restart the exit, so the handoff to the caller
180
+ // is one call rather than one per reason the toast was dismissed.
181
+ setPhase((current) => (current === 'leaving' ? current : 'leaving'));
182
+ }, []);
183
+ useEffect(() => {
184
+ if (phase !== 'leaving')
185
+ return;
186
+ const root = rootRef.current;
187
+ if (root === null)
188
+ return;
189
+ // The leave ends when the transition the CSS declared has run, and not on a
190
+ // second clock of this Component's own: the length of the leave is a CSS
191
+ // decision, and a number in TypeScript would be a second source of truth
192
+ // for it that would stop agreeing with the stylesheet the day the token
193
+ // moved.
194
+ //
195
+ // It is the root's own opacity rather than "the first transition to end",
196
+ // and that holds under reduced motion too. The fade is shortened there and
197
+ // not removed, so an opacity transition always runs and always ends, and the
198
+ // caller is always told to unmount. Reading the media query in JavaScript
199
+ // would put the same decision in two places: the stylesheet would shorten
200
+ // the fade and this code would have to guess the same rule to know whether
201
+ // to expect the event.
202
+ //
203
+ // A `const` arrow and not a hoisted declaration, for one reason that is not
204
+ // taste: a function declaration could be called before the null check above
205
+ // ran, so TypeScript drops the narrowing on `root` inside it, while an arrow
206
+ // assigned to a `const` cannot exist until the check has passed.
207
+ const finish = (event) => {
208
+ // Filtered to this element's own opacity, because a child control's
209
+ // colour transition would otherwise end the toast's exit early and the
210
+ // caller would unmount it half way through the fade.
211
+ if (event.target !== root)
212
+ return;
213
+ if (event.propertyName !== 'opacity')
214
+ return;
215
+ // Removed on the way through, because the phase does not change on the
216
+ // way out and so this effect is not re-run to clean up. A listener left
217
+ // attached would call the caller's unmount again on the next opacity
218
+ // transition on this element, and an unmount that runs twice is a state
219
+ // update on a component that is no longer there.
220
+ root.removeEventListener('transitionend', finish);
221
+ onDismiss?.();
222
+ };
223
+ root.addEventListener('transitionend', finish);
224
+ return () => root.removeEventListener('transitionend', finish);
225
+ }, [phase, onDismiss]);
226
+ const onKeyDown = (event) => {
227
+ // Escape dismisses, and only when the toast itself holds focus. A toast
228
+ // that answered a document-level Escape would swallow the key from whatever
229
+ // the reader is actually typing in, which is the failure every floating
230
+ // surface causes when it listens globally.
231
+ if (event.key !== 'Escape')
232
+ return;
233
+ if (!canLeave)
234
+ return;
235
+ if (!rootRef.current?.contains(event.target))
236
+ return;
237
+ event.stopPropagation();
238
+ dismiss();
239
+ };
240
+ return (_jsxs("div", { ref: rootRef, "data-slot": "toast", "data-phase": phase,
241
+ // The role is what makes the announcement happen at all, and it is the one
242
+ // `LiveRegion` uses and for the same reason: a toast is content that
243
+ // changed and is not waiting for the reader. `aria-live` is written
244
+ // explicitly so the politeness is a stated fact rather than an implication
245
+ // of the role, and `aria-atomic` is on because a title and a sentence
246
+ // arrive together and a reader should hear one notification rather than
247
+ // two.
248
+ role: "status", "aria-live": "polite", "aria-atomic": "true", onKeyDown: onKeyDown, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), onFocus: () => setFocused(true), onBlur: () => setFocused(false), className: cn(toastVariants({ variant }),
249
+ // The enter and the leave as one transition on two properties.
250
+ // `duration-slow` rather than `duration-base` because a toast crosses
251
+ // the page and a fast one is over before a reader has registered that
252
+ // anything arrived; `ease-out` because both directions are decelerating
253
+ // into a resting state rather than accelerating out of one.
254
+ 'transition-[opacity,transform] duration-slow ease-out',
255
+ // Reduced motion shortens the fade and removes the travel, rather than
256
+ // removing the transition. The fade is what tells a reader the toast is
257
+ // there and then that it is gone, and a reader who asked for less motion
258
+ // has not asked to be told nothing; the rise is movement, and movement is
259
+ // what they asked not to have. It is also why the handoff below waits on
260
+ // an opacity transition rather than reading the media query in JavaScript:
261
+ // an opacity that always transitions always ends, so there is no case in
262
+ // which the caller is never told to unmount.
263
+ 'motion-reduce:duration-fast', 'motion-safe:data-[phase=entering]:translate-y-1 motion-safe:data-[phase=leaving]:translate-y-1', 'data-[phase=entering]:opacity-0 data-[phase=leaving]:opacity-0', className), ...props, children: [_jsxs("div", { "data-slot": "toast-body", className: "flex min-w-0 flex-1 flex-col gap-1", children: [title === undefined ? null : (_jsx("p", { "data-slot": "toast-title", className: "text-sm font-medium", children: title })), description === undefined ? null : (_jsx("p", { "data-slot": "toast-description", className: "text-pretty text-sm opacity-90", children: description })), action === undefined ? null : (_jsx("div", { "data-slot": "toast-action", className: "mt-1.5 flex items-center", children: action }))] }), showCloseButton && canLeave ? (_jsx("button", { type: "button", "data-slot": "toast-close", "aria-label": closeLabel, onClick: dismiss,
264
+ // The ring is at full strength for the reason `Button`'s is: half alpha
265
+ // composites to under 3:1 against every surface in every pack, and this
266
+ // is the one indicator on a control a reader reaches for without
267
+ // having opened anything.
268
+ className: cn('ring-offset-background focus-visible:ring-ring absolute top-2 right-2 rounded-sm opacity-70 outline-none', 'transition-opacity duration-fast ease-out', 'hover:opacity-100 focus-visible:ring-[3px]'), children: _jsx(XIcon, { className: "size-4", "aria-hidden": "true" }) })) : null] }));
269
+ }
270
+ export { Toast };
@@ -0,0 +1,118 @@
1
+ import { type ComponentProps, type ReactNode } from 'react';
2
+ /** How many members of a ToggleGroup may be pressed at once. */
3
+ export type ToggleGroupSelectionMode = 'single' | 'multiple';
4
+ /** The props the ToggleGroup accepts. */
5
+ export interface ToggleGroupProps extends Omit<ComponentProps<'div'>, 'onChange' | 'children'> {
6
+ /** The members, as `ToggleGroupItem` elements. */
7
+ children?: ReactNode;
8
+ /**
9
+ * Whether one member or several may be pressed.
10
+ *
11
+ * This is the caller's decision and it is a real one, which is why it is a prop
12
+ * with two values rather than two Components. See the group's JSDoc for what
13
+ * each mode means in the accessibility tree, because the two are not the same
14
+ * control wearing two looks.
15
+ */
16
+ selectionMode?: ToggleGroupSelectionMode;
17
+ /** The pressed values, when the group is controlled. */
18
+ value?: readonly string[];
19
+ /** The pressed values to start with, for an uncontrolled group. */
20
+ defaultValue?: readonly string[];
21
+ /** Called with the group's whole set of pressed values when it changes. */
22
+ onValueChange?: (value: readonly string[]) => void;
23
+ /** Whether every member ignores user interaction. */
24
+ disabled?: boolean;
25
+ /**
26
+ * The group's accessible name.
27
+ *
28
+ * Required rather than defaulted. A group of toggles with no name is announced
29
+ * as an unnamed group, and a toolbar with two of them is a toolbar where a
30
+ * reader cannot tell which set of controls they are in. The name is the
31
+ * caller's word, for the reason every region's name in this package is.
32
+ */
33
+ 'aria-label'?: string;
34
+ /** The direction the arrow keys move in. @defaultValue 'horizontal' */
35
+ orientation?: 'horizontal' | 'vertical';
36
+ /** Layout only. */
37
+ className?: string;
38
+ }
39
+ /** The props the ToggleGroupItem accepts. */
40
+ export interface ToggleGroupItemProps extends Omit<ComponentProps<'button'>, 'value' | 'children'> {
41
+ /**
42
+ * The value this member contributes to the group.
43
+ *
44
+ * Required, because a member the group cannot name is a member it cannot report
45
+ * and cannot restore, and the group reports the whole set rather than a
46
+ * difference.
47
+ */
48
+ value: string;
49
+ /** Whether this member ignores user interaction. */
50
+ disabled?: boolean;
51
+ /** The words on the member, and its accessible name. */
52
+ children?: ReactNode;
53
+ }
54
+ /**
55
+ * A set of toggles that behave as one control.
56
+ *
57
+ * **The single or multiple decision is the caller's, and it changes what the
58
+ * group is rather than how it looks.** This is the decision worth stating because
59
+ * getting it wrong is the usual failure, and it is invisible in a screenshot: two
60
+ * groups of three buttons, one where at most one is pressed and one where any
61
+ * number are, look identical until you read the roles.
62
+ *
63
+ * In `single` mode the group is a **radiogroup** and its members are **radios**
64
+ * carrying `aria-checked`. That is not a stylistic preference, it is the only
65
+ * description of the constraint that is true. The choices are mutually exclusive,
66
+ * there is exactly one answer, and the whole set is one question rather than three
67
+ * independent facts. Three buttons carrying `aria-pressed` say three independent
68
+ * things can be on at once, which is a lie, and a reader of the accessibility tree
69
+ * is left to infer the constraint from nothing.
70
+ *
71
+ * In `multiple` mode the group is a **toolbar** and its members are **pressed
72
+ * buttons** carrying `aria-pressed`, and the arrow keys move focus without
73
+ * choosing. That is the right behaviour for a toolbar of independent toggles,
74
+ * where arrowing past a member must not silently turn it on, and Space is what
75
+ * presses. So the two modes differ in the role of the group, the role of the
76
+ * member, the state attribute, and what an arrow key does, and none of the four is
77
+ * reachable from the other by passing a prop.
78
+ *
79
+ * **The group is one Tab stop, and it is the current answer.** Tab enters on the
80
+ * member that is pressed, or on the first member when nothing is pressed, and Tab
81
+ * leaves the group in one step. That is the composite pattern, and it is why a
82
+ * consumer cannot assemble this from a row of Toggles: composing them gives the
83
+ * Tab order of the document, which is every member of the group and none of the
84
+ * arrows. A radiogroup whose Tab lands on the first option when a different one is
85
+ * checked is a group that reports the wrong current value through the tab order
86
+ * alone, and with seven members in a row the reader pays for it.
87
+ *
88
+ * **The tab stop follows the reader once they move.** It is a piece of state
89
+ * rather than a derivation, because a reader who arrows across a group of seven
90
+ * and Tabs away expects to arrive back where they were, and a stop recomputed
91
+ * from the pressed value on every render is a stop that follows the pressed value
92
+ * instead of the reader.
93
+ *
94
+ * **The keyboard model lives here rather than in each member,** for the reason
95
+ * `Tree` keeps its own: three members each handling an arrow key is three
96
+ * implementations of one rule, and the third is the one that is wrong. The order
97
+ * the arrows walk is the group's own children rather than the node list, so it is
98
+ * the order the reader sees and the order a reordering caller declared, with no
99
+ * second list to fall behind the first.
100
+ *
101
+ * It is a client Component: it holds the pressed set and the roving tab stop, and
102
+ * both are the control rather than a decoration of it.
103
+ */
104
+ declare function ToggleGroup({ children, className, selectionMode, value, defaultValue, onValueChange, disabled, orientation, ...props }: ToggleGroupProps): import("react").JSX.Element;
105
+ /**
106
+ * One member of a ToggleGroup.
107
+ *
108
+ * A native `<button>` in both modes, because it is focusable, it submits nothing
109
+ * it was not asked to, and it is the element the browser's own activation already
110
+ * handles. What changes between the modes is the role and the state attribute, and
111
+ * both are read from the group: a radio carrying `aria-checked` in single mode, a
112
+ * pressed button in multiple mode. Render a Prism `Toggle` outside a group when a
113
+ * member stands alone; render this inside one, where the group owns the keyboard
114
+ * model and the pressed set.
115
+ */
116
+ declare function ToggleGroupItem({ className, value, disabled, children, ...props }: ToggleGroupItemProps): import("react").JSX.Element;
117
+ export { ToggleGroup, ToggleGroupItem };
118
+ //# sourceMappingURL=toggle-group.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle-group.d.ts","sourceRoot":"","sources":["../../../src/components/ui/toggle-group.tsx"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAId,gEAAgE;AAChE,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,UAAU,CAAA;AAE5D,yCAAyC;AACzC,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IAC5F,kDAAkD;IAClD,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,wBAAwB,CAAA;IACxC,wDAAwD;IACxD,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzB,mEAAmE;IACnE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IAChC,2EAA2E;IAC3E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;IAClD,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,uEAAuE;IACvE,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAA;IACvC,mBAAmB;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,6CAA6C;AAC7C,MAAM,WAAW,oBAAqB,SAAQ,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IAChG;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAyCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,iBAAS,WAAW,CAAC,EACnB,QAAQ,EACR,SAAS,EACT,aAAwB,EACxB,KAAK,EACL,YAAY,EACZ,aAAa,EACb,QAAgB,EAChB,WAA0B,EAC1B,GAAG,KAAK,EACT,EAAE,gBAAgB,+BAoHlB;AAED;;;;;;;;;;GAUG;AACH,iBAAS,eAAe,CAAC,EACvB,SAAS,EACT,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,oBAAoB,+BAiDtB;AAED,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,CAAA"}