@dowel-ui/react 0.1.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 (691) hide show
  1. package/LICENSE +21 -0
  2. package/dist/blocks/admin-users/meta.js +27 -0
  3. package/dist/blocks/admin-users/meta.js.map +1 -0
  4. package/dist/blocks/ai-chat/meta.js +30 -0
  5. package/dist/blocks/ai-chat/meta.js.map +1 -0
  6. package/dist/blocks/dashboard/meta.js +23 -0
  7. package/dist/blocks/dashboard/meta.js.map +1 -0
  8. package/dist/blocks/forgot-password/meta.js +24 -0
  9. package/dist/blocks/forgot-password/meta.js.map +1 -0
  10. package/dist/blocks/login/meta.js +26 -0
  11. package/dist/blocks/login/meta.js.map +1 -0
  12. package/dist/blocks/pricing/meta.js +24 -0
  13. package/dist/blocks/pricing/meta.js.map +1 -0
  14. package/dist/blocks/settings/meta.js +29 -0
  15. package/dist/blocks/settings/meta.js.map +1 -0
  16. package/dist/blocks/signup/meta.js +25 -0
  17. package/dist/blocks/signup/meta.js.map +1 -0
  18. package/dist/components/accordion/accordion.d.ts +19 -0
  19. package/dist/components/accordion/accordion.d.ts.map +1 -0
  20. package/dist/components/accordion/accordion.js +58 -0
  21. package/dist/components/accordion/accordion.js.map +1 -0
  22. package/dist/components/accordion/index.d.ts +2 -0
  23. package/dist/components/accordion/index.js +2 -0
  24. package/dist/components/accordion/meta.js +17 -0
  25. package/dist/components/accordion/meta.js.map +1 -0
  26. package/dist/components/activity-feed/activity-feed.d.ts +39 -0
  27. package/dist/components/activity-feed/activity-feed.d.ts.map +1 -0
  28. package/dist/components/activity-feed/activity-feed.js +77 -0
  29. package/dist/components/activity-feed/activity-feed.js.map +1 -0
  30. package/dist/components/activity-feed/index.d.ts +2 -0
  31. package/dist/components/activity-feed/index.js +2 -0
  32. package/dist/components/activity-feed/meta.js +17 -0
  33. package/dist/components/activity-feed/meta.js.map +1 -0
  34. package/dist/components/ai-agent-status/ai-agent-status.d.ts +30 -0
  35. package/dist/components/ai-agent-status/ai-agent-status.d.ts.map +1 -0
  36. package/dist/components/ai-agent-status/ai-agent-status.js +43 -0
  37. package/dist/components/ai-agent-status/ai-agent-status.js.map +1 -0
  38. package/dist/components/ai-agent-status/index.d.ts +2 -0
  39. package/dist/components/ai-agent-status/index.js +2 -0
  40. package/dist/components/ai-agent-status/meta.js +17 -0
  41. package/dist/components/ai-agent-status/meta.js.map +1 -0
  42. package/dist/components/ai-conversation/ai-conversation.d.ts +45 -0
  43. package/dist/components/ai-conversation/ai-conversation.d.ts.map +1 -0
  44. package/dist/components/ai-conversation/ai-conversation.js +138 -0
  45. package/dist/components/ai-conversation/ai-conversation.js.map +1 -0
  46. package/dist/components/ai-conversation/index.d.ts +2 -0
  47. package/dist/components/ai-conversation/index.js +2 -0
  48. package/dist/components/ai-conversation/meta.js +17 -0
  49. package/dist/components/ai-conversation/meta.js.map +1 -0
  50. package/dist/components/ai-message/ai-message.d.ts +56 -0
  51. package/dist/components/ai-message/ai-message.d.ts.map +1 -0
  52. package/dist/components/ai-message/ai-message.js +90 -0
  53. package/dist/components/ai-message/ai-message.js.map +1 -0
  54. package/dist/components/ai-message/index.d.ts +2 -0
  55. package/dist/components/ai-message/index.js +2 -0
  56. package/dist/components/ai-message/meta.js +17 -0
  57. package/dist/components/ai-message/meta.js.map +1 -0
  58. package/dist/components/ai-model-selector/ai-model-selector.d.ts +42 -0
  59. package/dist/components/ai-model-selector/ai-model-selector.d.ts.map +1 -0
  60. package/dist/components/ai-model-selector/ai-model-selector.js +48 -0
  61. package/dist/components/ai-model-selector/ai-model-selector.js.map +1 -0
  62. package/dist/components/ai-model-selector/index.d.ts +2 -0
  63. package/dist/components/ai-model-selector/index.js +2 -0
  64. package/dist/components/ai-model-selector/meta.js +17 -0
  65. package/dist/components/ai-model-selector/meta.js.map +1 -0
  66. package/dist/components/ai-prompt-input/ai-prompt-input.d.ts +61 -0
  67. package/dist/components/ai-prompt-input/ai-prompt-input.d.ts.map +1 -0
  68. package/dist/components/ai-prompt-input/ai-prompt-input.js +170 -0
  69. package/dist/components/ai-prompt-input/ai-prompt-input.js.map +1 -0
  70. package/dist/components/ai-prompt-input/index.d.ts +2 -0
  71. package/dist/components/ai-prompt-input/index.js +2 -0
  72. package/dist/components/ai-prompt-input/meta.js +17 -0
  73. package/dist/components/ai-prompt-input/meta.js.map +1 -0
  74. package/dist/components/ai-reasoning/ai-reasoning.d.ts +24 -0
  75. package/dist/components/ai-reasoning/ai-reasoning.d.ts.map +1 -0
  76. package/dist/components/ai-reasoning/ai-reasoning.js +64 -0
  77. package/dist/components/ai-reasoning/ai-reasoning.js.map +1 -0
  78. package/dist/components/ai-reasoning/index.d.ts +2 -0
  79. package/dist/components/ai-reasoning/index.js +2 -0
  80. package/dist/components/ai-reasoning/meta.js +17 -0
  81. package/dist/components/ai-reasoning/meta.js.map +1 -0
  82. package/dist/components/ai-response/ai-response.d.ts +36 -0
  83. package/dist/components/ai-response/ai-response.d.ts.map +1 -0
  84. package/dist/components/ai-response/ai-response.js +46 -0
  85. package/dist/components/ai-response/ai-response.js.map +1 -0
  86. package/dist/components/ai-response/index.d.ts +2 -0
  87. package/dist/components/ai-response/index.js +2 -0
  88. package/dist/components/ai-response/meta.js +17 -0
  89. package/dist/components/ai-response/meta.js.map +1 -0
  90. package/dist/components/ai-sources/ai-sources.d.ts +44 -0
  91. package/dist/components/ai-sources/ai-sources.d.ts.map +1 -0
  92. package/dist/components/ai-sources/ai-sources.js +112 -0
  93. package/dist/components/ai-sources/ai-sources.js.map +1 -0
  94. package/dist/components/ai-sources/index.d.ts +2 -0
  95. package/dist/components/ai-sources/index.js +2 -0
  96. package/dist/components/ai-sources/meta.js +17 -0
  97. package/dist/components/ai-sources/meta.js.map +1 -0
  98. package/dist/components/ai-token-usage/ai-token-usage.d.ts +34 -0
  99. package/dist/components/ai-token-usage/ai-token-usage.d.ts.map +1 -0
  100. package/dist/components/ai-token-usage/ai-token-usage.js +58 -0
  101. package/dist/components/ai-token-usage/ai-token-usage.js.map +1 -0
  102. package/dist/components/ai-token-usage/index.d.ts +2 -0
  103. package/dist/components/ai-token-usage/index.js +2 -0
  104. package/dist/components/ai-token-usage/meta.js +17 -0
  105. package/dist/components/ai-token-usage/meta.js.map +1 -0
  106. package/dist/components/ai-tool/ai-tool.d.ts +50 -0
  107. package/dist/components/ai-tool/ai-tool.d.ts.map +1 -0
  108. package/dist/components/ai-tool/ai-tool.js +129 -0
  109. package/dist/components/ai-tool/ai-tool.js.map +1 -0
  110. package/dist/components/ai-tool/index.d.ts +2 -0
  111. package/dist/components/ai-tool/index.js +2 -0
  112. package/dist/components/ai-tool/meta.js +17 -0
  113. package/dist/components/ai-tool/meta.js.map +1 -0
  114. package/dist/components/alert/alert.d.ts +32 -0
  115. package/dist/components/alert/alert.d.ts.map +1 -0
  116. package/dist/components/alert/alert.js +49 -0
  117. package/dist/components/alert/alert.js.map +1 -0
  118. package/dist/components/alert/index.d.ts +2 -0
  119. package/dist/components/alert/index.js +2 -0
  120. package/dist/components/alert/meta.js +17 -0
  121. package/dist/components/alert/meta.js.map +1 -0
  122. package/dist/components/avatar/avatar.d.ts +23 -0
  123. package/dist/components/avatar/avatar.d.ts.map +1 -0
  124. package/dist/components/avatar/avatar.js +44 -0
  125. package/dist/components/avatar/avatar.js.map +1 -0
  126. package/dist/components/avatar/index.d.ts +2 -0
  127. package/dist/components/avatar/index.js +2 -0
  128. package/dist/components/avatar/meta.js +17 -0
  129. package/dist/components/avatar/meta.js.map +1 -0
  130. package/dist/components/badge/badge.d.ts +20 -0
  131. package/dist/components/badge/badge.d.ts.map +1 -0
  132. package/dist/components/badge/badge.js +47 -0
  133. package/dist/components/badge/badge.js.map +1 -0
  134. package/dist/components/badge/index.d.ts +2 -0
  135. package/dist/components/badge/index.js +2 -0
  136. package/dist/components/badge/meta.js +17 -0
  137. package/dist/components/badge/meta.js.map +1 -0
  138. package/dist/components/button/button.d.ts +28 -0
  139. package/dist/components/button/button.d.ts.map +1 -0
  140. package/dist/components/button/button.js +77 -0
  141. package/dist/components/button/button.js.map +1 -0
  142. package/dist/components/button/index.d.ts +2 -0
  143. package/dist/components/button/index.js +2 -0
  144. package/dist/components/button/meta.js +17 -0
  145. package/dist/components/button/meta.js.map +1 -0
  146. package/dist/components/calendar/calendar.d.ts +16 -0
  147. package/dist/components/calendar/calendar.d.ts.map +1 -0
  148. package/dist/components/calendar/calendar.js +70 -0
  149. package/dist/components/calendar/calendar.js.map +1 -0
  150. package/dist/components/calendar/index.d.ts +2 -0
  151. package/dist/components/calendar/index.js +2 -0
  152. package/dist/components/calendar/meta.js +17 -0
  153. package/dist/components/calendar/meta.js.map +1 -0
  154. package/dist/components/card/card.d.ts +23 -0
  155. package/dist/components/card/card.d.ts.map +1 -0
  156. package/dist/components/card/card.js +53 -0
  157. package/dist/components/card/card.js.map +1 -0
  158. package/dist/components/card/index.d.ts +2 -0
  159. package/dist/components/card/index.js +2 -0
  160. package/dist/components/card/meta.js +17 -0
  161. package/dist/components/card/meta.js.map +1 -0
  162. package/dist/components/checkbox/checkbox.d.ts +15 -0
  163. package/dist/components/checkbox/checkbox.d.ts.map +1 -0
  164. package/dist/components/checkbox/checkbox.js +45 -0
  165. package/dist/components/checkbox/checkbox.js.map +1 -0
  166. package/dist/components/checkbox/index.d.ts +2 -0
  167. package/dist/components/checkbox/index.js +2 -0
  168. package/dist/components/checkbox/meta.js +17 -0
  169. package/dist/components/checkbox/meta.js.map +1 -0
  170. package/dist/components/code-block/code-block.d.ts +46 -0
  171. package/dist/components/code-block/code-block.d.ts.map +1 -0
  172. package/dist/components/code-block/code-block.js +110 -0
  173. package/dist/components/code-block/code-block.js.map +1 -0
  174. package/dist/components/code-block/index.d.ts +2 -0
  175. package/dist/components/code-block/index.js +2 -0
  176. package/dist/components/code-block/meta.js +17 -0
  177. package/dist/components/code-block/meta.js.map +1 -0
  178. package/dist/components/combobox/combobox.d.ts +59 -0
  179. package/dist/components/combobox/combobox.d.ts.map +1 -0
  180. package/dist/components/combobox/combobox.js +346 -0
  181. package/dist/components/combobox/combobox.js.map +1 -0
  182. package/dist/components/combobox/index.d.ts +2 -0
  183. package/dist/components/combobox/index.js +2 -0
  184. package/dist/components/combobox/meta.js +17 -0
  185. package/dist/components/combobox/meta.js.map +1 -0
  186. package/dist/components/command/command.d.ts +65 -0
  187. package/dist/components/command/command.d.ts.map +1 -0
  188. package/dist/components/command/command.js +330 -0
  189. package/dist/components/command/command.js.map +1 -0
  190. package/dist/components/command/index.d.ts +2 -0
  191. package/dist/components/command/index.js +2 -0
  192. package/dist/components/command/meta.js +17 -0
  193. package/dist/components/command/meta.js.map +1 -0
  194. package/dist/components/data-table/data-table.d.ts +91 -0
  195. package/dist/components/data-table/data-table.d.ts.map +1 -0
  196. package/dist/components/data-table/data-table.js +263 -0
  197. package/dist/components/data-table/data-table.js.map +1 -0
  198. package/dist/components/data-table/index.d.ts +2 -0
  199. package/dist/components/data-table/index.js +2 -0
  200. package/dist/components/data-table/meta.js +22 -0
  201. package/dist/components/data-table/meta.js.map +1 -0
  202. package/dist/components/date-picker/date-picker.d.ts +31 -0
  203. package/dist/components/date-picker/date-picker.d.ts.map +1 -0
  204. package/dist/components/date-picker/date-picker.js +123 -0
  205. package/dist/components/date-picker/date-picker.js.map +1 -0
  206. package/dist/components/date-picker/index.d.ts +2 -0
  207. package/dist/components/date-picker/index.js +2 -0
  208. package/dist/components/date-picker/meta.js +21 -0
  209. package/dist/components/date-picker/meta.js.map +1 -0
  210. package/dist/components/dialog/dialog.d.ts +30 -0
  211. package/dist/components/dialog/dialog.d.ts.map +1 -0
  212. package/dist/components/dialog/dialog.js +79 -0
  213. package/dist/components/dialog/dialog.js.map +1 -0
  214. package/dist/components/dialog/index.d.ts +2 -0
  215. package/dist/components/dialog/index.js +2 -0
  216. package/dist/components/dialog/meta.js +17 -0
  217. package/dist/components/dialog/meta.js.map +1 -0
  218. package/dist/components/drawer/drawer.d.ts +32 -0
  219. package/dist/components/drawer/drawer.d.ts.map +1 -0
  220. package/dist/components/drawer/drawer.js +153 -0
  221. package/dist/components/drawer/drawer.js.map +1 -0
  222. package/dist/components/drawer/index.d.ts +2 -0
  223. package/dist/components/drawer/index.js +2 -0
  224. package/dist/components/drawer/meta.js +17 -0
  225. package/dist/components/drawer/meta.js.map +1 -0
  226. package/dist/components/dropdown-menu/dropdown-menu.d.ts +43 -0
  227. package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +1 -0
  228. package/dist/components/dropdown-menu/dropdown-menu.js +130 -0
  229. package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -0
  230. package/dist/components/dropdown-menu/index.d.ts +2 -0
  231. package/dist/components/dropdown-menu/index.js +2 -0
  232. package/dist/components/dropdown-menu/meta.js +17 -0
  233. package/dist/components/dropdown-menu/meta.js.map +1 -0
  234. package/dist/components/empty-state/empty-state.d.ts +24 -0
  235. package/dist/components/empty-state/empty-state.d.ts.map +1 -0
  236. package/dist/components/empty-state/empty-state.js +73 -0
  237. package/dist/components/empty-state/empty-state.js.map +1 -0
  238. package/dist/components/empty-state/index.d.ts +2 -0
  239. package/dist/components/empty-state/index.js +2 -0
  240. package/dist/components/empty-state/meta.js +17 -0
  241. package/dist/components/empty-state/meta.js.map +1 -0
  242. package/dist/components/form/form.d.ts +43 -0
  243. package/dist/components/form/form.d.ts.map +1 -0
  244. package/dist/components/form/form.js +127 -0
  245. package/dist/components/form/form.js.map +1 -0
  246. package/dist/components/form/index.d.ts +2 -0
  247. package/dist/components/form/index.js +2 -0
  248. package/dist/components/form/meta.js +17 -0
  249. package/dist/components/form/meta.js.map +1 -0
  250. package/dist/components/input/index.d.ts +2 -0
  251. package/dist/components/input/index.js +2 -0
  252. package/dist/components/input/input.d.ts +21 -0
  253. package/dist/components/input/input.d.ts.map +1 -0
  254. package/dist/components/input/input.js +34 -0
  255. package/dist/components/input/input.js.map +1 -0
  256. package/dist/components/input/meta.js +17 -0
  257. package/dist/components/input/meta.js.map +1 -0
  258. package/dist/components/label/index.d.ts +2 -0
  259. package/dist/components/label/index.js +2 -0
  260. package/dist/components/label/label.d.ts +14 -0
  261. package/dist/components/label/label.d.ts.map +1 -0
  262. package/dist/components/label/label.js +20 -0
  263. package/dist/components/label/label.js.map +1 -0
  264. package/dist/components/label/meta.js +17 -0
  265. package/dist/components/label/meta.js.map +1 -0
  266. package/dist/components/pagination/index.d.ts +2 -0
  267. package/dist/components/pagination/index.js +2 -0
  268. package/dist/components/pagination/meta.js +17 -0
  269. package/dist/components/pagination/meta.js.map +1 -0
  270. package/dist/components/pagination/pagination.d.ts +33 -0
  271. package/dist/components/pagination/pagination.d.ts.map +1 -0
  272. package/dist/components/pagination/pagination.js +143 -0
  273. package/dist/components/pagination/pagination.js.map +1 -0
  274. package/dist/components/popover/index.d.ts +2 -0
  275. package/dist/components/popover/index.js +2 -0
  276. package/dist/components/popover/meta.js +17 -0
  277. package/dist/components/popover/meta.js.map +1 -0
  278. package/dist/components/popover/popover.d.ts +24 -0
  279. package/dist/components/popover/popover.d.ts.map +1 -0
  280. package/dist/components/popover/popover.js +60 -0
  281. package/dist/components/popover/popover.js.map +1 -0
  282. package/dist/components/progress/index.d.ts +2 -0
  283. package/dist/components/progress/index.js +2 -0
  284. package/dist/components/progress/meta.js +17 -0
  285. package/dist/components/progress/meta.js.map +1 -0
  286. package/dist/components/progress/progress.d.ts +21 -0
  287. package/dist/components/progress/progress.d.ts.map +1 -0
  288. package/dist/components/progress/progress.js +55 -0
  289. package/dist/components/progress/progress.js.map +1 -0
  290. package/dist/components/radio-group/index.d.ts +2 -0
  291. package/dist/components/radio-group/index.js +2 -0
  292. package/dist/components/radio-group/meta.js +17 -0
  293. package/dist/components/radio-group/meta.js.map +1 -0
  294. package/dist/components/radio-group/radio-group.d.ts +17 -0
  295. package/dist/components/radio-group/radio-group.d.ts.map +1 -0
  296. package/dist/components/radio-group/radio-group.js +29 -0
  297. package/dist/components/radio-group/radio-group.js.map +1 -0
  298. package/dist/components/select/index.d.ts +2 -0
  299. package/dist/components/select/index.js +2 -0
  300. package/dist/components/select/meta.js +17 -0
  301. package/dist/components/select/meta.js.map +1 -0
  302. package/dist/components/select/select.d.ts +37 -0
  303. package/dist/components/select/select.d.ts.map +1 -0
  304. package/dist/components/select/select.js +128 -0
  305. package/dist/components/select/select.js.map +1 -0
  306. package/dist/components/separator/index.d.ts +2 -0
  307. package/dist/components/separator/index.js +2 -0
  308. package/dist/components/separator/meta.js +17 -0
  309. package/dist/components/separator/meta.js.map +1 -0
  310. package/dist/components/separator/separator.d.ts +15 -0
  311. package/dist/components/separator/separator.d.ts.map +1 -0
  312. package/dist/components/separator/separator.js +23 -0
  313. package/dist/components/separator/separator.js.map +1 -0
  314. package/dist/components/sheet/index.d.ts +2 -0
  315. package/dist/components/sheet/index.js +2 -0
  316. package/dist/components/sheet/meta.js +17 -0
  317. package/dist/components/sheet/meta.js.map +1 -0
  318. package/dist/components/sheet/sheet.d.ts +31 -0
  319. package/dist/components/sheet/sheet.d.ts.map +1 -0
  320. package/dist/components/sheet/sheet.js +90 -0
  321. package/dist/components/sheet/sheet.js.map +1 -0
  322. package/dist/components/skeleton/index.d.ts +2 -0
  323. package/dist/components/skeleton/index.js +2 -0
  324. package/dist/components/skeleton/meta.js +17 -0
  325. package/dist/components/skeleton/meta.js.map +1 -0
  326. package/dist/components/skeleton/skeleton.d.ts +20 -0
  327. package/dist/components/skeleton/skeleton.d.ts.map +1 -0
  328. package/dist/components/skeleton/skeleton.js +29 -0
  329. package/dist/components/skeleton/skeleton.js.map +1 -0
  330. package/dist/components/slider/index.d.ts +2 -0
  331. package/dist/components/slider/index.js +2 -0
  332. package/dist/components/slider/meta.js +17 -0
  333. package/dist/components/slider/meta.js.map +1 -0
  334. package/dist/components/slider/slider.d.ts +29 -0
  335. package/dist/components/slider/slider.d.ts.map +1 -0
  336. package/dist/components/slider/slider.js +61 -0
  337. package/dist/components/slider/slider.js.map +1 -0
  338. package/dist/components/spinner/index.d.ts +2 -0
  339. package/dist/components/spinner/index.js +2 -0
  340. package/dist/components/spinner/meta.js +17 -0
  341. package/dist/components/spinner/meta.js.map +1 -0
  342. package/dist/components/spinner/spinner.d.ts +21 -0
  343. package/dist/components/spinner/spinner.d.ts.map +1 -0
  344. package/dist/components/spinner/spinner.js +45 -0
  345. package/dist/components/spinner/spinner.js.map +1 -0
  346. package/dist/components/switch/index.d.ts +2 -0
  347. package/dist/components/switch/index.js +2 -0
  348. package/dist/components/switch/meta.js +17 -0
  349. package/dist/components/switch/meta.js.map +1 -0
  350. package/dist/components/switch/switch.d.ts +15 -0
  351. package/dist/components/switch/switch.d.ts.map +1 -0
  352. package/dist/components/switch/switch.js +21 -0
  353. package/dist/components/switch/switch.js.map +1 -0
  354. package/dist/components/table/index.d.ts +2 -0
  355. package/dist/components/table/index.js +2 -0
  356. package/dist/components/table/meta.js +17 -0
  357. package/dist/components/table/meta.js.map +1 -0
  358. package/dist/components/table/table.d.ts +41 -0
  359. package/dist/components/table/table.d.ts.map +1 -0
  360. package/dist/components/table/table.js +78 -0
  361. package/dist/components/table/table.js.map +1 -0
  362. package/dist/components/tabs/index.d.ts +2 -0
  363. package/dist/components/tabs/index.js +2 -0
  364. package/dist/components/tabs/meta.js +17 -0
  365. package/dist/components/tabs/meta.js.map +1 -0
  366. package/dist/components/tabs/tabs.d.ts +28 -0
  367. package/dist/components/tabs/tabs.d.ts.map +1 -0
  368. package/dist/components/tabs/tabs.js +58 -0
  369. package/dist/components/tabs/tabs.js.map +1 -0
  370. package/dist/components/toast/index.d.ts +3 -0
  371. package/dist/components/toast/index.js +3 -0
  372. package/dist/components/toast/meta.js +17 -0
  373. package/dist/components/toast/meta.js.map +1 -0
  374. package/dist/components/toast/toast-store.d.ts +84 -0
  375. package/dist/components/toast/toast-store.d.ts.map +1 -0
  376. package/dist/components/toast/toast-store.js +115 -0
  377. package/dist/components/toast/toast-store.js.map +1 -0
  378. package/dist/components/toast/toast.d.ts +39 -0
  379. package/dist/components/toast/toast.d.ts.map +1 -0
  380. package/dist/components/toast/toast.js +140 -0
  381. package/dist/components/toast/toast.js.map +1 -0
  382. package/dist/components/tooltip/index.d.ts +2 -0
  383. package/dist/components/tooltip/index.js +2 -0
  384. package/dist/components/tooltip/meta.js +17 -0
  385. package/dist/components/tooltip/meta.js.map +1 -0
  386. package/dist/components/tooltip/tooltip.d.ts +24 -0
  387. package/dist/components/tooltip/tooltip.d.ts.map +1 -0
  388. package/dist/components/tooltip/tooltip.js +38 -0
  389. package/dist/components/tooltip/tooltip.js.map +1 -0
  390. package/dist/index.d.ts +97 -0
  391. package/dist/index.js +51 -0
  392. package/dist/lib/styles.d.ts +21 -0
  393. package/dist/lib/styles.d.ts.map +1 -0
  394. package/dist/lib/styles.js +22 -0
  395. package/dist/lib/styles.js.map +1 -0
  396. package/dist/lib/utils.d.ts +11 -0
  397. package/dist/lib/utils.d.ts.map +1 -0
  398. package/dist/lib/utils.js +21 -0
  399. package/dist/lib/utils.js.map +1 -0
  400. package/dist/registry/blocks.d.ts +15 -0
  401. package/dist/registry/blocks.d.ts.map +1 -0
  402. package/dist/registry/blocks.js +32 -0
  403. package/dist/registry/blocks.js.map +1 -0
  404. package/dist/registry/components.d.ts +18 -0
  405. package/dist/registry/components.d.ts.map +1 -0
  406. package/dist/registry/components.js +112 -0
  407. package/dist/registry/components.js.map +1 -0
  408. package/dist/registry/schema.d.ts +44 -0
  409. package/dist/registry/schema.d.ts.map +1 -0
  410. package/dist/registry/schema.js +33 -0
  411. package/dist/registry/schema.js.map +1 -0
  412. package/package.json +74 -0
  413. package/src/blocks/admin-users/admin-users.stories.tsx +83 -0
  414. package/src/blocks/admin-users/admin-users.test.tsx +159 -0
  415. package/src/blocks/admin-users/admin-users.tsx +251 -0
  416. package/src/blocks/admin-users/index.ts +1 -0
  417. package/src/blocks/admin-users/meta.ts +27 -0
  418. package/src/blocks/ai-chat/ai-chat.stories.tsx +149 -0
  419. package/src/blocks/ai-chat/ai-chat.test.tsx +166 -0
  420. package/src/blocks/ai-chat/ai-chat.tsx +280 -0
  421. package/src/blocks/ai-chat/index.ts +7 -0
  422. package/src/blocks/ai-chat/meta.ts +32 -0
  423. package/src/blocks/dashboard/dashboard.stories.tsx +106 -0
  424. package/src/blocks/dashboard/dashboard.test.tsx +94 -0
  425. package/src/blocks/dashboard/dashboard.tsx +192 -0
  426. package/src/blocks/dashboard/index.ts +6 -0
  427. package/src/blocks/dashboard/meta.ts +18 -0
  428. package/src/blocks/forgot-password/forgot-password.stories.tsx +41 -0
  429. package/src/blocks/forgot-password/forgot-password.test.tsx +62 -0
  430. package/src/blocks/forgot-password/forgot-password.tsx +158 -0
  431. package/src/blocks/forgot-password/index.ts +1 -0
  432. package/src/blocks/forgot-password/meta.ts +18 -0
  433. package/src/blocks/login/index.ts +1 -0
  434. package/src/blocks/login/login.stories.tsx +46 -0
  435. package/src/blocks/login/login.test.tsx +100 -0
  436. package/src/blocks/login/login.tsx +178 -0
  437. package/src/blocks/login/meta.ts +18 -0
  438. package/src/blocks/pricing/index.ts +1 -0
  439. package/src/blocks/pricing/meta.ts +18 -0
  440. package/src/blocks/pricing/pricing.stories.tsx +62 -0
  441. package/src/blocks/pricing/pricing.test.tsx +101 -0
  442. package/src/blocks/pricing/pricing.tsx +176 -0
  443. package/src/blocks/settings/index.ts +6 -0
  444. package/src/blocks/settings/meta.ts +29 -0
  445. package/src/blocks/settings/settings.stories.tsx +94 -0
  446. package/src/blocks/settings/settings.test.tsx +167 -0
  447. package/src/blocks/settings/settings.tsx +317 -0
  448. package/src/blocks/signup/index.ts +1 -0
  449. package/src/blocks/signup/meta.ts +18 -0
  450. package/src/blocks/signup/signup.stories.tsx +27 -0
  451. package/src/blocks/signup/signup.test.tsx +97 -0
  452. package/src/blocks/signup/signup.tsx +240 -0
  453. package/src/components/accordion/accordion.stories.tsx +90 -0
  454. package/src/components/accordion/accordion.test.tsx +156 -0
  455. package/src/components/accordion/accordion.tsx +88 -0
  456. package/src/components/accordion/index.ts +9 -0
  457. package/src/components/accordion/meta.ts +16 -0
  458. package/src/components/activity-feed/activity-feed.stories.tsx +163 -0
  459. package/src/components/activity-feed/activity-feed.test.tsx +125 -0
  460. package/src/components/activity-feed/activity-feed.tsx +115 -0
  461. package/src/components/activity-feed/index.ts +12 -0
  462. package/src/components/activity-feed/meta.ts +17 -0
  463. package/src/components/ai-agent-status/ai-agent-status.stories.tsx +86 -0
  464. package/src/components/ai-agent-status/ai-agent-status.test.tsx +66 -0
  465. package/src/components/ai-agent-status/ai-agent-status.tsx +88 -0
  466. package/src/components/ai-agent-status/index.ts +6 -0
  467. package/src/components/ai-agent-status/meta.ts +17 -0
  468. package/src/components/ai-conversation/ai-conversation.stories.tsx +126 -0
  469. package/src/components/ai-conversation/ai-conversation.test.tsx +144 -0
  470. package/src/components/ai-conversation/ai-conversation.tsx +229 -0
  471. package/src/components/ai-conversation/index.ts +9 -0
  472. package/src/components/ai-conversation/meta.ts +20 -0
  473. package/src/components/ai-message/ai-message.stories.tsx +106 -0
  474. package/src/components/ai-message/ai-message.test.tsx +160 -0
  475. package/src/components/ai-message/ai-message.tsx +162 -0
  476. package/src/components/ai-message/index.ts +13 -0
  477. package/src/components/ai-message/meta.ts +17 -0
  478. package/src/components/ai-model-selector/ai-model-selector.stories.tsx +66 -0
  479. package/src/components/ai-model-selector/ai-model-selector.test.tsx +120 -0
  480. package/src/components/ai-model-selector/ai-model-selector.tsx +112 -0
  481. package/src/components/ai-model-selector/index.ts +1 -0
  482. package/src/components/ai-model-selector/meta.ts +17 -0
  483. package/src/components/ai-prompt-input/ai-prompt-input.stories.tsx +145 -0
  484. package/src/components/ai-prompt-input/ai-prompt-input.test.tsx +273 -0
  485. package/src/components/ai-prompt-input/ai-prompt-input.tsx +306 -0
  486. package/src/components/ai-prompt-input/index.ts +11 -0
  487. package/src/components/ai-prompt-input/meta.ts +18 -0
  488. package/src/components/ai-reasoning/ai-reasoning.stories.tsx +60 -0
  489. package/src/components/ai-reasoning/ai-reasoning.test.tsx +95 -0
  490. package/src/components/ai-reasoning/ai-reasoning.tsx +106 -0
  491. package/src/components/ai-reasoning/index.ts +7 -0
  492. package/src/components/ai-reasoning/meta.ts +17 -0
  493. package/src/components/ai-response/ai-response.stories.tsx +75 -0
  494. package/src/components/ai-response/ai-response.test.tsx +96 -0
  495. package/src/components/ai-response/ai-response.tsx +95 -0
  496. package/src/components/ai-response/index.ts +7 -0
  497. package/src/components/ai-response/meta.ts +17 -0
  498. package/src/components/ai-sources/ai-sources.stories.tsx +93 -0
  499. package/src/components/ai-sources/ai-sources.test.tsx +102 -0
  500. package/src/components/ai-sources/ai-sources.tsx +186 -0
  501. package/src/components/ai-sources/index.ts +11 -0
  502. package/src/components/ai-sources/meta.ts +17 -0
  503. package/src/components/ai-token-usage/ai-token-usage.stories.tsx +59 -0
  504. package/src/components/ai-token-usage/ai-token-usage.test.tsx +83 -0
  505. package/src/components/ai-token-usage/ai-token-usage.tsx +105 -0
  506. package/src/components/ai-token-usage/index.ts +6 -0
  507. package/src/components/ai-token-usage/meta.ts +16 -0
  508. package/src/components/ai-tool/ai-tool.stories.tsx +96 -0
  509. package/src/components/ai-tool/ai-tool.test.tsx +137 -0
  510. package/src/components/ai-tool/ai-tool.tsx +235 -0
  511. package/src/components/ai-tool/index.ts +13 -0
  512. package/src/components/ai-tool/meta.ts +17 -0
  513. package/src/components/alert/alert.stories.tsx +101 -0
  514. package/src/components/alert/alert.test.tsx +94 -0
  515. package/src/components/alert/alert.tsx +89 -0
  516. package/src/components/alert/index.ts +8 -0
  517. package/src/components/alert/meta.ts +16 -0
  518. package/src/components/avatar/avatar.stories.tsx +58 -0
  519. package/src/components/avatar/avatar.test.tsx +64 -0
  520. package/src/components/avatar/avatar.tsx +68 -0
  521. package/src/components/avatar/index.ts +9 -0
  522. package/src/components/avatar/meta.ts +15 -0
  523. package/src/components/badge/badge.stories.tsx +68 -0
  524. package/src/components/badge/badge.test.tsx +61 -0
  525. package/src/components/badge/badge.tsx +54 -0
  526. package/src/components/badge/index.ts +1 -0
  527. package/src/components/badge/meta.ts +15 -0
  528. package/src/components/button/button.stories.tsx +128 -0
  529. package/src/components/button/button.test.tsx +224 -0
  530. package/src/components/button/button.tsx +114 -0
  531. package/src/components/button/index.ts +1 -0
  532. package/src/components/button/meta.ts +16 -0
  533. package/src/components/calendar/calendar.stories.tsx +105 -0
  534. package/src/components/calendar/calendar.test.tsx +255 -0
  535. package/src/components/calendar/calendar.tsx +115 -0
  536. package/src/components/calendar/index.ts +1 -0
  537. package/src/components/calendar/meta.ts +17 -0
  538. package/src/components/card/card.stories.tsx +61 -0
  539. package/src/components/card/card.test.tsx +66 -0
  540. package/src/components/card/card.tsx +81 -0
  541. package/src/components/card/index.ts +9 -0
  542. package/src/components/card/meta.ts +16 -0
  543. package/src/components/checkbox/checkbox.stories.tsx +124 -0
  544. package/src/components/checkbox/checkbox.test.tsx +121 -0
  545. package/src/components/checkbox/checkbox.tsx +66 -0
  546. package/src/components/checkbox/index.ts +1 -0
  547. package/src/components/checkbox/meta.ts +16 -0
  548. package/src/components/code-block/code-block.stories.tsx +62 -0
  549. package/src/components/code-block/code-block.test.tsx +139 -0
  550. package/src/components/code-block/code-block.tsx +188 -0
  551. package/src/components/code-block/index.ts +1 -0
  552. package/src/components/code-block/meta.ts +17 -0
  553. package/src/components/combobox/combobox.stories.tsx +171 -0
  554. package/src/components/combobox/combobox.test.tsx +429 -0
  555. package/src/components/combobox/combobox.tsx +544 -0
  556. package/src/components/combobox/index.ts +15 -0
  557. package/src/components/combobox/meta.ts +17 -0
  558. package/src/components/command/command.stories.tsx +152 -0
  559. package/src/components/command/command.test.tsx +380 -0
  560. package/src/components/command/command.tsx +482 -0
  561. package/src/components/command/index.ts +17 -0
  562. package/src/components/command/meta.ts +18 -0
  563. package/src/components/data-table/data-table.stories.tsx +151 -0
  564. package/src/components/data-table/data-table.test.tsx +288 -0
  565. package/src/components/data-table/data-table.tsx +485 -0
  566. package/src/components/data-table/index.ts +13 -0
  567. package/src/components/data-table/meta.ts +19 -0
  568. package/src/components/date-picker/date-picker.stories.tsx +103 -0
  569. package/src/components/date-picker/date-picker.test.tsx +205 -0
  570. package/src/components/date-picker/date-picker.tsx +198 -0
  571. package/src/components/date-picker/index.ts +6 -0
  572. package/src/components/date-picker/meta.ts +18 -0
  573. package/src/components/dialog/dialog.stories.tsx +140 -0
  574. package/src/components/dialog/dialog.test.tsx +186 -0
  575. package/src/components/dialog/dialog.tsx +132 -0
  576. package/src/components/dialog/index.ts +16 -0
  577. package/src/components/dialog/meta.ts +16 -0
  578. package/src/components/drawer/drawer.stories.tsx +111 -0
  579. package/src/components/drawer/drawer.test.tsx +187 -0
  580. package/src/components/drawer/drawer.tsx +293 -0
  581. package/src/components/drawer/index.ts +16 -0
  582. package/src/components/drawer/meta.ts +16 -0
  583. package/src/components/dropdown-menu/dropdown-menu.stories.tsx +128 -0
  584. package/src/components/dropdown-menu/dropdown-menu.test.tsx +321 -0
  585. package/src/components/dropdown-menu/dropdown-menu.tsx +242 -0
  586. package/src/components/dropdown-menu/index.ts +21 -0
  587. package/src/components/dropdown-menu/meta.ts +17 -0
  588. package/src/components/empty-state/empty-state.stories.tsx +70 -0
  589. package/src/components/empty-state/empty-state.test.tsx +97 -0
  590. package/src/components/empty-state/empty-state.tsx +92 -0
  591. package/src/components/empty-state/index.ts +9 -0
  592. package/src/components/empty-state/meta.ts +16 -0
  593. package/src/components/form/form.stories.tsx +144 -0
  594. package/src/components/form/form.test.tsx +203 -0
  595. package/src/components/form/form.tsx +221 -0
  596. package/src/components/form/index.ts +13 -0
  597. package/src/components/form/meta.ts +17 -0
  598. package/src/components/input/index.ts +1 -0
  599. package/src/components/input/input.stories.tsx +84 -0
  600. package/src/components/input/input.test.tsx +108 -0
  601. package/src/components/input/input.tsx +51 -0
  602. package/src/components/input/meta.ts +15 -0
  603. package/src/components/label/index.ts +1 -0
  604. package/src/components/label/label.stories.tsx +51 -0
  605. package/src/components/label/label.test.tsx +55 -0
  606. package/src/components/label/label.tsx +26 -0
  607. package/src/components/label/meta.ts +15 -0
  608. package/src/components/pagination/index.ts +10 -0
  609. package/src/components/pagination/meta.ts +17 -0
  610. package/src/components/pagination/pagination.stories.tsx +129 -0
  611. package/src/components/pagination/pagination.test.tsx +119 -0
  612. package/src/components/pagination/pagination.tsx +142 -0
  613. package/src/components/popover/index.ts +9 -0
  614. package/src/components/popover/meta.ts +18 -0
  615. package/src/components/popover/popover.stories.tsx +84 -0
  616. package/src/components/popover/popover.test.tsx +163 -0
  617. package/src/components/popover/popover.tsx +89 -0
  618. package/src/components/progress/index.ts +1 -0
  619. package/src/components/progress/meta.ts +17 -0
  620. package/src/components/progress/progress.stories.tsx +90 -0
  621. package/src/components/progress/progress.test.tsx +78 -0
  622. package/src/components/progress/progress.tsx +70 -0
  623. package/src/components/radio-group/index.ts +6 -0
  624. package/src/components/radio-group/meta.ts +16 -0
  625. package/src/components/radio-group/radio-group.stories.tsx +102 -0
  626. package/src/components/radio-group/radio-group.test.tsx +152 -0
  627. package/src/components/radio-group/radio-group.tsx +53 -0
  628. package/src/components/select/index.ts +14 -0
  629. package/src/components/select/meta.ts +16 -0
  630. package/src/components/select/select.stories.tsx +137 -0
  631. package/src/components/select/select.test.tsx +209 -0
  632. package/src/components/select/select.tsx +222 -0
  633. package/src/components/separator/index.ts +1 -0
  634. package/src/components/separator/meta.ts +15 -0
  635. package/src/components/separator/separator.stories.tsx +42 -0
  636. package/src/components/separator/separator.test.tsx +46 -0
  637. package/src/components/separator/separator.tsx +33 -0
  638. package/src/components/sheet/index.ts +14 -0
  639. package/src/components/sheet/meta.ts +16 -0
  640. package/src/components/sheet/sheet.stories.tsx +107 -0
  641. package/src/components/sheet/sheet.test.tsx +152 -0
  642. package/src/components/sheet/sheet.tsx +160 -0
  643. package/src/components/skeleton/index.ts +1 -0
  644. package/src/components/skeleton/meta.ts +15 -0
  645. package/src/components/skeleton/skeleton.stories.tsx +46 -0
  646. package/src/components/skeleton/skeleton.test.tsx +57 -0
  647. package/src/components/skeleton/skeleton.tsx +28 -0
  648. package/src/components/slider/index.ts +1 -0
  649. package/src/components/slider/meta.ts +19 -0
  650. package/src/components/slider/slider.stories.tsx +87 -0
  651. package/src/components/slider/slider.test.tsx +148 -0
  652. package/src/components/slider/slider.tsx +135 -0
  653. package/src/components/spinner/index.ts +1 -0
  654. package/src/components/spinner/meta.ts +15 -0
  655. package/src/components/spinner/spinner.stories.tsx +47 -0
  656. package/src/components/spinner/spinner.test.tsx +41 -0
  657. package/src/components/spinner/spinner.tsx +68 -0
  658. package/src/components/switch/index.ts +1 -0
  659. package/src/components/switch/meta.ts +15 -0
  660. package/src/components/switch/switch.stories.tsx +70 -0
  661. package/src/components/switch/switch.test.tsx +101 -0
  662. package/src/components/switch/switch.tsx +42 -0
  663. package/src/components/table/index.ts +11 -0
  664. package/src/components/table/meta.ts +17 -0
  665. package/src/components/table/table.stories.tsx +131 -0
  666. package/src/components/table/table.test.tsx +153 -0
  667. package/src/components/table/table.tsx +138 -0
  668. package/src/components/tabs/index.ts +11 -0
  669. package/src/components/tabs/meta.ts +17 -0
  670. package/src/components/tabs/tabs.stories.tsx +139 -0
  671. package/src/components/tabs/tabs.test.tsx +148 -0
  672. package/src/components/tabs/tabs.tsx +106 -0
  673. package/src/components/toast/index.ts +24 -0
  674. package/src/components/toast/meta.ts +18 -0
  675. package/src/components/toast/toast-store.ts +181 -0
  676. package/src/components/toast/toast.stories.tsx +167 -0
  677. package/src/components/toast/toast.test.tsx +306 -0
  678. package/src/components/toast/toast.tsx +241 -0
  679. package/src/components/tooltip/index.ts +8 -0
  680. package/src/components/tooltip/meta.ts +17 -0
  681. package/src/components/tooltip/tooltip.stories.tsx +89 -0
  682. package/src/components/tooltip/tooltip.test.tsx +120 -0
  683. package/src/components/tooltip/tooltip.tsx +58 -0
  684. package/src/index.ts +50 -0
  685. package/src/lib/styles.ts +26 -0
  686. package/src/lib/utils.test.ts +32 -0
  687. package/src/lib/utils.ts +24 -0
  688. package/src/registry/blocks.ts +30 -0
  689. package/src/registry/components.ts +114 -0
  690. package/src/registry/meta.test.ts +234 -0
  691. package/src/registry/schema.ts +58 -0
@@ -0,0 +1,160 @@
1
+ import { render, screen } from "@testing-library/react";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { describe, expect, it } from "vitest";
4
+
5
+ import { expectNoA11yViolations } from "../../../test/a11y";
6
+ import { Button } from "../button";
7
+ import {
8
+ Message,
9
+ MessageActions,
10
+ MessageAvatar,
11
+ MessageBody,
12
+ MessageFooter,
13
+ } from "./ai-message";
14
+
15
+ describe("Message", () => {
16
+ it("renders as a list item, for a transcript", () => {
17
+ render(
18
+ <ol>
19
+ <Message from="user">
20
+ <MessageBody from="user">Hello</MessageBody>
21
+ </Message>
22
+ </ol>,
23
+ );
24
+ expect(screen.getByRole("listitem")).toBeInTheDocument();
25
+ });
26
+
27
+ it.each([
28
+ ["user", "You said"],
29
+ ["assistant", "Assistant said"],
30
+ ["system", "System"],
31
+ ] as const)("names the %s speaker in text, not only by layout", (role, label) => {
32
+ render(
33
+ <ol>
34
+ <Message from={role}>
35
+ <MessageBody from={role}>Content</MessageBody>
36
+ </Message>
37
+ </ol>,
38
+ );
39
+ // Colour and alignment convey the speaker to a sighted reader and nothing
40
+ // to anyone else, so the role has to be readable.
41
+ expect(screen.getByRole("listitem")).toHaveTextContent(label);
42
+ });
43
+
44
+ it("accepts a custom speaker label", () => {
45
+ render(
46
+ <ol>
47
+ <Message from="assistant" fromLabel="Claude said">
48
+ <MessageBody from="assistant">Hi</MessageBody>
49
+ </Message>
50
+ </ol>,
51
+ );
52
+ expect(screen.getByRole("listitem")).toHaveTextContent("Claude said");
53
+ });
54
+
55
+ it("marks the speaker for styling", () => {
56
+ render(
57
+ <ol>
58
+ <Message from="user">
59
+ <MessageBody from="user">Hello</MessageBody>
60
+ </Message>
61
+ </ol>,
62
+ );
63
+ expect(screen.getByRole("listitem")).toHaveAttribute("data-from", "user");
64
+ });
65
+
66
+ it("does not shadow the ARIA role attribute", () => {
67
+ // `from` names the speaker; `role` still reaches the element as the real
68
+ // ARIA attribute, so a consumer can override the list-item semantics.
69
+ render(
70
+ <ol>
71
+ <Message from="assistant" role="presentation">
72
+ <MessageBody from="assistant">Hi</MessageBody>
73
+ </Message>
74
+ </ol>,
75
+ );
76
+ expect(screen.queryByRole("listitem")).not.toBeInTheDocument();
77
+ });
78
+
79
+ it("hides the avatar from assistive technology", () => {
80
+ const { container } = render(
81
+ <ol>
82
+ <Message from="assistant">
83
+ <MessageAvatar>AI</MessageAvatar>
84
+ <MessageBody from="assistant">Hi</MessageBody>
85
+ </Message>
86
+ </ol>,
87
+ );
88
+ expect(container.querySelector("[data-slot='message-avatar']")).toHaveAttribute(
89
+ "aria-hidden",
90
+ "true",
91
+ );
92
+ });
93
+
94
+ it("keeps hover-revealed actions in the tab order", async () => {
95
+ const user = userEvent.setup();
96
+ render(
97
+ <ol>
98
+ <Message from="assistant">
99
+ <MessageBody from="assistant">
100
+ Hi
101
+ <MessageActions>
102
+ <Button size="icon-sm" variant="ghost" aria-label="Copy">
103
+ C
104
+ </Button>
105
+ </MessageActions>
106
+ </MessageBody>
107
+ </Message>
108
+ </ol>,
109
+ );
110
+
111
+ // Visually faded until hover, but reachable — a control that only exists on
112
+ // hover is unusable by keyboard and invisible on touch.
113
+ await user.tab();
114
+ expect(screen.getByRole("button", { name: "Copy" })).toHaveFocus();
115
+ });
116
+
117
+ it("renders a footer for attachments and citations", () => {
118
+ render(
119
+ <ol>
120
+ <Message from="assistant">
121
+ <MessageBody from="assistant">
122
+ Hi
123
+ <MessageFooter>
124
+ <span>2 sources</span>
125
+ </MessageFooter>
126
+ </MessageBody>
127
+ </Message>
128
+ </ol>,
129
+ );
130
+ expect(screen.getByText("2 sources")).toBeInTheDocument();
131
+ });
132
+
133
+ it("lets a consumer className override a conflicting utility", () => {
134
+ render(
135
+ <ol>
136
+ <Message from="user" className="gap-8">
137
+ <MessageBody from="user">Hi</MessageBody>
138
+ </Message>
139
+ </ol>,
140
+ );
141
+ const item = screen.getByRole("listitem");
142
+ expect(item).toHaveClass("gap-8");
143
+ expect(item).not.toHaveClass("gap-3");
144
+ });
145
+
146
+ it("has no accessibility violations", async () => {
147
+ const { container } = render(
148
+ <ol>
149
+ <Message from="user">
150
+ <MessageBody from="user">What is the capital of France?</MessageBody>
151
+ </Message>
152
+ <Message from="assistant">
153
+ <MessageAvatar>AI</MessageAvatar>
154
+ <MessageBody from="assistant">Paris.</MessageBody>
155
+ </Message>
156
+ </ol>,
157
+ );
158
+ await expectNoA11yViolations(container);
159
+ });
160
+ });
@@ -0,0 +1,162 @@
1
+ "use client";
2
+
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { Slot } from "radix-ui";
5
+ import type { ComponentPropsWithRef } from "react";
6
+
7
+ import { cn } from "@/lib/utils";
8
+
9
+ /**
10
+ * One turn in a conversation.
11
+ *
12
+ * The role is stated in text, not only in layout. Alignment and colour are how
13
+ * a sighted reader tells a question from an answer; a screen reader user gets
14
+ * nothing from either, so every message carries a visually hidden label naming
15
+ * who is speaking.
16
+ */
17
+
18
+ const messageVariants = cva("group/message flex w-full gap-3", {
19
+ variants: {
20
+ role: {
21
+ user: "flex-row-reverse",
22
+ assistant: "flex-row",
23
+ system: "flex-row",
24
+ },
25
+ },
26
+ defaultVariants: {
27
+ role: "assistant",
28
+ },
29
+ });
30
+
31
+ const messageBodyVariants = cva("min-w-0 rounded-xl px-4 py-3 text-sm", {
32
+ variants: {
33
+ role: {
34
+ user: "max-w-[85%] bg-primary text-primary-foreground",
35
+ assistant: "w-full bg-transparent px-0 py-0 text-foreground",
36
+ system:
37
+ "w-full border border-dashed border-border bg-muted/40 text-xs text-muted-foreground",
38
+ },
39
+ },
40
+ defaultVariants: {
41
+ role: "assistant",
42
+ },
43
+ });
44
+
45
+ export type MessageRole = "user" | "assistant" | "system";
46
+
47
+ export interface MessageProps
48
+ extends ComponentPropsWithRef<"li">, Omit<VariantProps<typeof messageVariants>, "role"> {
49
+ /**
50
+ * Who is speaking.
51
+ *
52
+ * Named `from` rather than `role` on purpose. `role` is a global HTML
53
+ * attribute, and a component prop that shadows it cannot be told apart from
54
+ * the real thing by static analysis — every consumer's accessibility linter
55
+ * would flag ordinary usage of this component. The values are still the
56
+ * familiar conversation roles.
57
+ */
58
+ from?: MessageRole;
59
+ /** Overrides the visually hidden speaker label. */
60
+ fromLabel?: string;
61
+ }
62
+
63
+ const DEFAULT_ROLE_LABELS: Record<MessageRole, string> = {
64
+ user: "You said",
65
+ assistant: "Assistant said",
66
+ system: "System",
67
+ };
68
+
69
+ export function Message({
70
+ className,
71
+ from = "assistant",
72
+ fromLabel,
73
+ children,
74
+ ...props
75
+ }: MessageProps) {
76
+ return (
77
+ <li
78
+ data-slot="message"
79
+ data-from={from}
80
+ className={cn(messageVariants({ role: from }), className)}
81
+ {...props}
82
+ >
83
+ {/* Names the speaker for anyone who cannot see the layout. */}
84
+ <span className="sr-only">{fromLabel ?? DEFAULT_ROLE_LABELS[from]}:</span>
85
+ {children}
86
+ </li>
87
+ );
88
+ }
89
+
90
+ export interface MessageBodyProps
91
+ extends ComponentPropsWithRef<"div">, Omit<VariantProps<typeof messageBodyVariants>, "role"> {
92
+ /** Who is speaking. See the note on MessageProps for why not `role`. */
93
+ from?: MessageRole;
94
+ }
95
+
96
+ export function MessageBody({ className, from = "assistant", ...props }: MessageBodyProps) {
97
+ return (
98
+ <div
99
+ data-slot="message-body"
100
+ className={cn(messageBodyVariants({ role: from }), className)}
101
+ {...props}
102
+ />
103
+ );
104
+ }
105
+
106
+ export interface MessageAvatarProps extends ComponentPropsWithRef<"div"> {
107
+ asChild?: boolean;
108
+ }
109
+
110
+ /** Decorative: the speaker is already named by the hidden label on Message. */
111
+ export function MessageAvatar({ className, asChild, ...props }: MessageAvatarProps) {
112
+ const Comp = asChild ? Slot.Root : "div";
113
+
114
+ return (
115
+ <Comp
116
+ data-slot="message-avatar"
117
+ aria-hidden="true"
118
+ className={cn(
119
+ "grid size-7 shrink-0 place-items-center rounded-full border border-border bg-muted",
120
+ "text-xs font-medium text-muted-foreground",
121
+ "[&_svg:not([class*='size-'])]:size-3.5",
122
+ className,
123
+ )}
124
+ {...props}
125
+ />
126
+ );
127
+ }
128
+
129
+ /**
130
+ * Per-message controls: copy, regenerate, feedback.
131
+ *
132
+ * Revealed on hover for pointer users but always present in the DOM and in the
133
+ * tab order — hiding controls behind hover makes them unreachable by keyboard
134
+ * and invisible on touch.
135
+ */
136
+ export function MessageActions({ className, ...props }: ComponentPropsWithRef<"div">) {
137
+ return (
138
+ <div
139
+ data-slot="message-actions"
140
+ className={cn(
141
+ "mt-1.5 flex items-center gap-1",
142
+ "opacity-0 transition-opacity duration-[var(--duration-fast)]",
143
+ "group-focus-within/message:opacity-100 group-hover/message:opacity-100",
144
+ className,
145
+ )}
146
+ {...props}
147
+ />
148
+ );
149
+ }
150
+
151
+ /** Attachments, citations and other content that hangs off a message. */
152
+ export function MessageFooter({ className, ...props }: ComponentPropsWithRef<"div">) {
153
+ return (
154
+ <div
155
+ data-slot="message-footer"
156
+ className={cn("mt-2 flex flex-wrap items-center gap-2", className)}
157
+ {...props}
158
+ />
159
+ );
160
+ }
161
+
162
+ export { messageBodyVariants, messageVariants };
@@ -0,0 +1,13 @@
1
+ export {
2
+ Message,
3
+ MessageActions,
4
+ MessageAvatar,
5
+ MessageBody,
6
+ MessageFooter,
7
+ messageBodyVariants,
8
+ messageVariants,
9
+ type MessageAvatarProps,
10
+ type MessageBodyProps,
11
+ type MessageProps,
12
+ type MessageRole,
13
+ } from "./ai-message";
@@ -0,0 +1,17 @@
1
+ import { defineMeta } from "@/registry/schema";
2
+
3
+ export const meta = defineMeta({
4
+ name: "ai-message",
5
+ title: "AI Message",
6
+ description: "One turn in a conversation, with role, avatar, actions and footer slots.",
7
+ category: "ai",
8
+ status: "stable",
9
+ dependencies: ["class-variance-authority", "radix-ui"],
10
+ registryDependencies: [],
11
+ files: ["ai-message.tsx"],
12
+ a11y:
13
+ "Every message carries a visually hidden label naming the speaker. Alignment and colour tell " +
14
+ "a sighted reader who is talking and tell a screen reader user nothing, so the role is always " +
15
+ "in text. Message actions fade in on hover but stay in the DOM and in the tab order — a " +
16
+ "control that only exists on hover is unreachable by keyboard and invisible on touch.",
17
+ });
@@ -0,0 +1,66 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+
3
+ import { Badge } from "@/components/badge";
4
+
5
+ import { ModelSelector, type ModelOption } from "./ai-model-selector";
6
+
7
+ const MODELS: ModelOption[] = [
8
+ {
9
+ id: "fast",
10
+ name: "Fast",
11
+ description: "Lowest latency. Good for short answers.",
12
+ group: "General",
13
+ },
14
+ {
15
+ id: "balanced",
16
+ name: "Balanced",
17
+ description: "The default for most work.",
18
+ group: "General",
19
+ badge: (
20
+ <Badge size="sm" variant="secondary">
21
+ Default
22
+ </Badge>
23
+ ),
24
+ },
25
+ {
26
+ id: "deep",
27
+ name: "Deep Research",
28
+ description: "Multi-step research with citations.",
29
+ group: "Advanced",
30
+ },
31
+ {
32
+ id: "vision",
33
+ name: "Vision Pro",
34
+ group: "Advanced",
35
+ disabled: true,
36
+ disabledReason: "Available on the Team plan",
37
+ },
38
+ ];
39
+
40
+ const meta = {
41
+ title: "AI/Model Selector",
42
+ component: ModelSelector,
43
+ args: { models: MODELS, defaultValue: "balanced", "aria-label": "Model" },
44
+ parameters: { controls: { disable: true } },
45
+ } satisfies Meta<typeof ModelSelector>;
46
+
47
+ export default meta;
48
+ type Story = StoryObj<typeof meta>;
49
+
50
+ /** The trigger shows only the model name; descriptions stay in the list. */
51
+ export const Default: Story = {};
52
+
53
+ export const Ungrouped: Story = {
54
+ args: {
55
+ models: [
56
+ { id: "a", name: "Model A", description: "Fast and cheap." },
57
+ { id: "b", name: "Model B", description: "Slower and stronger." },
58
+ ],
59
+ defaultValue: "a",
60
+ },
61
+ };
62
+
63
+ /** A disabled model always says why. Otherwise it reads as a broken interface. */
64
+ export const WithUnavailableModel: Story = {
65
+ args: { defaultValue: "fast" },
66
+ };
@@ -0,0 +1,120 @@
1
+ import { render, screen, waitFor } from "@testing-library/react";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { describe, expect, it, vi } from "vitest";
4
+
5
+ import { expectNoA11yViolations } from "../../../test/a11y";
6
+ import { ModelSelector, type ModelOption } from "./ai-model-selector";
7
+
8
+ const MODELS: ModelOption[] = [
9
+ { id: "fast", name: "Fast", description: "Quick answers.", group: "General" },
10
+ { id: "balanced", name: "Balanced", description: "The default.", group: "General" },
11
+ {
12
+ id: "deep",
13
+ name: "Deep Research",
14
+ group: "Advanced",
15
+ disabled: true,
16
+ disabledReason: "Available on the Pro plan",
17
+ },
18
+ ];
19
+
20
+ describe("ModelSelector", () => {
21
+ it("shows a placeholder until a model is chosen", () => {
22
+ render(<ModelSelector models={MODELS} aria-label="Model" />);
23
+ expect(screen.getByRole("combobox")).toHaveTextContent("Select a model");
24
+ });
25
+
26
+ it("lists the models, grouped", async () => {
27
+ const user = userEvent.setup();
28
+ render(<ModelSelector models={MODELS} aria-label="Model" />);
29
+
30
+ await user.click(screen.getByRole("combobox"));
31
+ expect(await screen.findByRole("option", { name: /Fast/ })).toBeInTheDocument();
32
+ expect(screen.getByText("General")).toBeInTheDocument();
33
+ expect(screen.getByText("Advanced")).toBeInTheDocument();
34
+ });
35
+
36
+ it("shows each model's description", async () => {
37
+ const user = userEvent.setup();
38
+ render(<ModelSelector models={MODELS} aria-label="Model" />);
39
+
40
+ await user.click(screen.getByRole("combobox"));
41
+ expect(await screen.findByText("Quick answers.")).toBeInTheDocument();
42
+ });
43
+
44
+ it("says why an unavailable model cannot be chosen", async () => {
45
+ const user = userEvent.setup();
46
+ render(<ModelSelector models={MODELS} aria-label="Model" />);
47
+
48
+ await user.click(screen.getByRole("combobox"));
49
+ // A disabled option with no reason reads as a broken interface.
50
+ expect(await screen.findByText("Available on the Pro plan")).toBeInTheDocument();
51
+ });
52
+
53
+ it("does not select a disabled model", async () => {
54
+ const onValueChange = vi.fn();
55
+ const user = userEvent.setup();
56
+ render(<ModelSelector models={MODELS} aria-label="Model" onValueChange={onValueChange} />);
57
+
58
+ await user.click(screen.getByRole("combobox"));
59
+ await user.click(await screen.findByRole("option", { name: /Deep Research/ }));
60
+ expect(onValueChange).not.toHaveBeenCalled();
61
+ });
62
+
63
+ it("reports the chosen model", async () => {
64
+ const onValueChange = vi.fn();
65
+ const user = userEvent.setup();
66
+ render(<ModelSelector models={MODELS} aria-label="Model" onValueChange={onValueChange} />);
67
+
68
+ await user.click(screen.getByRole("combobox"));
69
+ await user.click(await screen.findByRole("option", { name: /Balanced/ }));
70
+ expect(onValueChange).toHaveBeenCalledWith("balanced");
71
+ });
72
+
73
+ it("shows the chosen model's name, not its description", async () => {
74
+ render(<ModelSelector models={MODELS} aria-label="Model" defaultValue="fast" />);
75
+
76
+ await waitFor(() => {
77
+ expect(screen.getByRole("combobox")).toHaveTextContent("Fast");
78
+ });
79
+ expect(screen.getByRole("combobox")).not.toHaveTextContent("Quick answers.");
80
+ });
81
+
82
+ it("keeps the order it was given rather than sorting groups", async () => {
83
+ const user = userEvent.setup();
84
+ render(<ModelSelector models={MODELS} aria-label="Model" />);
85
+
86
+ await user.click(screen.getByRole("combobox"));
87
+ const options = await screen.findAllByRole("option");
88
+ expect(options.map((option) => option.textContent?.slice(0, 4))).toEqual([
89
+ "Fast",
90
+ "Bala",
91
+ "Deep",
92
+ ]);
93
+ });
94
+
95
+ it("works without groups", async () => {
96
+ const user = userEvent.setup();
97
+ render(
98
+ <ModelSelector
99
+ models={[
100
+ { id: "a", name: "Model A" },
101
+ { id: "b", name: "Model B" },
102
+ ]}
103
+ aria-label="Model"
104
+ />,
105
+ );
106
+
107
+ await user.click(screen.getByRole("combobox"));
108
+ expect(await screen.findByRole("option", { name: "Model A" })).toBeInTheDocument();
109
+ });
110
+
111
+ it("has no accessibility violations", async () => {
112
+ const { container } = render(
113
+ <>
114
+ <span id="model-label">Model</span>
115
+ <ModelSelector models={MODELS} aria-labelledby="model-label" />
116
+ </>,
117
+ );
118
+ await expectNoA11yViolations(container);
119
+ });
120
+ });
@@ -0,0 +1,112 @@
1
+ "use client";
2
+
3
+ import type { ComponentPropsWithRef, ReactNode } from "react";
4
+
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectGroup,
9
+ SelectItem,
10
+ SelectLabel,
11
+ SelectTrigger,
12
+ SelectValue,
13
+ } from "@/components/select";
14
+ import { cn } from "@/lib/utils";
15
+
16
+ /**
17
+ * Picks the model a conversation runs on.
18
+ *
19
+ * A thin, opinionated layer over Select rather than a new control: model
20
+ * pickers differ between products in what they show, not in how they behave.
21
+ * What this adds is the shape of the option — a name, a short description, and
22
+ * the fact that some models are unavailable on the current plan — which is the
23
+ * part every implementation gets wrong in the same way, by hiding the reason a
24
+ * model cannot be chosen.
25
+ */
26
+
27
+ export interface ModelOption {
28
+ id: string;
29
+ name: string;
30
+ /** One line on what the model is for. */
31
+ description?: string;
32
+ /** Grouping, for example a provider name. */
33
+ group?: string;
34
+ disabled?: boolean;
35
+ /**
36
+ * Why it is unavailable.
37
+ *
38
+ * Shown and announced alongside the name. A disabled option with no reason
39
+ * makes the user think the interface is broken.
40
+ */
41
+ disabledReason?: string;
42
+ badge?: ReactNode;
43
+ }
44
+
45
+ export interface ModelSelectorProps extends Omit<
46
+ ComponentPropsWithRef<typeof SelectTrigger>,
47
+ "children"
48
+ > {
49
+ models: ModelOption[];
50
+ value?: string;
51
+ defaultValue?: string;
52
+ onValueChange?: (value: string) => void;
53
+ placeholder?: string;
54
+ }
55
+
56
+ export function ModelSelector({
57
+ className,
58
+ models,
59
+ value,
60
+ defaultValue,
61
+ onValueChange,
62
+ placeholder = "Select a model",
63
+ ...props
64
+ }: ModelSelectorProps) {
65
+ // Preserves the order the caller gave, rather than sorting group names.
66
+ const groups = new Map<string, ModelOption[]>();
67
+ for (const model of models) {
68
+ const key = model.group ?? "";
69
+ groups.set(key, [...(groups.get(key) ?? []), model]);
70
+ }
71
+
72
+ return (
73
+ <Select value={value} defaultValue={defaultValue} onValueChange={onValueChange}>
74
+ <SelectTrigger
75
+ data-slot="model-selector"
76
+ className={cn("w-auto min-w-44 gap-2", className)}
77
+ {...props}
78
+ >
79
+ <SelectValue placeholder={placeholder} />
80
+ </SelectTrigger>
81
+ <SelectContent className="min-w-64">
82
+ {[...groups].map(([group, groupModels]) => (
83
+ <SelectGroup key={group || "ungrouped"}>
84
+ {group ? <SelectLabel>{group}</SelectLabel> : null}
85
+ {groupModels.map((model) => (
86
+ <SelectItem
87
+ key={model.id}
88
+ value={model.id}
89
+ disabled={model.disabled}
90
+ textValue={model.name}
91
+ // Only the name reaches the trigger; the description stays in
92
+ // the list where there is room for it.
93
+ label={model.name}
94
+ >
95
+ <span className="flex min-w-0 flex-col gap-0.5">
96
+ <span className="flex items-center gap-2">{model.badge}</span>
97
+ {model.disabled && model.disabledReason ? (
98
+ <span className="text-2xs text-muted-foreground">
99
+ {model.disabledReason}
100
+ </span>
101
+ ) : model.description ? (
102
+ <span className="text-2xs text-muted-foreground">{model.description}</span>
103
+ ) : null}
104
+ </span>
105
+ </SelectItem>
106
+ ))}
107
+ </SelectGroup>
108
+ ))}
109
+ </SelectContent>
110
+ </Select>
111
+ );
112
+ }
@@ -0,0 +1 @@
1
+ export { ModelSelector, type ModelOption, type ModelSelectorProps } from "./ai-model-selector";
@@ -0,0 +1,17 @@
1
+ import { defineMeta } from "@/registry/schema";
2
+
3
+ export const meta = defineMeta({
4
+ name: "ai-model-selector",
5
+ title: "AI Model Selector",
6
+ description: "Picks the model a conversation runs on, with descriptions and availability.",
7
+ category: "ai",
8
+ status: "stable",
9
+ dependencies: [],
10
+ registryDependencies: ["select"],
11
+ files: ["ai-model-selector.tsx"],
12
+ a11y:
13
+ "Inherits Select's listbox keyboard model. Each option sets textValue to the model name so " +
14
+ "typeahead matches the name rather than the description. A disabled model shows and " +
15
+ "announces why it is unavailable — a disabled option with no reason reads as a broken " +
16
+ "interface.",
17
+ });