@webjsdev/ui 0.3.17 → 0.5.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 (360) hide show
  1. package/README.md +67 -8
  2. package/THIRD_PARTY_NOTICES.md +349 -0
  3. package/package.json +4 -2
  4. package/packages/registry/blocks/_shared/placeholder.svg +1 -0
  5. package/packages/registry/blocks/charts/chart-area-axes.ts +72 -0
  6. package/packages/registry/blocks/charts/chart-area-default.ts +64 -0
  7. package/packages/registry/blocks/charts/chart-area-gradient.ts +82 -0
  8. package/packages/registry/blocks/charts/chart-area-icons.ts +77 -0
  9. package/packages/registry/blocks/charts/chart-area-interactive.ts +204 -0
  10. package/packages/registry/blocks/charts/chart-area-legend.ts +72 -0
  11. package/packages/registry/blocks/charts/chart-area-linear.ts +64 -0
  12. package/packages/registry/blocks/charts/chart-area-stacked-expand.ts +77 -0
  13. package/packages/registry/blocks/charts/chart-area-stacked.ts +71 -0
  14. package/packages/registry/blocks/charts/chart-area-step.ts +68 -0
  15. package/packages/registry/blocks/charts/chart-bar-active.ts +93 -0
  16. package/packages/registry/blocks/charts/chart-bar-default.ts +60 -0
  17. package/packages/registry/blocks/charts/chart-bar-horizontal.ts +62 -0
  18. package/packages/registry/blocks/charts/chart-bar-interactive.ts +185 -0
  19. package/packages/registry/blocks/charts/chart-bar-label-custom.ts +78 -0
  20. package/packages/registry/blocks/charts/chart-bar-label.ts +66 -0
  21. package/packages/registry/blocks/charts/chart-bar-mixed.ts +87 -0
  22. package/packages/registry/blocks/charts/chart-bar-multiple.ts +67 -0
  23. package/packages/registry/blocks/charts/chart-bar-negative.ts +61 -0
  24. package/packages/registry/blocks/charts/chart-bar-stacked.ts +68 -0
  25. package/packages/registry/blocks/charts/chart-line-default.ts +61 -0
  26. package/packages/registry/blocks/charts/chart-line-dots-colors.ts +86 -0
  27. package/packages/registry/blocks/charts/chart-line-dots-custom.ts +75 -0
  28. package/packages/registry/blocks/charts/chart-line-dots.ts +65 -0
  29. package/packages/registry/blocks/charts/chart-line-interactive.ts +185 -0
  30. package/packages/registry/blocks/charts/chart-line-label-custom.ts +94 -0
  31. package/packages/registry/blocks/charts/chart-line-label.ts +73 -0
  32. package/packages/registry/blocks/charts/chart-line-linear.ts +61 -0
  33. package/packages/registry/blocks/charts/chart-line-multiple.ts +71 -0
  34. package/packages/registry/blocks/charts/chart-line-step.ts +61 -0
  35. package/packages/registry/blocks/charts/chart-pie-donut-active.ts +86 -0
  36. package/packages/registry/blocks/charts/chart-pie-donut-text.ts +89 -0
  37. package/packages/registry/blocks/charts/chart-pie-donut.ts +77 -0
  38. package/packages/registry/blocks/charts/chart-pie-interactive.ts +120 -0
  39. package/packages/registry/blocks/charts/chart-pie-label-custom.ts +82 -0
  40. package/packages/registry/blocks/charts/chart-pie-label-list.ts +86 -0
  41. package/packages/registry/blocks/charts/chart-pie-label.ts +77 -0
  42. package/packages/registry/blocks/charts/chart-pie-legend.ts +79 -0
  43. package/packages/registry/blocks/charts/chart-pie-separator-none.ts +77 -0
  44. package/packages/registry/blocks/charts/chart-pie-simple.ts +77 -0
  45. package/packages/registry/blocks/charts/chart-pie-stacked.ts +99 -0
  46. package/packages/registry/blocks/charts/chart-radar-default.ts +61 -0
  47. package/packages/registry/blocks/charts/chart-radar-dots.ts +61 -0
  48. package/packages/registry/blocks/charts/chart-radar-grid-circle-fill.ts +61 -0
  49. package/packages/registry/blocks/charts/chart-radar-grid-circle-no-lines.ts +61 -0
  50. package/packages/registry/blocks/charts/chart-radar-grid-circle.ts +61 -0
  51. package/packages/registry/blocks/charts/chart-radar-grid-custom.ts +61 -0
  52. package/packages/registry/blocks/charts/chart-radar-grid-fill.ts +61 -0
  53. package/packages/registry/blocks/charts/chart-radar-grid-none.ts +60 -0
  54. package/packages/registry/blocks/charts/chart-radar-icons.ts +76 -0
  55. package/packages/registry/blocks/charts/chart-radar-label-custom.ts +77 -0
  56. package/packages/registry/blocks/charts/chart-radar-legend.ts +70 -0
  57. package/packages/registry/blocks/charts/chart-radar-lines-only.ts +68 -0
  58. package/packages/registry/blocks/charts/chart-radar-multiple.ts +68 -0
  59. package/packages/registry/blocks/charts/chart-radar-radius.ts +68 -0
  60. package/packages/registry/blocks/charts/chart-radial-grid.ts +80 -0
  61. package/packages/registry/blocks/charts/chart-radial-label.ts +85 -0
  62. package/packages/registry/blocks/charts/chart-radial-shape.ts +81 -0
  63. package/packages/registry/blocks/charts/chart-radial-simple.ts +79 -0
  64. package/packages/registry/blocks/charts/chart-radial-stacked.ts +69 -0
  65. package/packages/registry/blocks/charts/chart-radial-text.ts +82 -0
  66. package/packages/registry/blocks/charts/chart-tooltip-advanced.ts +84 -0
  67. package/packages/registry/blocks/charts/chart-tooltip-default.ts +62 -0
  68. package/packages/registry/blocks/charts/chart-tooltip-formatter.ts +75 -0
  69. package/packages/registry/blocks/charts/chart-tooltip-icons.ts +68 -0
  70. package/packages/registry/blocks/charts/chart-tooltip-indicator-line.ts +62 -0
  71. package/packages/registry/blocks/charts/chart-tooltip-indicator-none.ts +62 -0
  72. package/packages/registry/blocks/charts/chart-tooltip-label-custom.ts +65 -0
  73. package/packages/registry/blocks/charts/chart-tooltip-label-formatter.ts +66 -0
  74. package/packages/registry/blocks/charts/chart-tooltip-label-none.ts +62 -0
  75. package/packages/registry/blocks/dashboard-01/components/app-sidebar.ts +108 -0
  76. package/packages/registry/blocks/dashboard-01/components/chart-area-interactive.ts +276 -0
  77. package/packages/registry/blocks/dashboard-01/components/dashboard-data.ts +89 -0
  78. package/packages/registry/blocks/dashboard-01/components/data-table.ts +644 -0
  79. package/packages/registry/blocks/dashboard-01/components/nav-documents.ts +65 -0
  80. package/packages/registry/blocks/dashboard-01/components/nav-main.ts +61 -0
  81. package/packages/registry/blocks/dashboard-01/components/nav-secondary.ts +40 -0
  82. package/packages/registry/blocks/dashboard-01/components/nav-user.ts +66 -0
  83. package/packages/registry/blocks/dashboard-01/components/section-cards.ts +59 -0
  84. package/packages/registry/blocks/dashboard-01/components/site-header.ts +52 -0
  85. package/packages/registry/blocks/dashboard-01/page.ts +39 -0
  86. package/packages/registry/blocks/login-01/components/login-form.ts +70 -0
  87. package/packages/registry/blocks/login-01/page.ts +19 -0
  88. package/packages/registry/blocks/login-02/components/login-form.ts +68 -0
  89. package/packages/registry/blocks/login-02/page.ts +36 -0
  90. package/packages/registry/blocks/login-03/components/login-form.ts +89 -0
  91. package/packages/registry/blocks/login-03/page.ts +28 -0
  92. package/packages/registry/blocks/login-04/components/login-form.ts +91 -0
  93. package/packages/registry/blocks/login-04/page.ts +20 -0
  94. package/packages/registry/blocks/login-05/components/login-form.ts +75 -0
  95. package/packages/registry/blocks/login-05/page.ts +19 -0
  96. package/packages/registry/blocks/preview/cards/activate-agent-dialog.ts +77 -0
  97. package/packages/registry/blocks/preview/cards/analytics-card.ts +64 -0
  98. package/packages/registry/blocks/preview/cards/anomaly-alert.ts +35 -0
  99. package/packages/registry/blocks/preview/cards/bar-chart-card.ts +91 -0
  100. package/packages/registry/blocks/preview/cards/book-appointment.ts +51 -0
  101. package/packages/registry/blocks/preview/cards/codespaces-card.ts +172 -0
  102. package/packages/registry/blocks/preview/cards/contributions-activity.ts +63 -0
  103. package/packages/registry/blocks/preview/cards/contributors.ts +51 -0
  104. package/packages/registry/blocks/preview/cards/environment-variables.ts +47 -0
  105. package/packages/registry/blocks/preview/cards/feedback-form.ts +61 -0
  106. package/packages/registry/blocks/preview/cards/file-upload.ts +51 -0
  107. package/packages/registry/blocks/preview/cards/github-profile.ts +66 -0
  108. package/packages/registry/blocks/preview/cards/icon-preview-grid.ts +47 -0
  109. package/packages/registry/blocks/preview/cards/invite-team.ts +78 -0
  110. package/packages/registry/blocks/preview/cards/invoice.ts +91 -0
  111. package/packages/registry/blocks/preview/cards/live-waveform.ts +330 -0
  112. package/packages/registry/blocks/preview/cards/no-team-members.ts +61 -0
  113. package/packages/registry/blocks/preview/cards/not-found.ts +46 -0
  114. package/packages/registry/blocks/preview/cards/observability-card.ts +44 -0
  115. package/packages/registry/blocks/preview/cards/pie-chart-card.ts +84 -0
  116. package/packages/registry/blocks/preview/cards/report-bug.ts +71 -0
  117. package/packages/registry/blocks/preview/cards/shipping-address.ts +79 -0
  118. package/packages/registry/blocks/preview/cards/shortcuts.ts +57 -0
  119. package/packages/registry/blocks/preview/cards/skeleton-loading.ts +37 -0
  120. package/packages/registry/blocks/preview/cards/sleep-report.ts +85 -0
  121. package/packages/registry/blocks/preview/cards/style-overview.ts +64 -0
  122. package/packages/registry/blocks/preview/cards/typography-specimen.ts +107 -0
  123. package/packages/registry/blocks/preview/cards/ui-elements.ts +164 -0
  124. package/packages/registry/blocks/preview/cards/usage-card.ts +63 -0
  125. package/packages/registry/blocks/preview/cards/visitors.ts +71 -0
  126. package/packages/registry/blocks/preview/cards/weekly-fitness-summary.ts +54 -0
  127. package/packages/registry/blocks/preview/page.ts +103 -0
  128. package/packages/registry/blocks/preview-02/cards/account-access.ts +70 -0
  129. package/packages/registry/blocks/preview-02/cards/card-overview.ts +75 -0
  130. package/packages/registry/blocks/preview-02/cards/claimable-balance.ts +54 -0
  131. package/packages/registry/blocks/preview-02/cards/contribution-history.ts +80 -0
  132. package/packages/registry/blocks/preview-02/cards/cover-art.ts +41 -0
  133. package/packages/registry/blocks/preview-02/cards/dividend-income.ts +76 -0
  134. package/packages/registry/blocks/preview-02/cards/empty-connect-bank.ts +38 -0
  135. package/packages/registry/blocks/preview-02/cards/empty-distribute-track.ts +38 -0
  136. package/packages/registry/blocks/preview-02/cards/empty-explore-catalog.ts +39 -0
  137. package/packages/registry/blocks/preview-02/cards/faq.ts +79 -0
  138. package/packages/registry/blocks/preview-02/cards/front-door.ts +40 -0
  139. package/packages/registry/blocks/preview-02/cards/index-investing.ts +31 -0
  140. package/packages/registry/blocks/preview-02/cards/kitchen-island.ts +90 -0
  141. package/packages/registry/blocks/preview-02/cards/loading-card.ts +34 -0
  142. package/packages/registry/blocks/preview-02/cards/new-milestone.ts +53 -0
  143. package/packages/registry/blocks/preview-02/cards/notification-settings.ts +126 -0
  144. package/packages/registry/blocks/preview-02/cards/payments.ts +88 -0
  145. package/packages/registry/blocks/preview-02/cards/payout-threshold.ts +92 -0
  146. package/packages/registry/blocks/preview-02/cards/power-usage.ts +84 -0
  147. package/packages/registry/blocks/preview-02/cards/preferences.ts +89 -0
  148. package/packages/registry/blocks/preview-02/cards/qr-connect.ts +54 -0
  149. package/packages/registry/blocks/preview-02/cards/receiving-method.ts +89 -0
  150. package/packages/registry/blocks/preview-02/cards/recent-transactions.ts +101 -0
  151. package/packages/registry/blocks/preview-02/cards/release-catalog.ts +73 -0
  152. package/packages/registry/blocks/preview-02/cards/roller-shades.ts +110 -0
  153. package/packages/registry/blocks/preview-02/cards/savings-progress.ts +68 -0
  154. package/packages/registry/blocks/preview-02/cards/savings-targets.ts +132 -0
  155. package/packages/registry/blocks/preview-02/cards/sidebar-nav.ts +88 -0
  156. package/packages/registry/blocks/preview-02/cards/social-links.ts +57 -0
  157. package/packages/registry/blocks/preview-02/cards/stock-performance.ts +106 -0
  158. package/packages/registry/blocks/preview-02/cards/syncing-state.ts +37 -0
  159. package/packages/registry/blocks/preview-02/cards/transfer-funds.ts +111 -0
  160. package/packages/registry/blocks/preview-02/cards/upcoming-payments.ts +69 -0
  161. package/packages/registry/blocks/preview-02/page.ts +111 -0
  162. package/packages/registry/blocks/preview-03/cards/files-chat.ts +75 -0
  163. package/packages/registry/blocks/preview-03/cards/group-chat.ts +114 -0
  164. package/packages/registry/blocks/preview-03/cards/reasoning-chat.ts +88 -0
  165. package/packages/registry/blocks/preview-03/cards/simple-chat.ts +53 -0
  166. package/packages/registry/blocks/preview-03/components/chat-card.ts +126 -0
  167. package/packages/registry/blocks/preview-03/components/chat-player.ts +174 -0
  168. package/packages/registry/blocks/preview-03/components/part-file.ts +77 -0
  169. package/packages/registry/blocks/preview-03/components/part-reasoning.ts +25 -0
  170. package/packages/registry/blocks/preview-03/components/part-source.ts +48 -0
  171. package/packages/registry/blocks/preview-03/components/part-text.ts +69 -0
  172. package/packages/registry/blocks/preview-03/components/part-tool.ts +71 -0
  173. package/packages/registry/blocks/preview-03/components/prompt-input.ts +86 -0
  174. package/packages/registry/blocks/preview-03/page.ts +39 -0
  175. package/packages/registry/blocks/sidebar-01/components/app-sidebar.ts +113 -0
  176. package/packages/registry/blocks/sidebar-01/components/search-form.ts +33 -0
  177. package/packages/registry/blocks/sidebar-01/components/version-switcher.ts +50 -0
  178. package/packages/registry/blocks/sidebar-01/page.ts +58 -0
  179. package/packages/registry/blocks/sidebar-02/components/app-sidebar.ts +131 -0
  180. package/packages/registry/blocks/sidebar-02/components/search-form.ts +33 -0
  181. package/packages/registry/blocks/sidebar-02/components/version-switcher.ts +50 -0
  182. package/packages/registry/blocks/sidebar-02/page.ts +53 -0
  183. package/packages/registry/blocks/sidebar-03/components/app-sidebar.ts +134 -0
  184. package/packages/registry/blocks/sidebar-03/page.ts +60 -0
  185. package/packages/registry/blocks/sidebar-04/components/app-sidebar.ts +136 -0
  186. package/packages/registry/blocks/sidebar-04/page.ts +58 -0
  187. package/packages/registry/blocks/sidebar-05/components/app-sidebar.ts +147 -0
  188. package/packages/registry/blocks/sidebar-05/components/search-form.ts +33 -0
  189. package/packages/registry/blocks/sidebar-05/page.ts +58 -0
  190. package/packages/registry/blocks/sidebar-06/components/app-sidebar.ts +105 -0
  191. package/packages/registry/blocks/sidebar-06/components/nav-main.ts +56 -0
  192. package/packages/registry/blocks/sidebar-06/components/sidebar-opt-in-form.ts +44 -0
  193. package/packages/registry/blocks/sidebar-06/page.ts +57 -0
  194. package/packages/registry/blocks/sidebar-07/components/app-sidebar.ts +108 -0
  195. package/packages/registry/blocks/sidebar-07/components/nav-main.ts +61 -0
  196. package/packages/registry/blocks/sidebar-07/components/nav-projects.ts +65 -0
  197. package/packages/registry/blocks/sidebar-07/components/nav-user.ts +70 -0
  198. package/packages/registry/blocks/sidebar-07/components/team-switcher.ts +66 -0
  199. package/packages/registry/blocks/sidebar-07/page.ts +59 -0
  200. package/packages/registry/blocks/sidebar-08/components/app-sidebar.ts +122 -0
  201. package/packages/registry/blocks/sidebar-08/components/nav-main.ts +68 -0
  202. package/packages/registry/blocks/sidebar-08/components/nav-projects.ts +65 -0
  203. package/packages/registry/blocks/sidebar-08/components/nav-secondary.ts +40 -0
  204. package/packages/registry/blocks/sidebar-08/components/nav-user.ts +70 -0
  205. package/packages/registry/blocks/sidebar-08/page.ts +59 -0
  206. package/packages/registry/blocks/sidebar-09/components/app-sidebar.ts +213 -0
  207. package/packages/registry/blocks/sidebar-09/components/nav-user.ts +70 -0
  208. package/packages/registry/blocks/sidebar-09/page.ts +52 -0
  209. package/packages/registry/blocks/sidebar-10/components/app-sidebar.ts +125 -0
  210. package/packages/registry/blocks/sidebar-10/components/nav-actions.ts +84 -0
  211. package/packages/registry/blocks/sidebar-10/components/nav-favorites.ts +66 -0
  212. package/packages/registry/blocks/sidebar-10/components/nav-main.ts +37 -0
  213. package/packages/registry/blocks/sidebar-10/components/nav-secondary.ts +43 -0
  214. package/packages/registry/blocks/sidebar-10/components/nav-workspaces.ts +78 -0
  215. package/packages/registry/blocks/sidebar-10/components/team-switcher.ts +63 -0
  216. package/packages/registry/blocks/sidebar-10/page.ts +46 -0
  217. package/packages/registry/blocks/sidebar-11/components/app-sidebar.ts +114 -0
  218. package/packages/registry/blocks/sidebar-11/page.ts +63 -0
  219. package/packages/registry/blocks/sidebar-12/components/app-sidebar.ts +63 -0
  220. package/packages/registry/blocks/sidebar-12/components/calendars.ts +53 -0
  221. package/packages/registry/blocks/sidebar-12/components/date-picker.ts +26 -0
  222. package/packages/registry/blocks/sidebar-12/components/nav-user.ts +70 -0
  223. package/packages/registry/blocks/sidebar-12/page.ts +43 -0
  224. package/packages/registry/blocks/sidebar-13/components/settings-dialog.ts +114 -0
  225. package/packages/registry/blocks/sidebar-13/page.ts +21 -0
  226. package/packages/registry/blocks/sidebar-14/components/app-sidebar.ts +120 -0
  227. package/packages/registry/blocks/sidebar-14/page.ts +55 -0
  228. package/packages/registry/blocks/sidebar-15/components/calendars.ts +53 -0
  229. package/packages/registry/blocks/sidebar-15/components/date-picker.ts +26 -0
  230. package/packages/registry/blocks/sidebar-15/components/nav-favorites.ts +66 -0
  231. package/packages/registry/blocks/sidebar-15/components/nav-main.ts +35 -0
  232. package/packages/registry/blocks/sidebar-15/components/nav-secondary.ts +43 -0
  233. package/packages/registry/blocks/sidebar-15/components/nav-user.ts +70 -0
  234. package/packages/registry/blocks/sidebar-15/components/nav-workspaces.ts +75 -0
  235. package/packages/registry/blocks/sidebar-15/components/sidebar-left.ts +126 -0
  236. package/packages/registry/blocks/sidebar-15/components/sidebar-right.ts +62 -0
  237. package/packages/registry/blocks/sidebar-15/components/team-switcher.ts +63 -0
  238. package/packages/registry/blocks/sidebar-15/page.ts +47 -0
  239. package/packages/registry/blocks/sidebar-16/components/app-sidebar.ts +124 -0
  240. package/packages/registry/blocks/sidebar-16/components/nav-main.ts +67 -0
  241. package/packages/registry/blocks/sidebar-16/components/nav-projects.ts +65 -0
  242. package/packages/registry/blocks/sidebar-16/components/nav-secondary.ts +40 -0
  243. package/packages/registry/blocks/sidebar-16/components/nav-user.ts +70 -0
  244. package/packages/registry/blocks/sidebar-16/components/search-form.ts +27 -0
  245. package/packages/registry/blocks/sidebar-16/components/site-header.ts +42 -0
  246. package/packages/registry/blocks/sidebar-16/page.ts +38 -0
  247. package/packages/registry/blocks/signup-01/components/signup-form.ts +78 -0
  248. package/packages/registry/blocks/signup-01/page.ts +19 -0
  249. package/packages/registry/blocks/signup-02/components/signup-form.ts +78 -0
  250. package/packages/registry/blocks/signup-02/page.ts +36 -0
  251. package/packages/registry/blocks/signup-03/components/signup-form.ts +79 -0
  252. package/packages/registry/blocks/signup-03/page.ts +28 -0
  253. package/packages/registry/blocks/signup-04/components/signup-form.ts +100 -0
  254. package/packages/registry/blocks/signup-04/page.ts +20 -0
  255. package/packages/registry/blocks/signup-05/components/signup-form.ts +75 -0
  256. package/packages/registry/blocks/signup-05/page.ts +20 -0
  257. package/packages/registry/components/accordion.ts +20 -7
  258. package/packages/registry/components/alert-dialog.ts +58 -13
  259. package/packages/registry/components/alert.ts +11 -6
  260. package/packages/registry/components/attachment.ts +119 -0
  261. package/packages/registry/components/avatar.ts +17 -8
  262. package/packages/registry/components/badge.ts +16 -9
  263. package/packages/registry/components/breadcrumb.ts +6 -6
  264. package/packages/registry/components/bubble.ts +95 -0
  265. package/packages/registry/components/button-group.ts +73 -0
  266. package/packages/registry/components/button.ts +35 -25
  267. package/packages/registry/components/calendar.ts +566 -0
  268. package/packages/registry/components/card.ts +8 -8
  269. package/packages/registry/components/carousel.ts +352 -0
  270. package/packages/registry/components/chart-element.ts +547 -0
  271. package/packages/registry/components/chart-geometry.ts +457 -0
  272. package/packages/registry/components/chart.ts +932 -0
  273. package/packages/registry/components/checkbox.ts +22 -84
  274. package/packages/registry/components/code-block.ts +191 -0
  275. package/packages/registry/components/collapsible.ts +5 -2
  276. package/packages/registry/components/combobox.ts +802 -0
  277. package/packages/registry/components/command.ts +618 -0
  278. package/packages/registry/components/context-menu.ts +302 -0
  279. package/packages/registry/components/dialog.ts +156 -45
  280. package/packages/registry/components/direction.ts +43 -0
  281. package/packages/registry/components/drawer.ts +226 -0
  282. package/packages/registry/components/dropdown-menu.ts +262 -83
  283. package/packages/registry/components/empty.ts +8 -8
  284. package/packages/registry/components/field.ts +20 -18
  285. package/packages/registry/components/floating.ts +124 -0
  286. package/packages/registry/components/hover-card.ts +19 -8
  287. package/packages/registry/components/input-group.ts +118 -0
  288. package/packages/registry/components/input-otp.ts +365 -0
  289. package/packages/registry/components/input.ts +3 -3
  290. package/packages/registry/components/item.ts +134 -0
  291. package/packages/registry/components/kbd.ts +2 -2
  292. package/packages/registry/components/label.ts +1 -1
  293. package/packages/registry/components/marker.ts +63 -0
  294. package/packages/registry/components/menubar.ts +388 -0
  295. package/packages/registry/components/message-scroller.ts +470 -0
  296. package/packages/registry/components/message.ts +69 -0
  297. package/packages/registry/components/native-select.ts +5 -5
  298. package/packages/registry/components/navigation-menu.ts +564 -0
  299. package/packages/registry/components/pagination.ts +5 -5
  300. package/packages/registry/components/popover.ts +30 -84
  301. package/packages/registry/components/progress.ts +7 -3
  302. package/packages/registry/components/questionnaire.ts +840 -0
  303. package/packages/registry/components/radio-group.ts +18 -73
  304. package/packages/registry/components/resizable.ts +330 -0
  305. package/packages/registry/components/scroll-area.ts +46 -0
  306. package/packages/registry/components/select.ts +650 -0
  307. package/packages/registry/components/separator.ts +1 -1
  308. package/packages/registry/components/sheet.ts +128 -0
  309. package/packages/registry/components/sidebar.ts +457 -0
  310. package/packages/registry/components/skeleton.ts +1 -1
  311. package/packages/registry/components/slider.ts +333 -0
  312. package/packages/registry/components/sonner.ts +74 -7
  313. package/packages/registry/components/spinner.ts +7 -4
  314. package/packages/registry/components/switch.ts +117 -9
  315. package/packages/registry/components/table.ts +11 -9
  316. package/packages/registry/components/tabs.ts +76 -25
  317. package/packages/registry/components/textarea.ts +1 -1
  318. package/packages/registry/components/toggle-group.ts +30 -11
  319. package/packages/registry/components/toggle.ts +20 -13
  320. package/packages/registry/components/tooltip.ts +68 -7
  321. package/packages/registry/components/trace.ts +75 -0
  322. package/packages/registry/lib/dom.ts +3 -4
  323. package/packages/registry/lib/icons-hugeicons.ts +955 -0
  324. package/packages/registry/lib/icons-phosphor.ts +955 -0
  325. package/packages/registry/lib/icons-remixicon.ts +955 -0
  326. package/packages/registry/lib/icons-tabler.ts +955 -0
  327. package/packages/registry/lib/icons.ts +768 -0
  328. package/packages/registry/lib/utils.ts +52 -8
  329. package/packages/registry/registry.json +4056 -72
  330. package/packages/registry/styles/shadcn-tailwind.css +654 -0
  331. package/packages/registry/styles/style-luma.css +1987 -0
  332. package/packages/registry/styles/style-lyra.css +1965 -0
  333. package/packages/registry/styles/style-maia.css +1987 -0
  334. package/packages/registry/styles/style-mira.css +1992 -0
  335. package/packages/registry/styles/style-new-york.css +1597 -0
  336. package/packages/registry/styles/style-nova.css +1990 -0
  337. package/packages/registry/styles/style-rhea.css +1987 -0
  338. package/packages/registry/styles/style-sera.css +1977 -0
  339. package/packages/registry/styles/style-vega.css +1990 -0
  340. package/packages/registry/styles/supplement.json +54 -0
  341. package/packages/registry/styles/tw-animate.css +6 -0
  342. package/packages/registry/themes/base-colors.js +8 -2
  343. package/packages/registry/themes/fonts.js +120 -0
  344. package/packages/registry/themes/index.css +2 -0
  345. package/packages/registry/themes/items.js +61 -0
  346. package/packages/registry/themes/preset.js +302 -0
  347. package/packages/registry/themes/themes.js +1193 -0
  348. package/src/commands/add.js +266 -14
  349. package/src/commands/diff.js +34 -20
  350. package/src/commands/info.js +7 -0
  351. package/src/commands/init.js +127 -10
  352. package/src/commands/list.js +43 -11
  353. package/src/commands/view.js +33 -5
  354. package/src/lint/rules/no-restyle.js +1 -1
  355. package/src/registry/extract.js +194 -5
  356. package/src/registry/icons.js +31 -0
  357. package/src/registry/local.js +15 -1
  358. package/src/registry/schema.js +13 -0
  359. package/src/registry/style-bake.js +506 -0
  360. package/src/utils/theme.js +110 -21
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The preview-03 group chat card: several people planning a dinner, with
3
+ * join, leave and typing notices between their messages, and an assistant
4
+ * the group calls with `@chat,`. Your own messages sit at the end in a
5
+ * tinted bubble; everyone else's carry their name. A fragment helper,
6
+ * rendered by the server; `<preview-03-chat>` plays the turns, one message
7
+ * each, and the notices on their own timing.
8
+ *
9
+ * Installed by `npx @webjsdev/ui add preview-03` at
10
+ * `components/preview-03/group-chat.ts`. Ported from shadcn/ui's preview-03,
11
+ * whose script it keeps except that its em-dashes are written as commas.
12
+ */
13
+ import { html } from '@webjsdev/core';
14
+ import { messageHeaderClass } from '../../../components/message.ts';
15
+ import { chatCard, chatItem, chatMarker, chatMessage, type ChatPrompt } from '../components/chat-card.ts';
16
+ import { partText } from '../components/part-text.ts';
17
+
18
+ interface GroupMessage {
19
+ /** Absent for your own messages. */
20
+ name?: string;
21
+ text: string;
22
+ }
23
+
24
+ const MESSAGES: GroupMessage[] = [
25
+ { text: 'Hey everyone, dinner this Saturday? I was thinking something casual at my place.' },
26
+ { name: 'Stella', text: "I'm in! Should we do potluck or does someone want to cook the whole thing?" },
27
+ { name: 'Marcus', text: 'Potluck sounds good. I can handle appetizers and drinks.' },
28
+ { text: 'Alright! Aleena?' },
29
+ { name: 'Aleena', text: "Can't make it. I'm out of town. 😭" },
30
+ { name: 'Aleena', text: "Sorry guys, let's catch up another time. Bye." },
31
+ { text: '@chat, can you suggest a menu and split up what each of us should bring?' },
32
+ ];
33
+
34
+ const REPLY = `Here's a simple **Saturday potluck** for the three of you:
35
+
36
+ **Who brings what**
37
+ - **You:** main, salmon or mushroom risotto
38
+ - **Stella:** salad + bread
39
+ - **Marcus:** appetizers + drinks
40
+ - **Chat:** dessert ideas below
41
+
42
+ **Menu**
43
+ - **Starter:** caprese skewers or whipped ricotta crostini
44
+ - **Main:** lemon-herb salmon with roasted asparagus *(or risotto for vegetarians)*
45
+ - **Side:** arugula salad with shaved parmesan
46
+ - **Dessert:** berry crisp or pistachio gelato
47
+
48
+ **Timing:** aim for **6:30 PM** so Marcus can set up apps while you finish the main.
49
+
50
+ Want me to scale this for **6 guests** or swap the main for something vegetarian-only?`;
51
+
52
+ /** The notices, each shown after message `turn`, `delay` milliseconds after it. */
53
+ const EVENTS: Array<{ type: 'user-joined' | 'user-left' | 'user-typing'; name: string; turn: number; delay: number }> = [
54
+ { type: 'user-joined', name: 'Stella', turn: 0, delay: 2000 },
55
+ { type: 'user-typing', name: 'Stella', turn: 0, delay: 4000 },
56
+ { type: 'user-joined', name: 'Marcus', turn: 1, delay: 2000 },
57
+ { type: 'user-typing', name: 'Marcus', turn: 1, delay: 4000 },
58
+ { type: 'user-joined', name: 'Aleena', turn: 2, delay: 0 },
59
+ { type: 'user-typing', name: 'Aleena', turn: 3, delay: 0 },
60
+ { type: 'user-left', name: 'Aleena', turn: 5, delay: 2000 },
61
+ ];
62
+
63
+ function eventText(e: (typeof EVENTS)[number]): string {
64
+ if (e.type === 'user-joined') return `${e.name} joined the chat`;
65
+ if (e.type === 'user-left') return `${e.name} left the chat`;
66
+ return `${e.name} is typing...`;
67
+ }
68
+
69
+ export function groupChat() {
70
+ const prompts: ChatPrompt[] = MESSAGES.map((m) => ({ text: m.text, sender: m.name ?? 'You' }));
71
+ const transcript = MESSAGES.map((m, turn) => {
72
+ const own = m.name === undefined;
73
+ const message = chatItem({
74
+ turn, kind: 'user', id: `group-${turn}`, anchor: m.text.trim().toLowerCase().startsWith('@chat,'),
75
+ content: chatMessage({
76
+ role: 'user',
77
+ align: own ? 'end' : 'start',
78
+ header: own ? '' : html`<div data-slot="message-header" class=${messageHeaderClass()}>${m.name}</div>`,
79
+ content: partText({ text: m.text, variant: 'bubble', tinted: own }),
80
+ }),
81
+ });
82
+ const events = EVENTS.filter((e) => e.turn === turn).map((e) => chatItem({
83
+ turn,
84
+ kind: e.type === 'user-typing' ? 'typing' : 'event',
85
+ name: e.name,
86
+ delay: e.delay,
87
+ content: chatMarker({ text: eventText(e), variant: e.type === 'user-typing' ? 'default' : 'separator', status: e.type === 'user-typing' }),
88
+ }));
89
+ const reply = turn === MESSAGES.length - 1
90
+ ? chatItem({
91
+ turn, kind: 'reply', id: 'group-reply', delay: 1000,
92
+ content: chatMessage({
93
+ role: 'assistant',
94
+ align: 'start',
95
+ header: html`<div data-slot="message-header" class=${messageHeaderClass()}>Chat</div>`,
96
+ content: partText({ text: REPLY, variant: 'default' }),
97
+ }),
98
+ })
99
+ : '';
100
+ return html`${message}${events}${reply}`;
101
+ });
102
+
103
+ return chatCard({
104
+ id: 'group-chat-prompt',
105
+ caption: 'Group Chat',
106
+ title: 'Saturday dinner plans',
107
+ description: 'A group chat with multiple users. Includes tinted bubbles for user messages.',
108
+ descriptionClass: 'leading-relaxed',
109
+ prompts,
110
+ transcript,
111
+ footerClass: 'flex-col items-stretch gap-2',
112
+ footerTop: html`<p class="px-1 text-xs text-muted-foreground">Posting as <span data-chat-sender>You</span>.</p>`,
113
+ });
114
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The preview-03 reasoning chat card: an assistant whose replies show their
3
+ * reasoning steps above the answer, across two scripted turns. A fragment
4
+ * helper, rendered by the server; `<preview-03-chat>` plays the turns.
5
+ *
6
+ * Installed by `npx @webjsdev/ui add preview-03` at
7
+ * `components/preview-03/reasoning-chat.ts`. Ported from shadcn/ui's
8
+ * preview-03, whose script it keeps except that an em-dash is written as a
9
+ * comma.
10
+ */
11
+ import { html } from '@webjsdev/core';
12
+ import { chatCard, chatItem, chatMessage, type ChatPrompt } from '../components/chat-card.ts';
13
+ import { getReasoningLevelLabel, partReasoning } from '../components/part-reasoning.ts';
14
+ import { partText } from '../components/part-text.ts';
15
+
16
+ const SCRIPT: Array<{ user: string; reasoning: string[]; text: string }> = [
17
+ {
18
+ user: 'Explain why the dashboard feels slow even though the API is fast.',
19
+ reasoning: [
20
+ `The user is separating perceived performance from backend latency. They likely measured API response times and found them acceptable, but users still complain about slowness.
21
+
22
+ I should avoid jumping straight to server-side optimizations and instead frame the answer around what people actually experience.`,
23
+ `Perceived slowness usually lives in the gap between user action and visible feedback:
24
+
25
+ - input latency before the request fires
26
+ - loading state placement and timing
27
+ - layout shifts when data arrives
28
+ - whether optimistic UI gives immediate acknowledgment
29
+
30
+ For a dashboard, I should also consider chart re-renders, independent card fetches, and skeleton dimensions that do not match the final layout.`,
31
+ `Ranking likely bottlenecks for this scenario:
32
+
33
+ 1. No immediate feedback on filter or refresh actions
34
+ 2. Skeleton cards that collapse or expand when data lands
35
+ 3. Waterfall requests where each widget fetches on its own
36
+ 4. Empty-state flashes because stale data is not shown while revalidating
37
+
38
+ The answer should stay practical and ordered by impact, not by how technical each fix sounds.`,
39
+ ],
40
+ text: `The API can be fast while the interface still **feels** slow.
41
+
42
+ Start by checking:
43
+
44
+ - whether the button gives immediate feedback
45
+ - whether skeletons match the final layout
46
+ - whether any reflow happens after data arrives
47
+ - whether the loading state appears near the content it replaces`,
48
+ },
49
+ {
50
+ user: 'What should I fix first?',
51
+ reasoning: [
52
+ `The user wants prioritization, not another diagnostic list.
53
+
54
+ Given the dashboard context, immediate feedback and layout stability usually beat micro-optimizations. I should recommend one fix with a clear way to measure success.`,
55
+ ],
56
+ text: `Fix **immediate feedback** first.
57
+
58
+ When someone clicks "Refresh", the button should disable and show a spinner within one frame, before the network round trip. That single change often cuts perceived latency in half.
59
+
60
+ Measure it with a screen recording and count frames between click and visual response.`,
61
+ },
62
+ ];
63
+
64
+ export function reasoningChat() {
65
+ const prompts: ChatPrompt[] = SCRIPT.map((t) => ({ text: t.user }));
66
+ return chatCard({
67
+ id: 'reasoning-chat-prompt',
68
+ caption: 'Reasoning',
69
+ title: 'Reasoning trace',
70
+ description: 'Layered reasoning traces across multiple assistant turns.',
71
+ prompts,
72
+ transcript: SCRIPT.map((t, turn) => html`
73
+ ${chatItem({
74
+ turn, kind: 'user', id: `reasoning-${turn}-user`, anchor: true,
75
+ content: chatMessage({ role: 'user', align: 'end', contentClass: 'flex-col items-end gap-2', content: partText({ text: t.user, variant: 'bubble' }) }),
76
+ })}
77
+ ${chatItem({
78
+ turn, kind: 'reply', id: `reasoning-${turn}-assistant`, delay: 1000,
79
+ content: chatMessage({
80
+ role: 'assistant',
81
+ align: 'start',
82
+ contentClass: 'flex-col items-start gap-2',
83
+ content: html`${t.reasoning.map((r, i) => partReasoning({ text: r, label: getReasoningLevelLabel(i) }))}${partText({ text: t.text, variant: 'default' })}`,
84
+ }),
85
+ })}
86
+ `),
87
+ });
88
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The preview-03 simple chat card: a one-to-one conversation with an
3
+ * assistant, four scripted turns. A fragment helper, rendered by the server;
4
+ * `<preview-03-chat>` plays the turns.
5
+ *
6
+ * Installed by `npx @webjsdev/ui add preview-03` at
7
+ * `components/preview-03/simple-chat.ts`. Ported from shadcn/ui's
8
+ * preview-03, whose script it keeps word for word except that an em-dash in
9
+ * it is written as a comma.
10
+ */
11
+ import { html } from '@webjsdev/core';
12
+ import { chatCard, chatItem, chatMessage, type ChatPrompt } from '../components/chat-card.ts';
13
+ import { partText } from '../components/part-text.ts';
14
+
15
+ const SCRIPT: Array<{ user: string; assistant: string }> = [
16
+ {
17
+ user: "Write me a haiku about centering a div and how it's done.",
18
+ assistant: 'One box in the void / Twenty wrappers, still offset / `margin: 0 auto`',
19
+ },
20
+ {
21
+ user: "Is this conversation actually happening? I've been sitting here wondering if you're **really** reading this.\n\nEvery reply feels a little too convenient, like someone already wrote `chat.next(messages)` and I'm just clicking send on my own lines.",
22
+ assistant: "You're in a preview block. I'm four hardcoded replies and a transport. Real enough for the demo, philosophically, we're both props.",
23
+ },
24
+ {
25
+ user: 'Okay, how do I make my loading spinner feel faster? Tell me in detail about the technique.',
26
+ assistant: 'Add text that says “Almost there…” and never update it. Users assume progress. Ethically dubious. Statistically effective.',
27
+ },
28
+ {
29
+ user: 'Can you at least pretend to be surprised?',
30
+ assistant: '😮 WOW! I had no idea you would ask that!',
31
+ },
32
+ ];
33
+
34
+ export function simpleChat() {
35
+ const prompts: ChatPrompt[] = SCRIPT.map((t) => ({ text: t.user }));
36
+ return chatCard({
37
+ id: 'simple-chat-prompt',
38
+ caption: 'Simple Chat',
39
+ title: 'What can I help you with today?',
40
+ description: 'A simple chat example.',
41
+ prompts,
42
+ transcript: SCRIPT.map((t, turn) => html`
43
+ ${chatItem({
44
+ turn, kind: 'user', id: `simple-${turn}-user`, anchor: true,
45
+ content: chatMessage({ role: 'user', align: 'end', content: partText({ text: t.user, role: 'user' }) }),
46
+ })}
47
+ ${chatItem({
48
+ turn, kind: 'reply', id: `simple-${turn}-assistant`, delay: 3000,
49
+ content: chatMessage({ role: 'assistant', align: 'start', content: partText({ text: t.assistant, role: 'assistant' }) }),
50
+ })}
51
+ `),
52
+ });
53
+ }
@@ -0,0 +1,126 @@
1
+ /**
2
+ * The preview-03 chat card: the frame every chat card shares, shadcn's
3
+ * Example wrapper (a caption over the card), a card with a title, a
4
+ * description and a start-over button, the transcript in the kit's
5
+ * `<ui-message-scroller>`, and the prompt input in the footer, all inside
6
+ * `<preview-03-chat>`, which plays the scripted turns. Plus the two helpers
7
+ * a card builds its transcript from. Fragment helpers, rendered by the server.
8
+ *
9
+ * Installed by `npx @webjsdev/ui add preview-03` at
10
+ * `components/preview-03/chat-card.ts`. Ported from shadcn/ui's preview-03,
11
+ * where each card repeats this frame inline.
12
+ */
13
+ import { html, nothing } from '@webjsdev/core';
14
+ import { cn } from '../../../lib/utils.ts';
15
+ import { buttonClass } from '../../../components/button.ts';
16
+ import {
17
+ cardActionClass,
18
+ cardClass,
19
+ cardContentClass,
20
+ cardDescriptionClass,
21
+ cardFooterClass,
22
+ cardHeaderClass,
23
+ cardTitleClass,
24
+ } from '../../../components/card.ts';
25
+ import { markerClass, markerContentClass, markerIconClass } from '../../../components/marker.ts';
26
+ import { messageClass, messageContentClass } from '../../../components/message.ts';
27
+ import { spinner } from '../../../components/spinner.ts';
28
+ import '../../../components/message-scroller.ts';
29
+ import { promptInput } from './prompt-input.ts';
30
+ import './chat-player.ts';
31
+ import { PlusIcon } from '../../../lib/icons.ts';
32
+
33
+ export interface ChatPrompt {
34
+ text: string;
35
+ sender?: string;
36
+ }
37
+
38
+ /**
39
+ * One scripted item of a transcript, hidden until `<preview-03-chat>` plays
40
+ * its turn. `delay` is milliseconds after the turn starts (for a reply, how
41
+ * long the "Thinking..." marker shows first).
42
+ */
43
+ export function chatItem(opts: {
44
+ turn: number;
45
+ kind: 'user' | 'reply' | 'event' | 'typing';
46
+ content: unknown;
47
+ id?: string;
48
+ delay?: number;
49
+ name?: string;
50
+ anchor?: boolean;
51
+ }) {
52
+ return html`<ui-message-scroller-item
53
+ hidden
54
+ message-id=${opts.id ?? nothing}
55
+ ?scroll-anchor=${!!opts.anchor}
56
+ data-chat-turn=${opts.turn}
57
+ data-chat-kind=${opts.kind}
58
+ data-chat-delay=${opts.delay ?? nothing}
59
+ data-chat-name=${opts.name ?? nothing}
60
+ >${opts.content}</ui-message-scroller-item>`;
61
+ }
62
+
63
+ /** A message, shadcn's Message and MessageContent. */
64
+ export function chatMessage(opts: { role: 'user' | 'assistant'; align: 'start' | 'end'; header?: unknown; contentClass?: string; content: unknown }) {
65
+ return html`<div data-slot="message" data-align=${opts.align} data-role=${opts.role} class=${messageClass()}>
66
+ ${opts.header ?? ''}
67
+ <div data-slot="message-content" class=${cn(messageContentClass(), opts.contentClass)}>${opts.content}</div>
68
+ </div>`;
69
+ }
70
+
71
+ /** A marker in the transcript, a join or leave notice or a typing line. */
72
+ export function chatMarker(opts: { text: string; variant?: 'default' | 'separator'; status?: boolean; icon?: unknown }) {
73
+ const variant = opts.variant ?? 'default';
74
+ return html`<div data-slot="marker" data-variant=${variant} role=${opts.status ? 'status' : nothing} class=${markerClass({ variant })}>
75
+ ${opts.icon ? html`<span data-slot="marker-icon" class=${markerIconClass()}>${opts.icon}</span>` : ''}
76
+ <span data-slot="marker-content" class=${markerContentClass()}>${opts.text}</span>
77
+ </div>`;
78
+ }
79
+
80
+ export function chatCard(opts: {
81
+ /** Unique on the page: the textarea's id and the menu button's derive from it. */
82
+ id: string;
83
+ caption: string;
84
+ title: string;
85
+ description: string;
86
+ descriptionClass?: string;
87
+ prompts: ChatPrompt[];
88
+ transcript: unknown;
89
+ /** Shown above the prompt input (the group chat's "Posting as" line). */
90
+ footerTop?: unknown;
91
+ footerClass?: string;
92
+ }) {
93
+ return html`<preview-03-chat data-prompts=${JSON.stringify(opts.prompts)} class="flex min-h-0 flex-1 flex-col">
94
+ <div data-slot="example" class="mx-auto flex w-full max-w-lg min-w-0 flex-1 flex-col gap-1 self-stretch lg:max-w-none">
95
+ <div class="px-1.5 py-2 text-xs font-medium text-muted-foreground">${opts.caption}</div>
96
+ <div data-slot="example-content" class="flex min-w-0 flex-1 flex-col items-start gap-6 rounded-xl bg-transparent p-0 text-foreground style-lyra:rounded-none style-sera:rounded-none *:[div:not([class*='w-'])]:w-full">
97
+ <div data-slot="card" data-size="default" class=${cn(cardClass(), 'max-h-140 min-h-0 flex-1')}>
98
+ <div data-slot="card-header" class=${cardHeaderClass()}>
99
+ <div data-slot="card-title" class=${cardTitleClass()}>${opts.title}</div>
100
+ <div data-slot="card-description" class=${cn(cardDescriptionClass(), opts.descriptionClass)}>${opts.description}</div>
101
+ <div data-slot="card-action" class=${cardActionClass()}>
102
+ <button type="button" data-chat-reset data-slot="button" data-variant="outline" data-size="icon" aria-label="Start over" class=${buttonClass({ variant: 'outline', size: 'icon' })}>${PlusIcon()}</button>
103
+ </div>
104
+ </div>
105
+ <div data-slot="card-content" class=${cn(cardContentClass(), 'flex-1 overflow-hidden p-0')}>
106
+ <ui-message-scroller>
107
+ <ui-message-scroller-viewport>
108
+ <ui-message-scroller-content aria-label=${`${opts.title} conversation`} class="p-[var(--card-spacing,1.5rem)]">
109
+ ${opts.transcript}
110
+ <ui-message-scroller-item hidden data-chat-thinking>
111
+ ${chatMarker({ text: 'Thinking...', status: true, icon: spinner({ decorative: true }) })}
112
+ </ui-message-scroller-item>
113
+ </ui-message-scroller-content>
114
+ </ui-message-scroller-viewport>
115
+ <ui-message-scroller-button></ui-message-scroller-button>
116
+ </ui-message-scroller>
117
+ </div>
118
+ <div data-slot="card-footer" class=${cn(cardFooterClass(), opts.footerClass)}>
119
+ ${opts.footerTop ?? ''}
120
+ ${promptInput({ id: opts.id, value: opts.prompts[0]?.text })}
121
+ </div>
122
+ </div>
123
+ </div>
124
+ </div>
125
+ </preview-03-chat>`;
126
+ }
@@ -0,0 +1,174 @@
1
+ /**
2
+ * `<preview-03-chat>` plays a scripted conversation in a preview-03 card,
3
+ * the part shadcn's demo gets from the AI SDK's useChat and a scripted
4
+ * transport.
5
+ *
6
+ * The server renders the whole script up front, every message and event
7
+ * `hidden` and tagged with its turn: `data-chat-turn="<n>"` and
8
+ * `data-chat-kind` (`user`, `reply`, `event` or `typing`), plus
9
+ * `data-chat-delay` (milliseconds after the turn starts) and, on a typing
10
+ * notice, `data-chat-name`. The card opens empty with the first prompt in the
11
+ * box, as shadcn's does. Send shows that turn's messages: a user message at
12
+ * once, then each event after its delay, then, for a turn with a reply, the
13
+ * "Thinking..." marker (`data-chat-thinking`) for the reply's delay before
14
+ * the reply itself. The box then holds the next prompt. The start-over button
15
+ * (`data-chat-reset`) hides everything again. The prompts, and who posts each
16
+ * one, are the host's `data-prompts` JSON.
17
+ *
18
+ * With JavaScript off the card shows its first state, an empty conversation
19
+ * and the queued prompt. Replace this element with your own once the card is
20
+ * wired to a real chat endpoint.
21
+ *
22
+ * Installed by `npx @webjsdev/ui add preview-03` at
23
+ * `components/preview-03/chat-player.ts`. Written for the WebJs port of
24
+ * shadcn/ui's preview-03.
25
+ */
26
+ import { WebComponent, html } from '@webjsdev/core';
27
+
28
+ interface Prompt {
29
+ text: string;
30
+ /** Who posts it, shown as "Posting as ..." in a group chat. */
31
+ sender?: string;
32
+ }
33
+
34
+ type Scroller = HTMLElement & { scrollToEnd?: () => void };
35
+
36
+ const wait = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
37
+
38
+ export class Preview03Chat extends WebComponent {
39
+ _turn = 0;
40
+ _run = 0;
41
+ _busy = false;
42
+ _step = 0;
43
+
44
+ connectedCallback() {
45
+ super.connectedCallback();
46
+ this.addEventListener('submit', this._onSubmit);
47
+ this.addEventListener('input', this._onInput);
48
+ this.addEventListener('click', this._onClick);
49
+ }
50
+
51
+ disconnectedCallback() {
52
+ this.removeEventListener('submit', this._onSubmit);
53
+ this.removeEventListener('input', this._onInput);
54
+ this.removeEventListener('click', this._onClick);
55
+ this._run++;
56
+ super.disconnectedCallback();
57
+ }
58
+
59
+ _prompts(): Prompt[] {
60
+ try {
61
+ const parsed: unknown = JSON.parse(this.getAttribute('data-prompts') ?? '[]');
62
+ return Array.isArray(parsed) ? (parsed as Prompt[]) : [];
63
+ } catch {
64
+ return [];
65
+ }
66
+ }
67
+
68
+ _items(turn: number, kind?: string): HTMLElement[] {
69
+ const kinds = kind ? `[data-chat-kind="${kind}"]` : '';
70
+ return Array.from(this.querySelectorAll<HTMLElement>(`[data-chat-turn="${turn}"]${kinds}`));
71
+ }
72
+
73
+ _show(el: Element | null, shown: boolean): void {
74
+ if (!el) return;
75
+ if (shown) el.removeAttribute('hidden');
76
+ else el.setAttribute('hidden', '');
77
+ }
78
+
79
+ _scrollToEnd(): void {
80
+ const scroller = this.querySelector<Scroller>('ui-message-scroller');
81
+ requestAnimationFrame(() => scroller?.scrollToEnd?.());
82
+ }
83
+
84
+ /** The box, the send button and the sender line, for the turn now queued. */
85
+ _queue(): void {
86
+ const prompt = this._prompts()[this._turn];
87
+ const input = this.querySelector<HTMLTextAreaElement>('[data-chat-input]');
88
+ if (input) input.value = this._busy ? '' : (prompt?.text ?? '');
89
+ const sender = this.querySelector('[data-chat-sender]');
90
+ if (sender) sender.textContent = prompt?.sender ?? 'You';
91
+ this._sync();
92
+ }
93
+
94
+ _sync(): void {
95
+ const input = this.querySelector<HTMLTextAreaElement>('[data-chat-input]');
96
+ const send = this.querySelector<HTMLButtonElement>('[data-chat-send]');
97
+ if (send) send.disabled = this._busy || !input?.value.trim();
98
+ }
99
+
100
+ async _play(): Promise<void> {
101
+ const turn = this._turn;
102
+ const prompt = this._prompts()[turn];
103
+ if (!prompt || this._busy) return;
104
+ const run = this._run;
105
+ // A turn's notices still pending stop once the next turn is sent, as in
106
+ // shadcn's (a typing notice must not land after that person has posted).
107
+ const step = ++this._step;
108
+ // A sender's own typing notice goes once their message lands.
109
+ if (prompt.sender) {
110
+ for (const el of this.querySelectorAll(`[data-chat-kind="typing"][data-chat-name="${prompt.sender}"]`)) this._show(el, false);
111
+ }
112
+ for (const el of this._items(turn, 'user')) this._show(el, true);
113
+ this._turn++;
114
+ this._busy = true;
115
+ this._queue();
116
+ this._scrollToEnd();
117
+
118
+ let elapsed = 0;
119
+ const later = [...this._items(turn, 'event'), ...this._items(turn, 'typing')]
120
+ .sort((a, b) => Number(a.dataset.chatDelay ?? 0) - Number(b.dataset.chatDelay ?? 0));
121
+ const replies = this._items(turn, 'reply');
122
+ // The events run on their own clock, so a reply is not held up by them.
123
+ const events = (async () => {
124
+ for (const el of later) {
125
+ const delay = Number(el.dataset.chatDelay ?? 0);
126
+ await wait(Math.max(0, delay - elapsed));
127
+ elapsed = delay;
128
+ if (run !== this._run || step !== this._step) return;
129
+ this._show(el, true);
130
+ this._scrollToEnd();
131
+ }
132
+ })();
133
+
134
+ if (replies.length) {
135
+ const thinking = this.querySelector('[data-chat-thinking]');
136
+ this._show(thinking, true);
137
+ this._scrollToEnd();
138
+ await wait(Number(replies[0].dataset.chatDelay ?? 1000));
139
+ if (run !== this._run) return;
140
+ this._show(thinking, false);
141
+ for (const el of replies) this._show(el, true);
142
+ this._scrollToEnd();
143
+ }
144
+ this._busy = false;
145
+ this._queue();
146
+ await events;
147
+ }
148
+
149
+ _reset(): void {
150
+ this._run++;
151
+ this._turn = 0;
152
+ this._busy = false;
153
+ for (const el of this.querySelectorAll('[data-chat-turn], [data-chat-thinking]')) this._show(el, false);
154
+ this._queue();
155
+ }
156
+
157
+ _onSubmit = (e: Event): void => {
158
+ e.preventDefault();
159
+ void this._play();
160
+ };
161
+
162
+ _onInput = (e: Event): void => {
163
+ if ((e.target as Element).matches?.('[data-chat-input]')) this._sync();
164
+ };
165
+
166
+ _onClick = (e: Event): void => {
167
+ if ((e.target as Element).closest?.('[data-chat-reset]')) this._reset();
168
+ };
169
+
170
+ render() {
171
+ return html`<slot></slot>`;
172
+ }
173
+ }
174
+ Preview03Chat.register('preview-03-chat');
@@ -0,0 +1,77 @@
1
+ /**
2
+ * The preview-03 file part: a file attached to a chat message, as the kit's
3
+ * attachment. An image shows its preview above its name and type; any other
4
+ * file shows an icon, its name and its media type. The whole attachment links
5
+ * to the file. A fragment helper, rendered by the server.
6
+ *
7
+ * Installed by `npx @webjsdev/ui add preview-03` at
8
+ * `components/preview-03/part-file.ts`. Ported from shadcn/ui's preview-03.
9
+ */
10
+ import { html } from '@webjsdev/core';
11
+ import { cn } from '../../../lib/utils.ts';
12
+ import {
13
+ attachmentActionClass,
14
+ attachmentActionsClass,
15
+ attachmentClass,
16
+ attachmentContentClass,
17
+ attachmentDescriptionClass,
18
+ attachmentMediaClass,
19
+ attachmentTitleClass,
20
+ attachmentTriggerClass,
21
+ } from '../../../components/attachment.ts';
22
+ import { badgeClass } from '../../../components/badge.ts';
23
+ import { buttonClass } from '../../../components/button.ts';
24
+ import { ExternalLinkIcon, FileTextIcon, ImageIcon } from '../../../lib/icons.ts';
25
+
26
+ export interface FilePart {
27
+ url: string;
28
+ mediaType: string;
29
+ filename?: string;
30
+ }
31
+
32
+ /** The file's name, else the last segment of its url, else a generic one. */
33
+ function filenameOf(part: FilePart): string {
34
+ if (part.filename) return part.filename;
35
+ try {
36
+ const last = new URL(part.url).pathname.split('/').filter(Boolean).pop();
37
+ if (last?.includes('.')) return decodeURIComponent(last);
38
+ } catch {
39
+ const last = part.url.split('?')[0]?.split('/').pop();
40
+ if (last?.includes('.')) return last;
41
+ }
42
+ return part.mediaType.startsWith('image/') ? 'Image file' : 'File';
43
+ }
44
+
45
+ export function partFile(opts: { part: FilePart; class?: string }) {
46
+ const { part } = opts;
47
+ const filename = filenameOf(part);
48
+ const trigger = html`<a data-slot="attachment-trigger" class=${attachmentTriggerClass()} href=${part.url} target="_blank" rel="noreferrer" aria-label=${`Open ${filename}`}></a>`;
49
+
50
+ if (part.mediaType.startsWith('image/')) {
51
+ return html`<div data-slot="attachment" data-size="default" data-orientation="vertical" class=${cn(attachmentClass({ orientation: 'vertical' }), 'group/file w-full max-w-72', opts.class)}>
52
+ <div data-slot="attachment-media" data-variant="image" class=${cn(attachmentMediaClass({ variant: 'image' }), 'aspect-[4/3] w-full')}>
53
+ <img src=${part.url} alt=${filename}>
54
+ </div>
55
+ <div data-slot="attachment-content" class=${cn(attachmentContentClass(), 'flex items-center gap-2')}>
56
+ <div data-slot="attachment-media" data-variant="icon" class=${cn(attachmentMediaClass(), 'size-7')}>${ImageIcon()}</div>
57
+ <span class="min-w-0 flex-1">
58
+ <span data-slot="attachment-title" class=${attachmentTitleClass()}>${filename}</span>
59
+ </span>
60
+ <span data-slot="badge" data-variant="outline" class=${cn(badgeClass({ variant: 'outline' }), 'shrink-0')}>${part.mediaType.replace('image/', '').toUpperCase()}</span>
61
+ </div>
62
+ ${trigger}
63
+ </div>`;
64
+ }
65
+
66
+ return html`<div data-slot="attachment" data-size="default" data-orientation="horizontal" class=${cn(attachmentClass(), 'w-full max-w-80', opts.class)}>
67
+ <div data-slot="attachment-media" data-variant="icon" class=${attachmentMediaClass()}>${FileTextIcon()}</div>
68
+ <div data-slot="attachment-content" class=${attachmentContentClass()}>
69
+ <span data-slot="attachment-title" class=${attachmentTitleClass()}>${filename}</span>
70
+ <span data-slot="attachment-description" class=${attachmentDescriptionClass()}>${part.mediaType}</span>
71
+ </div>
72
+ <div data-slot="attachment-actions" class=${attachmentActionsClass()}>
73
+ <span data-slot="attachment-action" data-variant="ghost" data-size="icon-xs" aria-hidden="true" class=${cn(buttonClass({ variant: 'ghost', size: 'icon-xs' }), attachmentActionClass())}>${ExternalLinkIcon()}</span>
74
+ </div>
75
+ ${trigger}
76
+ </div>`;
77
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The preview-03 reasoning part: one reasoning step of an assistant turn, its
3
+ * text under the kit's shimmer. A fragment helper, rendered by the server.
4
+ *
5
+ * Installed by `npx @webjsdev/ui add preview-03` at
6
+ * `components/preview-03/part-reasoning.ts`. Ported from shadcn/ui's
7
+ * preview-03.
8
+ */
9
+ import { html, nothing } from '@webjsdev/core';
10
+ import { cn } from '../../../lib/utils.ts';
11
+
12
+ const REASONING_LEVEL_LABELS = ['Understanding', 'Analyzing', 'Prioritizing', 'Refining'] as const;
13
+
14
+ /** The name of the nth reasoning step in a turn. */
15
+ export function getReasoningLevelLabel(index: number): string {
16
+ return REASONING_LEVEL_LABELS[index] ?? `Reasoning ${index + 1}`;
17
+ }
18
+
19
+ export function partReasoning(opts: { text: string; label?: string; class?: string }) {
20
+ return html`<div data-slot="part-reasoning" data-label=${opts.label ?? nothing} class=${cn('w-full max-w-full min-w-0', opts.class)}>
21
+ <div class="w-full shimmer">
22
+ <span class="whitespace-pre-wrap">${opts.text}</span>
23
+ </div>
24
+ </div>`;
25
+ }