@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,106 @@
1
+ import type { Decorator, Meta, StoryObj } from "@storybook/react-vite";
2
+
3
+ import { Button } from "@/components/button";
4
+
5
+ import { DashboardBlock, type DashboardEvent, type DashboardStat } from "./dashboard";
6
+
7
+ /** Named so its type is nameable in declaration output (TS2883). */
8
+ const withPageWidth: Decorator = (Story) => (
9
+ <div className="w-[64rem] max-w-full">
10
+ <Story />
11
+ </div>
12
+ );
13
+
14
+ const STATS: DashboardStat[] = [
15
+ {
16
+ id: "mrr",
17
+ label: "Monthly revenue",
18
+ value: "$48,120",
19
+ change: 12.4,
20
+ comparison: "on last month",
21
+ },
22
+ {
23
+ id: "users",
24
+ label: "Active users",
25
+ value: "2,410",
26
+ change: 4.2,
27
+ comparison: "on last week",
28
+ },
29
+ {
30
+ id: "churn",
31
+ label: "Churn",
32
+ value: "1.8%",
33
+ change: 0.4,
34
+ comparison: "on last month",
35
+ higherIsBetter: false,
36
+ },
37
+ { id: "uptime", label: "Uptime", value: "99.98%" },
38
+ ];
39
+
40
+ const EVENTS: DashboardEvent[] = [
41
+ {
42
+ id: "1",
43
+ title: "Deployed to production",
44
+ detail: "Build 1420 · main",
45
+ at: "2026-09-01T09:12:00Z",
46
+ label: "12 minutes ago",
47
+ tone: "success",
48
+ },
49
+ {
50
+ id: "2",
51
+ title: "Build finished with warnings",
52
+ detail: "3 unused exports",
53
+ at: "2026-09-01T09:04:00Z",
54
+ label: "20 minutes ago",
55
+ tone: "warning",
56
+ },
57
+ {
58
+ id: "3",
59
+ title: "Build failed",
60
+ detail: "Type error in table.tsx",
61
+ at: "2026-09-01T08:31:00Z",
62
+ label: "53 minutes ago",
63
+ tone: "destructive",
64
+ },
65
+ {
66
+ id: "4",
67
+ title: "Opened pull request #482",
68
+ at: "2026-08-31T17:20:00Z",
69
+ label: "Yesterday",
70
+ },
71
+ ];
72
+
73
+ const meta = {
74
+ title: "Blocks/Dashboard",
75
+ component: DashboardBlock,
76
+ args: { stats: STATS, events: EVENTS },
77
+ parameters: { controls: { disable: true } },
78
+ decorators: [withPageWidth],
79
+ } satisfies Meta<typeof DashboardBlock>;
80
+
81
+ export default meta;
82
+ type Story = StoryObj<typeof meta>;
83
+
84
+ /** Every change is stated in words — "up 12.4%", not a green triangle. */
85
+ export const Default: Story = {};
86
+
87
+ export const Loading: Story = {
88
+ args: { loading: true },
89
+ };
90
+
91
+ export const MetricsOnly: Story = {
92
+ args: { events: [] },
93
+ };
94
+
95
+ export const WithActions: Story = {
96
+ args: {
97
+ actions: (
98
+ <div className="flex gap-2">
99
+ <Button variant="outline" size="sm">
100
+ Last 30 days
101
+ </Button>
102
+ <Button size="sm">Export</Button>
103
+ </div>
104
+ ),
105
+ },
106
+ };
@@ -0,0 +1,94 @@
1
+ import { render, screen, within } from "@testing-library/react";
2
+ import { describe, expect, it } from "vitest";
3
+
4
+ import { expectNoA11yViolations } from "../../../test/a11y";
5
+ import { DashboardBlock, type DashboardEvent, type DashboardStat } from "./dashboard";
6
+
7
+ const STATS: DashboardStat[] = [
8
+ {
9
+ id: "mrr",
10
+ label: "Monthly revenue",
11
+ value: "$48,120",
12
+ change: 12.4,
13
+ comparison: "on last month",
14
+ },
15
+ { id: "churn", label: "Churn", value: "1.8%", change: 0.4, higherIsBetter: false },
16
+ { id: "users", label: "Active users", value: "2,410", change: -3.1 },
17
+ { id: "uptime", label: "Uptime", value: "99.98%" },
18
+ ];
19
+
20
+ const EVENTS: DashboardEvent[] = [
21
+ {
22
+ id: "1",
23
+ title: "Deployed to production",
24
+ at: "2026-09-01T09:12:00Z",
25
+ label: "12 minutes ago",
26
+ tone: "success",
27
+ },
28
+ {
29
+ id: "2",
30
+ title: "Build failed",
31
+ detail: "Type error in table.tsx",
32
+ at: "2026-09-01T08:40:00Z",
33
+ label: "44 minutes ago",
34
+ tone: "destructive",
35
+ },
36
+ ];
37
+
38
+ describe("DashboardBlock", () => {
39
+ it("renders each metric", () => {
40
+ render(<DashboardBlock stats={STATS} />);
41
+ expect(screen.getByText("$48,120")).toBeInTheDocument();
42
+ expect(screen.getByText("Active users")).toBeInTheDocument();
43
+ });
44
+
45
+ it("puts the metrics in a named region", () => {
46
+ render(<DashboardBlock stats={STATS} />);
47
+ expect(screen.getByRole("region", { name: "Key metrics" })).toBeInTheDocument();
48
+ });
49
+
50
+ it("states each change in words, not by a coloured arrow", () => {
51
+ render(<DashboardBlock stats={STATS} />);
52
+ expect(screen.getByText(/up 12\.4%/)).toBeInTheDocument();
53
+ expect(screen.getByText(/down 3\.1%/)).toBeInTheDocument();
54
+ });
55
+
56
+ it("knows a rise is not always good", () => {
57
+ render(<DashboardBlock stats={STATS} />);
58
+
59
+ // Churn rising is bad; revenue rising is good. Same sign, opposite meaning.
60
+ const churn = screen.getByText(/up 0\.4%/);
61
+ const revenue = screen.getByText(/up 12\.4%/);
62
+ expect(churn).toHaveClass("text-destructive");
63
+ expect(revenue).toHaveClass("text-success");
64
+ });
65
+
66
+ it("omits the change when there is nothing to compare to", () => {
67
+ render(<DashboardBlock stats={[STATS[3]!]} />);
68
+ expect(screen.queryByText(/up |down /)).not.toBeInTheDocument();
69
+ });
70
+
71
+ it("renders the activity feed as an ordered list", () => {
72
+ render(<DashboardBlock stats={STATS} events={EVENTS} />);
73
+
74
+ const list = screen.getByRole("list");
75
+ expect(list.tagName).toBe("OL");
76
+ expect(within(list).getAllByRole("listitem")).toHaveLength(2);
77
+ });
78
+
79
+ it("shows placeholders while loading, with no numbers to misread", () => {
80
+ render(<DashboardBlock stats={STATS} events={EVENTS} loading />);
81
+ expect(screen.queryByText("$48,120")).not.toBeInTheDocument();
82
+ expect(screen.queryByText(/up 12\.4%/)).not.toBeInTheDocument();
83
+ });
84
+
85
+ it("renders actions beside the heading", () => {
86
+ render(<DashboardBlock stats={STATS} actions={<button type="button">Export</button>} />);
87
+ expect(screen.getByRole("button", { name: "Export" })).toBeInTheDocument();
88
+ });
89
+
90
+ it("has no accessibility violations", async () => {
91
+ const { container } = render(<DashboardBlock stats={STATS} events={EVENTS} />);
92
+ await expectNoA11yViolations(container);
93
+ });
94
+ });
@@ -0,0 +1,192 @@
1
+ "use client";
2
+
3
+ import type { ReactNode } from "react";
4
+
5
+ import {
6
+ ActivityContent,
7
+ ActivityDescription,
8
+ ActivityFeed,
9
+ ActivityIndicator,
10
+ ActivityItem,
11
+ ActivityTime,
12
+ ActivityTitle,
13
+ } from "@/components/activity-feed";
14
+ import { Badge } from "@/components/badge";
15
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/card";
16
+ import { Skeleton } from "@/components/skeleton";
17
+ import { cn } from "@/lib/utils";
18
+
19
+ /**
20
+ * An overview page: headline numbers and what happened recently.
21
+ *
22
+ * The trend on a stat is stated in words as well as by direction and colour —
23
+ * "up 12.4%" rather than a green triangle — because a triangle is unreadable to
24
+ * a screen reader and ambiguous to anyone who cannot tell the colours apart.
25
+ */
26
+
27
+ export interface DashboardStat {
28
+ id: string;
29
+ label: string;
30
+ value: string;
31
+ /** Signed change, e.g. 12.4 or -3.1. Omit when there is nothing to compare to. */
32
+ change?: number;
33
+ /** What the change is measured against. */
34
+ comparison?: string;
35
+ /** Whether a rise is good. Churn going up is not. */
36
+ higherIsBetter?: boolean;
37
+ }
38
+
39
+ export interface DashboardEvent {
40
+ id: string;
41
+ title: string;
42
+ detail?: string;
43
+ /** Machine-readable timestamp. */
44
+ at: string;
45
+ /** Human label, e.g. "12 minutes ago". */
46
+ label: string;
47
+ tone?: "default" | "success" | "warning" | "destructive";
48
+ }
49
+
50
+ export interface DashboardBlockProps {
51
+ title?: string;
52
+ description?: string;
53
+ stats: DashboardStat[];
54
+ events?: DashboardEvent[];
55
+ /** Renders placeholders instead of content. */
56
+ loading?: boolean;
57
+ /** Anything to put beside the heading — a date range picker, an action. */
58
+ actions?: ReactNode;
59
+ className?: string;
60
+ }
61
+
62
+ function formatChange(change: number): string {
63
+ const rounded = Math.abs(change).toFixed(1);
64
+ return `${change >= 0 ? "up" : "down"} ${rounded}%`;
65
+ }
66
+
67
+ export function DashboardBlock({
68
+ title = "Overview",
69
+ description = "How things are going.",
70
+ stats,
71
+ events = [],
72
+ loading = false,
73
+ actions,
74
+ className,
75
+ }: DashboardBlockProps) {
76
+ return (
77
+ <div className={cn("flex flex-col gap-6", className)}>
78
+ <div className="flex flex-wrap items-end justify-between gap-3">
79
+ <div>
80
+ <h1 className="text-xl font-semibold tracking-tight">{title}</h1>
81
+ <p className="mt-1 text-sm text-muted-foreground">{description}</p>
82
+ </div>
83
+ {actions}
84
+ </div>
85
+
86
+ <section aria-label="Key metrics" className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
87
+ {stats.map((stat) => {
88
+ const good =
89
+ stat.change === undefined
90
+ ? undefined
91
+ : (stat.higherIsBetter ?? true)
92
+ ? stat.change >= 0
93
+ : stat.change < 0;
94
+
95
+ return (
96
+ <Card key={stat.id}>
97
+ <CardHeader className="pb-2">
98
+ <CardDescription>{stat.label}</CardDescription>
99
+ {/* Not a heading: a number is data, and making it one both
100
+ breaks the heading order and litters the outline. */}
101
+ <p className="text-2xl leading-tight font-semibold tracking-tight tabular-nums">
102
+ {loading ? <Skeleton className="h-7 w-24" /> : stat.value}
103
+ </p>
104
+ </CardHeader>
105
+ <CardContent>
106
+ {loading ? (
107
+ <Skeleton className="h-4 w-32" />
108
+ ) : stat.change === undefined ? null : (
109
+ <p className={cn("text-xs", good ? "text-success" : "text-destructive")}>
110
+ {/* In words: direction and magnitude, not a coloured arrow. */}
111
+ {formatChange(stat.change)}
112
+ {stat.comparison ? (
113
+ <span className="text-muted-foreground"> {stat.comparison}</span>
114
+ ) : null}
115
+ </p>
116
+ )}
117
+ </CardContent>
118
+ </Card>
119
+ );
120
+ })}
121
+ </section>
122
+
123
+ {events.length > 0 || loading ? (
124
+ <Card>
125
+ <CardHeader>
126
+ <CardTitle asChild>
127
+ <h2>Recent activity</h2>
128
+ </CardTitle>
129
+ <CardDescription>The last few things that happened.</CardDescription>
130
+ </CardHeader>
131
+ <CardContent>
132
+ {loading ? (
133
+ <div className="flex flex-col gap-4">
134
+ {[0, 1, 2].map((index) => (
135
+ <div key={index} className="flex gap-3">
136
+ <Skeleton className="size-6 rounded-full" />
137
+ <div className="flex-1 space-y-2">
138
+ <Skeleton className="h-4 w-48" />
139
+ <Skeleton className="h-3 w-24" />
140
+ </div>
141
+ </div>
142
+ ))}
143
+ </div>
144
+ ) : (
145
+ <ActivityFeed>
146
+ {events.map((event, index) => (
147
+ <ActivityItem key={event.id} last={index === events.length - 1}>
148
+ <ActivityIndicator
149
+ className={cn(
150
+ event.tone === "success" && "border-success/40 text-success",
151
+ event.tone === "warning" && "border-warning/40 text-warning",
152
+ event.tone === "destructive" &&
153
+ "border-destructive/40 text-destructive",
154
+ )}
155
+ />
156
+ <ActivityContent>
157
+ <ActivityTitle className="flex flex-wrap items-center gap-2">
158
+ {event.title}
159
+ {event.tone && event.tone !== "default" ? (
160
+ <Badge
161
+ size="sm"
162
+ variant={
163
+ event.tone === "success"
164
+ ? "success"
165
+ : event.tone === "warning"
166
+ ? "warning"
167
+ : "destructive"
168
+ }
169
+ >
170
+ {event.tone === "success"
171
+ ? "Succeeded"
172
+ : event.tone === "warning"
173
+ ? "Warning"
174
+ : "Failed"}
175
+ </Badge>
176
+ ) : null}
177
+ </ActivityTitle>
178
+ {event.detail ? (
179
+ <ActivityDescription>{event.detail}</ActivityDescription>
180
+ ) : null}
181
+ <ActivityTime dateTime={event.at}>{event.label}</ActivityTime>
182
+ </ActivityContent>
183
+ </ActivityItem>
184
+ ))}
185
+ </ActivityFeed>
186
+ )}
187
+ </CardContent>
188
+ </Card>
189
+ ) : null}
190
+ </div>
191
+ );
192
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ DashboardBlock,
3
+ type DashboardBlockProps,
4
+ type DashboardEvent,
5
+ type DashboardStat,
6
+ } from "./dashboard";
@@ -0,0 +1,18 @@
1
+ import { defineMeta } from "@/registry/schema";
2
+
3
+ export const meta = defineMeta({
4
+ name: "dashboard",
5
+ kind: "block",
6
+ title: "Dashboard",
7
+ description: "An overview page with headline metrics and a recent activity feed.",
8
+ category: "data",
9
+ status: "stable",
10
+ dependencies: [],
11
+ registryDependencies: ["activity-feed", "badge", "card", "skeleton"],
12
+ files: ["dashboard.tsx"],
13
+ a11y:
14
+ 'Each metric states its change in words — "up 12.4%" — rather than by a coloured arrow, ' +
15
+ "which is unreadable to a screen reader and ambiguous to anyone who cannot distinguish the " +
16
+ "colours. Whether a rise is good is configurable, since churn going up is not. The metrics " +
17
+ "sit in a named region so they can be jumped to.",
18
+ });
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { useState } from "react";
3
+
4
+ import { ForgotPasswordBlock } from "./forgot-password";
5
+
6
+ const meta = {
7
+ title: "Blocks/Forgot password",
8
+ component: ForgotPasswordBlock,
9
+ parameters: { layout: "centered", controls: { disable: true } },
10
+ } satisfies Meta<typeof ForgotPasswordBlock>;
11
+
12
+ export default meta;
13
+ type Story = StoryObj<typeof meta>;
14
+
15
+ export const Default: Story = {};
16
+
17
+ /** Neutral about whether the address exists — otherwise this form enumerates accounts. */
18
+ export const Sent: Story = {
19
+ args: { sent: true },
20
+ };
21
+
22
+ export const Interactive: Story = {
23
+ render: function Interactive() {
24
+ const [pending, setPending] = useState(false);
25
+ const [sent, setSent] = useState(false);
26
+
27
+ return (
28
+ <ForgotPasswordBlock
29
+ pending={pending}
30
+ sent={sent}
31
+ onSubmit={() => {
32
+ setPending(true);
33
+ window.setTimeout(() => {
34
+ setPending(false);
35
+ setSent(true);
36
+ }, 900);
37
+ }}
38
+ />
39
+ );
40
+ },
41
+ };
@@ -0,0 +1,62 @@
1
+ import { render, screen } 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 { ForgotPasswordBlock } from "./forgot-password";
7
+
8
+ describe("ForgotPasswordBlock", () => {
9
+ it("asks for an email", () => {
10
+ render(<ForgotPasswordBlock />);
11
+ expect(screen.getByLabelText("Email")).toHaveAttribute("type", "email");
12
+ });
13
+
14
+ it("submits a valid address", async () => {
15
+ const onSubmit = vi.fn();
16
+ const user = userEvent.setup();
17
+ render(<ForgotPasswordBlock onSubmit={onSubmit} />);
18
+
19
+ await user.type(screen.getByLabelText("Email"), "ada@example.com");
20
+ await user.click(screen.getByRole("button", { name: "Send reset link" }));
21
+
22
+ expect(onSubmit).toHaveBeenCalledWith({ email: "ada@example.com" });
23
+ });
24
+
25
+ it("refuses an invalid address", async () => {
26
+ const onSubmit = vi.fn();
27
+ const user = userEvent.setup();
28
+ render(<ForgotPasswordBlock onSubmit={onSubmit} />);
29
+
30
+ await user.type(screen.getByLabelText("Email"), "nope");
31
+ await user.click(screen.getByRole("button", { name: "Send reset link" }));
32
+
33
+ expect(onSubmit).not.toHaveBeenCalled();
34
+ });
35
+
36
+ describe("the confirmation", () => {
37
+ it("announces itself, because it replaces the form", () => {
38
+ render(<ForgotPasswordBlock sent />);
39
+ expect(screen.getByRole("status")).toHaveTextContent("Check your inbox");
40
+ });
41
+
42
+ it("does not reveal whether the account exists", () => {
43
+ render(<ForgotPasswordBlock sent />);
44
+ // Confirming it would turn this form into an account enumeration oracle.
45
+ expect(screen.getByText(/If an account exists/)).toBeInTheDocument();
46
+ });
47
+
48
+ it("replaces the form entirely", () => {
49
+ render(<ForgotPasswordBlock sent />);
50
+ expect(screen.queryByLabelText("Email")).not.toBeInTheDocument();
51
+ });
52
+ });
53
+
54
+ it("has no accessibility violations in either state", async () => {
55
+ const form = render(<ForgotPasswordBlock />);
56
+ await expectNoA11yViolations(form.container);
57
+ form.unmount();
58
+
59
+ const sent = render(<ForgotPasswordBlock sent />);
60
+ await expectNoA11yViolations(sent.container);
61
+ });
62
+ });
@@ -0,0 +1,158 @@
1
+ "use client";
2
+
3
+ import { useState, type FormEvent } from "react";
4
+
5
+ import { Button } from "@/components/button";
6
+ import {
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ } from "@/components/card";
14
+ import {
15
+ EmptyState,
16
+ EmptyStateDescription,
17
+ EmptyStateIcon,
18
+ EmptyStateTitle,
19
+ } from "@/components/empty-state";
20
+ import { Form, FormControl, FormField, FormLabel, FormMessage } from "@/components/form";
21
+ import { Input } from "@/components/input";
22
+ import { cn } from "@/lib/utils";
23
+
24
+ /**
25
+ * A password reset request.
26
+ *
27
+ * The confirmation deliberately does not say whether the address was found.
28
+ * Telling an anonymous visitor which emails have accounts turns this form into
29
+ * an account enumeration oracle, and the same neutral message covers both cases
30
+ * without being a lie.
31
+ */
32
+
33
+ export interface ForgotPasswordBlockProps {
34
+ onSubmit?: (values: { email: string }) => void;
35
+ /** Switches to the confirmation view. */
36
+ sent?: boolean;
37
+ error?: string;
38
+ pending?: boolean;
39
+ loginHref?: string;
40
+ className?: string;
41
+ }
42
+
43
+ export function ForgotPasswordBlock({
44
+ onSubmit,
45
+ sent = false,
46
+ error,
47
+ pending = false,
48
+ loginHref = "/login",
49
+ className,
50
+ }: ForgotPasswordBlockProps) {
51
+ const [email, setEmail] = useState("");
52
+ const [touched, setTouched] = useState(false);
53
+
54
+ const emailError =
55
+ touched && !email.includes("@") ? "Enter a valid email address." : undefined;
56
+
57
+ function handleSubmit(event: FormEvent<HTMLFormElement>) {
58
+ event.preventDefault();
59
+ setTouched(true);
60
+ if (!email.includes("@")) return;
61
+ onSubmit?.({ email });
62
+ }
63
+
64
+ if (sent) {
65
+ return (
66
+ <Card className={cn("w-full max-w-sm", className)}>
67
+ <CardContent className="pt-6">
68
+ {/* Announced, because it replaces the form the user just submitted. */}
69
+ <EmptyState role="status" aria-live="polite">
70
+ <EmptyStateIcon>
71
+ <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
72
+ <rect
73
+ x="3"
74
+ y="5"
75
+ width="18"
76
+ height="14"
77
+ rx="2"
78
+ stroke="currentColor"
79
+ strokeWidth="2"
80
+ />
81
+ <path
82
+ d="m3 7 9 6 9-6"
83
+ stroke="currentColor"
84
+ strokeWidth="2"
85
+ strokeLinecap="round"
86
+ />
87
+ </svg>
88
+ </EmptyStateIcon>
89
+ <EmptyStateTitle>Check your inbox</EmptyStateTitle>
90
+ <EmptyStateDescription>
91
+ If an account exists for {email}, a reset link is on its way. It expires in an
92
+ hour.
93
+ </EmptyStateDescription>
94
+ </EmptyState>
95
+ </CardContent>
96
+ <CardFooter className="justify-center">
97
+ <a
98
+ href={loginHref}
99
+ className="text-sm font-medium text-primary underline underline-offset-4"
100
+ >
101
+ Back to sign in
102
+ </a>
103
+ </CardFooter>
104
+ </Card>
105
+ );
106
+ }
107
+
108
+ return (
109
+ <Card className={cn("w-full max-w-sm", className)}>
110
+ <CardHeader>
111
+ <CardTitle>Reset your password</CardTitle>
112
+ <CardDescription>
113
+ Enter the address you signed up with and we will send you a link.
114
+ </CardDescription>
115
+ </CardHeader>
116
+
117
+ <CardContent>
118
+ <Form onSubmit={handleSubmit} className="gap-4">
119
+ {error ? (
120
+ <p role="alert" className="text-sm font-medium text-destructive">
121
+ {error}
122
+ </p>
123
+ ) : null}
124
+
125
+ <FormField name="email" error={emailError}>
126
+ <FormLabel>Email</FormLabel>
127
+ <FormControl>
128
+ <Input
129
+ type="email"
130
+ autoComplete="email"
131
+ placeholder="you@example.com"
132
+ value={email}
133
+ disabled={pending}
134
+ onChange={(event) => {
135
+ setEmail(event.target.value);
136
+ }}
137
+ />
138
+ </FormControl>
139
+ <FormMessage />
140
+ </FormField>
141
+
142
+ <Button type="submit" loading={pending} className="w-full">
143
+ Send reset link
144
+ </Button>
145
+ </Form>
146
+ </CardContent>
147
+
148
+ <CardFooter className="justify-center">
149
+ <a
150
+ href={loginHref}
151
+ className="text-sm text-muted-foreground underline underline-offset-4"
152
+ >
153
+ Back to sign in
154
+ </a>
155
+ </CardFooter>
156
+ </Card>
157
+ );
158
+ }
@@ -0,0 +1 @@
1
+ export { ForgotPasswordBlock, type ForgotPasswordBlockProps } from "./forgot-password";