@webjsdev/ui 0.3.16 → 0.4.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 (358) hide show
  1. package/README.md +71 -10
  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 +637 -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 +88 -0
  284. package/packages/registry/components/field.ts +165 -0
  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 +66 -0
  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/icons-hugeicons.ts +955 -0
  323. package/packages/registry/lib/icons-phosphor.ts +955 -0
  324. package/packages/registry/lib/icons-remixicon.ts +955 -0
  325. package/packages/registry/lib/icons-tabler.ts +955 -0
  326. package/packages/registry/lib/icons.ts +768 -0
  327. package/packages/registry/lib/utils.ts +49 -4
  328. package/packages/registry/registry.json +4092 -60
  329. package/packages/registry/styles/shadcn-tailwind.css +654 -0
  330. package/packages/registry/styles/style-luma.css +1987 -0
  331. package/packages/registry/styles/style-lyra.css +1965 -0
  332. package/packages/registry/styles/style-maia.css +1987 -0
  333. package/packages/registry/styles/style-mira.css +1992 -0
  334. package/packages/registry/styles/style-new-york.css +1597 -0
  335. package/packages/registry/styles/style-nova.css +1990 -0
  336. package/packages/registry/styles/style-rhea.css +1987 -0
  337. package/packages/registry/styles/style-sera.css +1977 -0
  338. package/packages/registry/styles/style-vega.css +1990 -0
  339. package/packages/registry/styles/supplement.json +54 -0
  340. package/packages/registry/styles/tw-animate.css +6 -0
  341. package/packages/registry/themes/base-colors.js +8 -2
  342. package/packages/registry/themes/fonts.js +120 -0
  343. package/packages/registry/themes/index.css +2 -0
  344. package/packages/registry/themes/items.js +61 -0
  345. package/packages/registry/themes/preset.js +302 -0
  346. package/packages/registry/themes/themes.js +1193 -0
  347. package/src/commands/add.js +236 -12
  348. package/src/commands/diff.js +34 -20
  349. package/src/commands/info.js +7 -0
  350. package/src/commands/init.js +125 -8
  351. package/src/commands/list.js +43 -11
  352. package/src/commands/view.js +33 -5
  353. package/src/registry/extract.js +192 -2
  354. package/src/registry/icons.js +31 -0
  355. package/src/registry/local.js +15 -1
  356. package/src/registry/schema.js +13 -0
  357. package/src/registry/style-bake.js +506 -0
  358. package/src/utils/theme.js +110 -21
@@ -0,0 +1,470 @@
1
+ /**
2
+ * Message scroller: the scroll container for a chat transcript. Tier-2. A
3
+ * port of shadcn's MessageScroller (the headless primitive in
4
+ * `@shadcn/react`, styled): it opens at the newest message, follows new ones
5
+ * while the reader is at the end, leaves them where they are once they have
6
+ * scrolled up, and offers a button back to the end.
7
+ *
8
+ * shadcn parity:
9
+ * MessageScroller.Provider + MessageScroller
10
+ * → <ui-message-scroller auto-scroll default-scroll-position
11
+ * scroll-edge-threshold scroll-previous-item-peek>
12
+ * MessageScrollerViewport → <ui-message-scroller-viewport>
13
+ * MessageScrollerContent → <ui-message-scroller-content> (a role="log")
14
+ * MessageScrollerItem (messageId, scrollAnchor)
15
+ * → <ui-message-scroller-item message-id scroll-anchor>
16
+ * MessageScrollerButton direction, children
17
+ * → <ui-message-scroller-button direction="end" | "start" label>,
18
+ * its children in place of the arrow
19
+ * useMessageScroller() → the element: scrollToEnd(), scrollToStart(), scrollToMessage(id)
20
+ * useMessageScrollerScrollable()
21
+ * → `scrollable` ({ start, end }) and `ui-scrollable-change`
22
+ * useMessageScrollerVisibility()
23
+ * → `visibleMessageIds` and `ui-visibility-change`
24
+ *
25
+ * `default-scroll-position` is where it opens: "end" (the default), "start",
26
+ * or "last-anchor", the last item marked `scroll-anchor` at the top (a new
27
+ * question with the answer streaming in under it). The transcript is always
28
+ * served visible, so it reads with JavaScript off (the opening position is
29
+ * then the start, the browser's own). A scroller the browser builds on the
30
+ * client, which has never painted, is held invisible until that position
31
+ * applies, so the reader never sees a jump; one the server rendered moves
32
+ * to it once its script runs.
33
+ * After that, an item that ARRIVES marked `scroll-anchor` (the question a
34
+ * reader just sent) settles near the top with `scroll-previous-item-peek`
35
+ * pixels (64 by default, shadcn's) of the previous turn still in view, and stays there while the reply streams in below it: a
36
+ * tail spacer at the end of the list makes the room, and shrinks as the
37
+ * reply grows. Once the reply fills the viewport, `auto-scroll` follows it.
38
+ * Messages added at the top keep the reader's place through the browser's
39
+ * own scroll anchoring. `scroll-edge-threshold` (8 pixels by default,
40
+ * shadcn's) is how near an edge counts as being at it: what keeps the
41
+ * scroller following, and what shows the button.
42
+ *
43
+ * A11y (handled by the element, plus your part): the content is a
44
+ * `role="log"` that announces additions, and the button is named "Scroll to
45
+ * end" / "Scroll to start" (or its `label`) and is inert while there is
46
+ * nowhere to go. Your
47
+ * part: label the transcript (`aria-label` on `<ui-message-scroller-content>`).
48
+ *
49
+ * @example
50
+ * ```html
51
+ * <ui-message-scroller auto-scroll class="h-96">
52
+ * <ui-message-scroller-viewport>
53
+ * <ui-message-scroller-content aria-label="Conversation">
54
+ * <ui-message-scroller-item message-id="m1">Hello</ui-message-scroller-item>
55
+ * <ui-message-scroller-item message-id="m2" scroll-anchor>What is WebJs?</ui-message-scroller-item>
56
+ * </ui-message-scroller-content>
57
+ * </ui-message-scroller-viewport>
58
+ * <ui-message-scroller-button></ui-message-scroller-button>
59
+ * </ui-message-scroller>
60
+ * ```
61
+ */
62
+ import { WebComponent, html, prop, signal, nothing } from '@webjsdev/core';
63
+ import { cn, takeAuthoredClass } from '../lib/utils.ts';
64
+ import { buttonClass, type ButtonVariant, type ButtonSize } from './button.ts';
65
+
66
+ /** The frame's classes (the element applies them). */
67
+ export const messageScrollerClass = (): string =>
68
+ 'cn-message-scroller group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden';
69
+ /** The scrolling viewport (the element applies them). */
70
+ export const messageScrollerViewportClass = (): string =>
71
+ 'cn-message-scroller-viewport size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-thumb-transparent data-autoscrolling:scrollbar-track-transparent data-[pending-scroll]:invisible';
72
+ /** The message list (the element applies them). */
73
+ export const messageScrollerContentClass = (): string =>
74
+ 'cn-message-scroller-content flex h-max min-h-full flex-col';
75
+ /** One message (the element puts them on the item itself). */
76
+ export const messageScrollerItemClass = (): string =>
77
+ 'cn-message-scroller-item min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]';
78
+ /** The scroll button (the element applies them). */
79
+ export const messageScrollerButtonClass = (): string =>
80
+ 'cn-message-scroller-button absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180';
81
+
82
+ const ROOT = 'ui-message-scroller';
83
+ // How near an edge counts as being at it, in pixels, and how much of the
84
+ // previous turn stays in view above a newly anchored one: shadcn's defaults
85
+ // (DEFAULT_SCROLL_EDGE_THRESHOLD and DEFAULT_SCROLL_PREVIOUS_ITEM_PEEK).
86
+ const EDGE = 8;
87
+ const PEEK = 64;
88
+
89
+ // shadcn's className lands on the element each part renders (the frame, the
90
+ // viewport, the list, the button), so each host hands its authored class to
91
+ // that element and becomes display: contents. A block host would otherwise
92
+ // sit between the frame's flex column and the viewport, the viewport would
93
+ // grow to its content, and nothing would scroll.
94
+ function takeAuthored(part: HTMLElement): string | null {
95
+ return takeAuthoredClass(part, 'contents');
96
+ }
97
+
98
+ function rootOf(el: Element): UiMessageScroller | null {
99
+ return (typeof el.closest === 'function' ? el.closest(ROOT) : null) as UiMessageScroller | null;
100
+ }
101
+
102
+ // --------------------------------------------------------------------------
103
+ // <ui-message-scroller>
104
+ // --------------------------------------------------------------------------
105
+
106
+ export class UiMessageScroller extends WebComponent({
107
+ autoScroll: prop(Boolean, { attribute: 'auto-scroll' }),
108
+ defaultScrollPosition: prop<'end' | 'start' | 'last-anchor'>(String, { attribute: 'default-scroll-position' }),
109
+ scrollEdgeThreshold: prop(Number, { attribute: 'scroll-edge-threshold' }),
110
+ scrollPreviousItemPeek: prop(Number, { attribute: 'scroll-previous-item-peek' }),
111
+ }) {
112
+ // Served visible: a transcript must read with JavaScript off.
113
+ readonly pending = signal(false);
114
+ /** The edges the viewport can still scroll toward. */
115
+ scrollable = { start: false, end: false };
116
+ /** The messages on screen, by `message-id`. */
117
+ visibleMessageIds: string[] = [];
118
+ _following = true;
119
+ _opened = false;
120
+ _resize: ResizeObserver | null = null;
121
+ _visible: IntersectionObserver | null = null;
122
+ _shown = new Set<string>();
123
+ // Turn anchoring: the anchored items already placed, the one being held,
124
+ // the scroll position that holds it, and the tail spacer's height.
125
+ _anchored = new WeakSet<Element>();
126
+ _held: Element | null = null;
127
+ _heldTop = 0;
128
+ _spacerHeight = 0;
129
+ _growFrame = 0;
130
+
131
+ constructor() {
132
+ super();
133
+ this.autoScroll = false;
134
+ this.defaultScrollPosition = 'end';
135
+ this.scrollEdgeThreshold = EDGE;
136
+ this.scrollPreviousItemPeek = PEEK;
137
+ }
138
+
139
+ connectedCallback(): void {
140
+ // A scroller built in the browser has not painted yet, so it is held
141
+ // invisible until its opening position applies. One the server rendered
142
+ // has painted already (its frame is in the markup), and hiding it now
143
+ // would blank text the reader can see, so it moves in place instead.
144
+ if (!this._opened && typeof this.querySelector === 'function' && !this.querySelector('[data-slot="message-scroller"]')) this.pending.set(true);
145
+ super.connectedCallback?.();
146
+ queueMicrotask(() => this._setup());
147
+ }
148
+
149
+ _edge(): number {
150
+ const n = Number(this.scrollEdgeThreshold);
151
+ return Number.isFinite(n) && n >= 0 ? n : EDGE;
152
+ }
153
+
154
+ _peek(): number {
155
+ const n = Number(this.scrollPreviousItemPeek);
156
+ return Number.isFinite(n) && n >= 0 ? n : PEEK;
157
+ }
158
+
159
+ disconnectedCallback(): void {
160
+ cancelAnimationFrame(this._growFrame);
161
+ this._resize?.disconnect();
162
+ this._visible?.disconnect();
163
+ this._resize = null;
164
+ this._visible = null;
165
+ super.disconnectedCallback?.();
166
+ }
167
+
168
+ render() {
169
+ return html`<div data-slot="message-scroller" ?data-pending-scroll=${this.pending.get()} class=${cn(messageScrollerClass(), takeAuthored(this))}><slot></slot></div>`;
170
+ }
171
+
172
+ viewport(): HTMLElement | null {
173
+ return this.querySelector<HTMLElement>('[data-slot="message-scroller-viewport"]');
174
+ }
175
+
176
+ _content(): HTMLElement | null {
177
+ return this.querySelector<HTMLElement>('[data-slot="message-scroller-content"]');
178
+ }
179
+
180
+ _items(): UiMessageScrollerItem[] {
181
+ if (typeof this.querySelectorAll !== 'function') return [];
182
+ return Array.from(this.querySelectorAll<UiMessageScrollerItem>('ui-message-scroller-item')).filter((i) => rootOf(i) === this);
183
+ }
184
+
185
+ _setup(): void {
186
+ const viewport = this.viewport();
187
+ const content = this._content();
188
+ if (!viewport || !content) {
189
+ requestAnimationFrame(() => this._setup());
190
+ return;
191
+ }
192
+ viewport.addEventListener('scroll', this._onScroll, { passive: true });
193
+ // New or growing messages: follow them if the reader is at the end.
194
+ if (typeof ResizeObserver === 'function') {
195
+ // Following the end is decided at once, before the next frame's scroll
196
+ // event can read the grown list as "scrolled away". The spacer is fitted
197
+ // a frame later, since resizing it inside the observed content would
198
+ // otherwise loop the observer; its own resize then comes back here.
199
+ this._resize = new ResizeObserver(() => {
200
+ this._onGrow();
201
+ cancelAnimationFrame(this._growFrame);
202
+ this._growFrame = requestAnimationFrame(() => this._fitSpacer());
203
+ });
204
+ this._resize.observe(content);
205
+ }
206
+ if (typeof IntersectionObserver === 'function') {
207
+ this._visible = new IntersectionObserver(this._onIntersect, { root: viewport });
208
+ for (const item of this._items()) this._visible.observe(item);
209
+ }
210
+ requestAnimationFrame(() => this._open());
211
+ }
212
+
213
+ // The opening position, applied once the messages have laid out.
214
+ _open(): void {
215
+ const viewport = this.viewport();
216
+ if (!viewport) return;
217
+ const pos = this.defaultScrollPosition;
218
+ if (pos === 'start') viewport.scrollTop = 0;
219
+ else if (pos === 'last-anchor') {
220
+ const anchors = this._items().filter((i) => i.hasAttribute('scroll-anchor'));
221
+ const last = anchors[anchors.length - 1];
222
+ if (last) this._scrollToItem(last, 'start', 'auto');
223
+ else viewport.scrollTop = viewport.scrollHeight;
224
+ } else viewport.scrollTop = viewport.scrollHeight;
225
+ this._opened = true;
226
+ // The turns present at open are placed by the opening position.
227
+ for (const item of this._items()) if (item.hasAttribute('scroll-anchor')) this._anchored.add(item);
228
+ this._following = this._atEnd();
229
+ this.pending.set(false);
230
+ // The viewport draws its own pending flag, so it redraws with it.
231
+ this.querySelector<UiMessageScrollerViewport>('ui-message-scroller-viewport')?.requestUpdate?.();
232
+ this._measure();
233
+ }
234
+
235
+ _atEnd(): boolean {
236
+ const v = this.viewport();
237
+ return !!v && v.scrollHeight - v.scrollTop - v.clientHeight <= this._edge();
238
+ }
239
+
240
+ _onScroll = (): void => {
241
+ // A scroll the reader makes away from the end stops the following; one
242
+ // back to the end resumes it.
243
+ if (this._opened) this._following = this._atEnd();
244
+ this._measure();
245
+ };
246
+
247
+ _onGrow = (): void => {
248
+ if (!this._opened) return;
249
+ if (this.autoScroll && this._following) {
250
+ const v = this.viewport();
251
+ if (v) {
252
+ v.setAttribute('data-autoscrolling', '');
253
+ v.scrollTop = v.scrollHeight;
254
+ requestAnimationFrame(() => v.removeAttribute('data-autoscrolling'));
255
+ }
256
+ }
257
+ this._measure();
258
+ };
259
+
260
+ _measure(): void {
261
+ const v = this.viewport();
262
+ if (!v) return;
263
+ const edge = this._edge();
264
+ const next = { start: v.scrollTop > edge, end: v.scrollHeight - v.scrollTop - v.clientHeight > edge };
265
+ if (next.start !== this.scrollable.start || next.end !== this.scrollable.end) {
266
+ this.scrollable = next;
267
+ this.dispatchEvent(new CustomEvent('ui-scrollable-change', { bubbles: true, detail: { ...next } }));
268
+ }
269
+ for (const b of Array.from(this.querySelectorAll<UiMessageScrollerButton>('ui-message-scroller-button'))) b.requestUpdate?.();
270
+ }
271
+
272
+ _onIntersect = (entries: IntersectionObserverEntry[]): void => {
273
+ for (const e of entries) {
274
+ const id = (e.target as Element).getAttribute('message-id');
275
+ if (!id) continue;
276
+ if (e.isIntersecting) this._shown.add(id);
277
+ else this._shown.delete(id);
278
+ }
279
+ const ids = this._items().map((i) => i.getAttribute('message-id')).filter((id): id is string => !!id && this._shown.has(id));
280
+ this.visibleMessageIds = ids;
281
+ this.dispatchEvent(new CustomEvent('ui-visibility-change', { bubbles: true, detail: { visibleMessageIds: ids } }));
282
+ };
283
+
284
+ // An item that arrives after setup is tracked too.
285
+ _itemConnected(item: UiMessageScrollerItem): void {
286
+ this._visible?.observe(item);
287
+ // A new turn marked scroll-anchor settles near the top, a peek of the
288
+ // previous turn above it, as shadcn's does. Placed once per item, since
289
+ // an item can connect again when the list re-renders around it.
290
+ if (this._opened && item.hasAttribute('scroll-anchor') && !this._anchored.has(item)) {
291
+ this._anchored.add(item);
292
+ requestAnimationFrame(() => this._anchorTurn(item));
293
+ }
294
+ }
295
+
296
+ _spacer(): HTMLElement | null {
297
+ return this.querySelector<HTMLElement>('[data-message-scroller-spacer]');
298
+ }
299
+
300
+ // Scroll a new anchored turn to the top, keeping the peek of the turn
301
+ // before it, with room made below by the tail spacer when the conversation
302
+ // is still too short to scroll that far.
303
+ _anchorTurn(item: Element): void {
304
+ const v = this.viewport();
305
+ const content = this._content();
306
+ if (!v || !content || !item.isConnected) return;
307
+ const pad = parseFloat(getComputedStyle(content).paddingTop) || 0;
308
+ // Where the turn sits in the layout, read through offsetTop so a
309
+ // transform on it (an entrance sliding it up) does not move the target.
310
+ const listTop = v.scrollTop + content.getBoundingClientRect().top - v.getBoundingClientRect().top;
311
+ const top = listTop + (item as HTMLElement).offsetTop - content.offsetTop;
312
+ this._held = item;
313
+ this._heldTop = Math.max(0, top - pad - this._peek());
314
+ this._fitSpacer();
315
+ v.scrollTo({ top: this._heldTop, behavior: this._behavior() });
316
+ }
317
+
318
+ // The spacer fills exactly the room the held turn needs below it, so it
319
+ // shrinks as the reply streams in and the turn stays where it is. Once the
320
+ // reply fills the viewport the spacer is gone, and a following viewport
321
+ // (auto-scroll) takes over from the end.
322
+ _fitSpacer(): void {
323
+ const v = this.viewport();
324
+ const spacer = this._spacer();
325
+ if (!v || !spacer) return;
326
+ if (this._held && !this._held.isConnected) this._held = null;
327
+ const natural = v.scrollHeight - this._spacerHeight;
328
+ const next = this._held ? Math.max(0, Math.ceil(this._heldTop + v.clientHeight - natural)) : 0;
329
+ if (next === this._spacerHeight) return;
330
+ this._spacerHeight = next;
331
+ if (next === 0) this._held = null;
332
+ const content = this._content();
333
+ const gap = content ? parseFloat(getComputedStyle(content).rowGap) || 0 : 0;
334
+ spacer.hidden = next === 0;
335
+ spacer.style.height = `${next}px`;
336
+ // The list's flex gap would add itself above the spacer, so it is taken
337
+ // back. The spacer is never the browser's scroll anchor (overflow-anchor:
338
+ // none): it is the last thing in view, so the browser would keep IT in
339
+ // place as the reply grows above it, pushing the held turn up a line at
340
+ // a time.
341
+ spacer.style.marginTop = next > 0 ? `${-gap}px` : '';
342
+ }
343
+
344
+ _scrollToItem(item: Element, align: 'start' | 'center' | 'end' | 'nearest', behavior: ScrollBehavior): void {
345
+ const v = this.viewport();
346
+ if (!v) return;
347
+ const vr = v.getBoundingClientRect();
348
+ const ir = item.getBoundingClientRect();
349
+ let top = v.scrollTop + (ir.top - vr.top);
350
+ if (align === 'end') top -= vr.height - ir.height;
351
+ else if (align === 'center') top -= (vr.height - ir.height) / 2;
352
+ else if (align === 'nearest') {
353
+ if (ir.top >= vr.top && ir.bottom <= vr.bottom) return;
354
+ if (ir.bottom > vr.bottom) top -= vr.height - ir.height;
355
+ }
356
+ v.scrollTo({ top, behavior });
357
+ }
358
+
359
+ _behavior(): ScrollBehavior {
360
+ return typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth';
361
+ }
362
+
363
+ /** Scroll to the newest message, and follow new ones again. */
364
+ scrollToEnd(): void {
365
+ const v = this.viewport();
366
+ if (!v) return;
367
+ this._following = true;
368
+ v.scrollTo({ top: v.scrollHeight, behavior: this._behavior() });
369
+ }
370
+
371
+ /** Scroll to the oldest message. */
372
+ scrollToStart(): void {
373
+ this.viewport()?.scrollTo({ top: 0, behavior: this._behavior() });
374
+ }
375
+
376
+ /** Scroll the message with `id` into view. */
377
+ scrollToMessage(id: string, opts: { align?: 'start' | 'center' | 'end' | 'nearest'; behavior?: ScrollBehavior } = {}): void {
378
+ const item = this._items().find((i) => i.getAttribute('message-id') === id);
379
+ if (item) this._scrollToItem(item, opts.align ?? 'start', opts.behavior ?? this._behavior());
380
+ }
381
+ }
382
+ UiMessageScroller.register('ui-message-scroller');
383
+
384
+ // --------------------------------------------------------------------------
385
+ // <ui-message-scroller-viewport> and <ui-message-scroller-content>
386
+ // --------------------------------------------------------------------------
387
+
388
+ export class UiMessageScrollerViewport extends WebComponent {
389
+ render() {
390
+ const pending = rootOf(this)?.pending?.get() ?? false;
391
+ return html`<div data-slot="message-scroller-viewport" ?data-pending-scroll=${!!pending} class=${cn(messageScrollerViewportClass(), takeAuthored(this))}><slot></slot></div>`;
392
+ }
393
+ }
394
+ UiMessageScrollerViewport.register('ui-message-scroller-viewport');
395
+
396
+ export class UiMessageScrollerContent extends WebComponent {
397
+ render() {
398
+ return html`<div
399
+ data-slot="message-scroller-content"
400
+ role="log"
401
+ aria-relevant="additions"
402
+ aria-label=${this.getAttribute?.('aria-label') || nothing}
403
+ class=${cn(messageScrollerContentClass(), takeAuthored(this))}
404
+ ><slot></slot><div data-message-scroller-spacer aria-hidden="true" hidden style="overflow-anchor: none"></div></div>`;
405
+ }
406
+ }
407
+ UiMessageScrollerContent.register('ui-message-scroller-content');
408
+
409
+ // --------------------------------------------------------------------------
410
+ // <ui-message-scroller-item>
411
+ // --------------------------------------------------------------------------
412
+
413
+ export class UiMessageScrollerItem extends WebComponent {
414
+ _authored: string | null = null;
415
+
416
+ connectedCallback(): void {
417
+ super.connectedCallback?.();
418
+ rootOf(this)?._itemConnected(this);
419
+ }
420
+
421
+ // An item is a flex child of the column, so it carries its own classes.
422
+ render() {
423
+ this._authored = takeAuthoredClass(this);
424
+ if (typeof this.setAttribute === 'function') {
425
+ this.setAttribute('class', cn(messageScrollerItemClass(), this._authored));
426
+ this.setAttribute('data-slot', 'message-scroller-item');
427
+ }
428
+ return html`<slot></slot>`;
429
+ }
430
+ }
431
+ UiMessageScrollerItem.register('ui-message-scroller-item');
432
+
433
+ // --------------------------------------------------------------------------
434
+ // <ui-message-scroller-button>
435
+ // --------------------------------------------------------------------------
436
+
437
+ export class UiMessageScrollerButton extends WebComponent({
438
+ direction: prop<'end' | 'start'>(String),
439
+ // The button's accessible name, for a transcript in another language.
440
+ label: String,
441
+ variant: String,
442
+ size: String,
443
+ }) {
444
+ constructor() {
445
+ super();
446
+ this.direction = 'end';
447
+ this.variant = 'secondary';
448
+ this.size = 'icon-sm';
449
+ }
450
+
451
+ render() {
452
+ const root = rootOf(this);
453
+ const toStart = this.direction === 'start';
454
+ const active = !!root && (toStart ? root.scrollable.start : root.scrollable.end);
455
+ return html`<button
456
+ type="button"
457
+ data-slot="message-scroller-button"
458
+ data-direction=${toStart ? 'start' : 'end'}
459
+ data-variant=${this.variant}
460
+ data-size=${this.size}
461
+ data-active=${active ? 'true' : 'false'}
462
+ tabindex=${active ? nothing : '-1'}
463
+ aria-hidden=${active ? nothing : 'true'}
464
+ class=${cn(buttonClass({ variant: this.variant as ButtonVariant, size: this.size as ButtonSize }), messageScrollerButtonClass(), takeAuthored(this))}
465
+ @click=${() => (toStart ? root?.scrollToStart() : root?.scrollToEnd())}
466
+ aria-label=${this.label || nothing}
467
+ ><slot><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14"></path><path d="m19 12-7 7-7-7"></path></svg>${this.label ? '' : html`<span class="sr-only">${toStart ? 'Scroll to start' : 'Scroll to end'}</span>`}</slot></button>`;
468
+ }
469
+ }
470
+ UiMessageScrollerButton.register('ui-message-scroller-button');
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Message: one entry in a conversation (a chat bubble with its avatar,
3
+ * header and footer), and the group that stacks several. Tier-1 class
4
+ * helper; compose with plain elements, and pair with the bubble helpers for
5
+ * the speech bubble itself.
6
+ *
7
+ * shadcn parity:
8
+ * MessageGroup → messageGroupClass()
9
+ * Message → messageClass(), with data-align="start" | "end"
10
+ * MessageAvatar → messageAvatarClass()
11
+ * MessageContent → messageContentClass()
12
+ * MessageHeader → messageHeaderClass()
13
+ * MessageFooter → messageFooterClass()
14
+ *
15
+ * `data-align="end"` on the message mirrors it to the inline end (the user's
16
+ * own messages), and the footer follows. Alignment is logical, so it flips
17
+ * under `dir="rtl"`.
18
+ *
19
+ * A11y (required for accessible output): render the conversation as a list
20
+ * (`<ol>` of messages, or `role="log"` on the container when new messages
21
+ * arrive live, which also makes them announced). Each message should say who
22
+ * sent it in text a screen reader reaches, the header or a visually hidden
23
+ * name, and an avatar image needs `alt` (or `alt=""` when the name is
24
+ * already in the header).
25
+ *
26
+ * Design tokens used: --muted, --muted-foreground.
27
+ *
28
+ * @example
29
+ * ```html
30
+ * <ol class=${messageGroupClass()} role="log" aria-label="Conversation">
31
+ * <li class=${messageClass()} data-align="end">
32
+ * <div class=${messageContentClass()}>
33
+ * <div class=${messageHeaderClass()}>You</div>
34
+ * <p>Can you ship it today?</p>
35
+ * </div>
36
+ * </li>
37
+ * </ol>
38
+ * ```
39
+ */
40
+
41
+ /** The stack of messages. */
42
+ export function messageGroupClass(): string {
43
+ return 'cn-message-group flex min-w-0 flex-col';
44
+ }
45
+
46
+ /** One message row. `data-align="end"` mirrors it to the inline end. */
47
+ export function messageClass(): string {
48
+ return 'cn-message group/message relative flex w-full min-w-0 data-[align=end]:flex-row-reverse';
49
+ }
50
+
51
+ /** The sender's avatar beside the message. */
52
+ export function messageAvatarClass(): string {
53
+ return 'cn-message-avatar flex w-fit shrink-0 items-center justify-center self-end overflow-hidden rounded-full bg-muted';
54
+ }
55
+
56
+ /** The column holding the header, the bubble and the footer. */
57
+ export function messageContentClass(): string {
58
+ return 'cn-message-content flex w-full min-w-0 flex-col wrap-break-word';
59
+ }
60
+
61
+ /** The sender name and time above the bubble. */
62
+ export function messageHeaderClass(): string {
63
+ return 'cn-message-header flex max-w-full min-w-0 items-center';
64
+ }
65
+
66
+ /** Actions or status below the bubble. */
67
+ export function messageFooterClass(): string {
68
+ return 'cn-message-footer flex max-w-full min-w-0 items-center group-data-[align=end]/message:justify-end';
69
+ }
@@ -73,18 +73,18 @@ export type NativeSelectSize = 'default' | 'sm';
73
73
  // convention that every part has a class helper.
74
74
 
75
75
  export const nativeSelectWrapperClass = (): string =>
76
- 'group/native-select relative w-fit has-[select:disabled]:opacity-50';
76
+ 'cn-native-select-wrapper group/native-select relative w-fit has-[select:disabled]:opacity-50';
77
77
 
78
78
  export function nativeSelectClass(): string {
79
79
  return cn(
80
- 'h-9 w-full min-w-0 appearance-none rounded-md border border-input bg-transparent px-3 py-2 pr-9 text-sm shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8 data-[size=sm]:py-1 dark:bg-input/30 dark:hover:bg-input/50',
81
- 'focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50',
82
- 'aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40',
80
+ 'cn-native-select outline-none disabled:pointer-events-none disabled:cursor-not-allowed',
81
+ 'cn-native-select-part-2',
82
+ 'cn-native-select-part-3',
83
83
  );
84
84
  }
85
85
 
86
86
  export const nativeSelectIconClass = (): string =>
87
- 'pointer-events-none absolute top-1/2 right-3.5 size-4 -translate-y-1/2 text-muted-foreground opacity-50 select-none';
87
+ 'cn-native-select-icon pointer-events-none absolute select-none';
88
88
 
89
89
  /** Option / optgroup styling: forces themed background even in dark mode. */
90
90
  export const nativeSelectOptionClass = (): string => 'bg-[Canvas] text-[CanvasText]';