@webjsdev/ui 0.3.17 → 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 +66 -7
  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 +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/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 +4056 -72
  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
@@ -12,11 +12,10 @@
12
12
  * Design tokens used: --input, --primary, --ring, --destructive.
13
13
  *
14
14
  * A11y (required for accessible output):
15
- * `data-slot="radio"` is REQUIRED, not decoration. The injected stylesheet
16
- * keys the indicator dot on it, and `radioClass()` carries no checked
17
- * background fill, so without the attribute a SELECTED radio differs from an
18
- * unselected one by border colour alone. That is both easy to miss and a
19
- * WCAG 1.4.1 problem (state by colour only). Every example here carries it.
15
+ * The dot is drawn by the class itself, so a selected radio never differs
16
+ * from an unselected one by colour alone (WCAG 1.4.1), with or without
17
+ * JavaScript. Keep `data-slot="radio"` on the input, as every example here
18
+ * does, since the styles' field rules select on it.
20
19
  * NAME THE GROUP. A bare `<div role="radiogroup">` has no accessible name, so
21
20
  * a screen reader announces "radio group" with no idea what is being chosen.
22
21
  * Point `aria-labelledby` at the visible group label, as below, or use a
@@ -48,68 +47,17 @@
48
47
  */
49
48
  import { cn } from '../lib/utils.ts';
50
49
 
51
- // Two SVGs, one per theme. The dot needs to contrast with the radio's
52
- // inner surface: and that surface flips between themes:
53
- //
54
- // light: input bg is `bg-transparent` (so the page bg shows through;
55
- // page bg is near-white) → dot must be DARK to be visible.
56
- // dark : input bg is `dark:bg-input/30` (a translucent white over the
57
- // near-black page bg; resolves to near-black) → dot must be
58
- // LIGHT to be visible.
59
- //
60
- // Hardcoding a single dark-coloured dot (the original implementation)
61
- // painted invisibly on the near-black dark-mode surface, making the
62
- // :checked state indistinguishable from unchecked. Same pattern the
63
- // checkbox fix uses (CHECKMARK_LIGHT / CHECKMARK_DARK): `currentColor`
64
- // in a data:url SVG used as background-image does not inherit from the
65
- // host element, so we ship two SVGs and toggle them via a theme
66
- // selector.
67
- const DOT_LIGHT =
68
- "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><circle cx='10' cy='10' r='5' fill='oklch(0.205 0 0)'/></svg>\")";
69
- const DOT_DARK =
70
- "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'><circle cx='10' cy='10' r='5' fill='oklch(0.985 0 0)'/></svg>\")";
71
-
50
+ // The dot is a radial gradient in `currentColor`, the radio's own text colour,
51
+ // which the style chooses. shadcn's styles fill a checked radio with the
52
+ // primary colour and set `data-checked:text-primary-foreground`, so the dot is
53
+ // the light one on the fill; the default style keeps a transparent ring and
54
+ // sets `checked:text-primary`, so the dot is the primary one. A fixed colour
55
+ // (the SVG this replaced, one per theme) could only match one of the two, and
56
+ // disappeared into the fill under every shadcn style. Half the box across,
57
+ // as shadcn's indicator is. It rides the class itself, so a checked radio
58
+ // paints in the first paint and with JavaScript off.
72
59
  const RADIO_CLASS =
73
- 'aspect-square size-4 shrink-0 appearance-none rounded-full border border-input bg-transparent shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 checked:border-primary checked:bg-no-repeat checked:bg-center dark:bg-input/30 dark:aria-invalid:ring-destructive/40';
74
-
75
- // Three sibling rule blocks for theme selection: mirrors the
76
- // checkbox.ts pattern in this same registry:
77
- // - prefers-color-scheme: dark (OS preference, gated by
78
- // :not([data-theme='light']):not(.light) so an explicit-light
79
- // toggle still wins over the OS)
80
- // - :root[data-theme='dark'] (explicit data-attribute toggle)
81
- // - :root.dark (explicit class toggle, shadcn convention)
82
- const STYLES = `
83
- input[type="radio"][data-slot="radio"]:checked {
84
- background-image: ${DOT_LIGHT};
85
- background-size: 100%;
86
- }
87
- @media (prefers-color-scheme: dark) {
88
- :root:not([data-theme='light']):not(.light) input[type="radio"][data-slot="radio"]:checked {
89
- background-image: ${DOT_DARK};
90
- }
91
- }
92
- :root[data-theme='dark'] input[type="radio"][data-slot="radio"]:checked,
93
- :root.dark input[type="radio"][data-slot="radio"]:checked {
94
- background-image: ${DOT_DARK};
95
- }
96
- `;
97
-
98
- let installed = false;
99
- export function installRadioStyles(): void {
100
- if (installed || typeof document === 'undefined') return;
101
- if (document.getElementById('ui-radio-styles')) {
102
- installed = true;
103
- return;
104
- }
105
- const style = document.createElement('style');
106
- style.id = 'ui-radio-styles';
107
- style.textContent = STYLES;
108
- document.head.appendChild(style);
109
- installed = true;
110
- }
111
-
112
- if (typeof document !== 'undefined') installRadioStyles();
60
+ 'cn-radio-group-item group/radio-group-item peer aspect-square shrink-0 appearance-none border outline-none disabled:cursor-not-allowed disabled:opacity-50 checked:bg-[image:radial-gradient(circle_closest-side,currentColor_50%,transparent_calc(50%+0.5px))]';
113
61
 
114
62
  /** Tailwind classes for a `<div role="radiogroup">` container. */
115
63
  export type RadioGroupOrientation = 'vertical' | 'horizontal';
@@ -127,16 +75,13 @@ export function radioGroupClass(opts: { orientation?: RadioGroupOrientation } =
127
75
  const orientation = opts.orientation ?? 'vertical';
128
76
  return orientation === 'horizontal'
129
77
  ? 'flex flex-wrap gap-x-6 gap-y-3'
130
- : 'grid gap-3';
78
+ : 'cn-radio-group';
131
79
  }
132
80
 
133
81
  /**
134
- * Tailwind classes for a styled `<input type="radio">`.
135
- *
136
- * PAIR THIS WITH `data-slot="radio"` ON THE SAME INPUT. The injected stylesheet
137
- * keys the indicator dot on that attribute, and this class deliberately carries
138
- * no checked background fill, so the class alone leaves a selected radio
139
- * differing from an unselected one by border colour and nothing else.
82
+ * Tailwind classes for a styled `<input type="radio">`. The class draws the
83
+ * checked dot itself, so a selected radio paints with JavaScript off. Keep
84
+ * `data-slot="radio"` on the input as shadcn does.
140
85
  */
141
86
  export function radioClass(): string {
142
87
  return cn(RADIO_CLASS);
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Resizable: panels in a row or a column with draggable handles between
3
+ * them. Tier-2. shadcn's is react-resizable-panels; this is the same layout
4
+ * on flex shares and Pointer Events, with no dependency. The server renders
5
+ * the default sizes, so the layout is in the first paint; resizing needs
6
+ * JavaScript.
7
+ *
8
+ * shadcn parity:
9
+ * ResizablePanelGroup orientation
10
+ * → <ui-resizable-panel-group orientation="horizontal" | "vertical">
11
+ * ResizablePanel (defaultSize, minSize, maxSize)
12
+ * → <ui-resizable-panel default-size min-size max-size> (percentages)
13
+ * ResizableHandle withHandle
14
+ * → <ui-resizable-handle with-handle>
15
+ * onLayout → `ui-layout-change` ({ detail: { sizes } }), percentages in order
16
+ *
17
+ * A panel with no `default-size` shares what the sized panels leave (give
18
+ * every panel a size for an exact server-rendered first paint). A drag
19
+ * or a key moves the boundary between the two panels around a handle, each
20
+ * kept within its `min-size` and `max-size`.
21
+ *
22
+ * Keyboard (the WAI-ARIA window splitter): a handle is a focusable
23
+ * separator; the arrows across the group (Left / Right in a row, Up / Down in
24
+ * a column; Left / Right swap under `dir="rtl"`) move it 10 points, Home and
25
+ * End move it as far as the panel before it allows.
26
+ *
27
+ * A11y (handled by the element): each handle is a `role="separator"` with
28
+ * `aria-orientation`, `aria-controls` naming the panel before it, and that
29
+ * panel's size as `aria-valuenow` within its `aria-valuemin` / `aria-valuemax`.
30
+ * Give the panels' content its own headings or labels, since a separator says
31
+ * only how big the panel is.
32
+ *
33
+ * @example
34
+ * ```html
35
+ * <ui-resizable-panel-group orientation="horizontal" class="max-w-md rounded-lg border">
36
+ * <ui-resizable-panel default-size="50"><div class="flex h-[200px] items-center justify-center p-6">One</div></ui-resizable-panel>
37
+ * <ui-resizable-handle with-handle></ui-resizable-handle>
38
+ * <ui-resizable-panel default-size="50" min-size="20"><div class="flex h-full items-center justify-center p-6">Two</div></ui-resizable-panel>
39
+ * </ui-resizable-panel-group>
40
+ * ```
41
+ */
42
+ import { WebComponent, html, prop } from '@webjsdev/core';
43
+ import { cn, takeAuthoredClass } from '../lib/utils.ts';
44
+
45
+ /** The group's classes (the element applies them). */
46
+ export const resizablePanelGroupClass = (): string =>
47
+ 'cn-resizable-panel-group flex h-full w-full aria-[orientation=vertical]:flex-col';
48
+ /** A handle's classes (the element puts them on the handle itself). */
49
+ export const resizableHandleClass = (): string =>
50
+ 'cn-resizable-handle relative flex w-px items-center justify-center bg-border ring-offset-background after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-hidden aria-[orientation=horizontal]:h-px aria-[orientation=horizontal]:w-full aria-[orientation=horizontal]:after:left-0 aria-[orientation=horizontal]:after:h-1 aria-[orientation=horizontal]:after:w-full aria-[orientation=horizontal]:after:translate-x-0 aria-[orientation=horizontal]:after:-translate-y-1/2 [&[aria-orientation=horizontal]>div]:rotate-90';
51
+ /** A handle's grip. */
52
+ export const resizableHandleIconClass = (): string => 'cn-resizable-handle-icon z-10 flex shrink-0';
53
+
54
+ const GROUP = 'ui-resizable-panel-group';
55
+ const STEP = 10;
56
+ let uid = 0;
57
+
58
+ function groupOf(el: Element): UiResizablePanelGroup | null {
59
+ return (typeof el.closest === 'function' ? el.closest(GROUP) : null) as UiResizablePanelGroup | null;
60
+ }
61
+
62
+ function num(v: string | null | undefined, fallback: number): number {
63
+ const n = Number(v);
64
+ return v !== null && v !== undefined && v !== '' && Number.isFinite(n) ? n : fallback;
65
+ }
66
+
67
+ // --------------------------------------------------------------------------
68
+ // <ui-resizable-panel-group>
69
+ // --------------------------------------------------------------------------
70
+
71
+ export class UiResizablePanelGroup extends WebComponent({
72
+ orientation: prop<'horizontal' | 'vertical'>(String, { reflect: true }),
73
+ }) {
74
+ // The current sizes, in percent, panel by panel; empty until first laid out.
75
+ sizes: number[] = [];
76
+ _authored: string | null = null;
77
+
78
+ constructor() {
79
+ super();
80
+ this.orientation = 'horizontal';
81
+ }
82
+
83
+ // shadcn's className on ResizablePanelGroup lands on the group box, which
84
+ // is the flex item of whatever holds it (a `max-w-sm` on the group, the
85
+ // `h-full` that lets a nested group fill its panel). So the class written
86
+ // on this host moves to the box it renders, read once at first render, and
87
+ // the host becomes `display: contents`, leaving the box to size itself
88
+ // against the host's parent as shadcn's does. The host's box is turned off
89
+ // through its style rather than a class: the server serves the class the
90
+ // tag was written with, but it does serve a style the element adds, so the
91
+ // first paint already has one box, not two.
92
+ render() {
93
+ this._authored = takeAuthoredClass(this, null);
94
+ if (!this.getAttribute?.('style')) this.setAttribute?.('style', 'display: contents');
95
+ return html`<div
96
+ data-slot="resizable-panel-group"
97
+ data-panel-group-direction=${this.orientation}
98
+ aria-orientation=${this.orientation}
99
+ class=${cn(resizablePanelGroupClass(), this._authored)}
100
+ ><slot></slot></div>`;
101
+ }
102
+
103
+ /** The panels in this group, in order. */
104
+ panels(): UiResizablePanel[] {
105
+ if (typeof this.querySelectorAll !== 'function') return [];
106
+ return Array.from(this.querySelectorAll<UiResizablePanel>('ui-resizable-panel')).filter((p) => groupOf(p) === this);
107
+ }
108
+
109
+ /** The handles in this group, in order. */
110
+ handles(): UiResizableHandle[] {
111
+ if (typeof this.querySelectorAll !== 'function') return [];
112
+ return Array.from(this.querySelectorAll<UiResizableHandle>('ui-resizable-handle')).filter((h) => groupOf(h) === this);
113
+ }
114
+
115
+ /** The default layout: sized panels keep their size, the rest share what is left. */
116
+ initialSizes(panels = this.panels()): number[] {
117
+ const given = panels.map((p) => num(p.getAttribute?.('default-size'), NaN));
118
+ const used = given.filter((n) => !Number.isNaN(n)).reduce((a, b) => a + b, 0);
119
+ const free = given.filter((n) => Number.isNaN(n)).length;
120
+ const share = free ? Math.max(0, 100 - used) / free : 0;
121
+ return given.map((n) => (Number.isNaN(n) ? share : n));
122
+ }
123
+
124
+ /** The size a panel is drawn at: its live size once laid out, else its default. */
125
+ sizeOf(panel: UiResizablePanel): number {
126
+ const panels = this.panels();
127
+ const i = panels.indexOf(panel);
128
+ // The server cannot list the panels, so there a panel draws at its own
129
+ // default size: give every panel one for an exact first paint.
130
+ if (i < 0) return num(panel.getAttribute?.('default-size'), 50);
131
+ return (this.sizes.length === panels.length ? this.sizes : this.initialSizes(panels))[i];
132
+ }
133
+
134
+ /**
135
+ * Move the boundary after panel `i` by `delta` points, keeping both panels
136
+ * within their limits. Returns whether anything moved.
137
+ */
138
+ resize(i: number, delta: number): boolean {
139
+ const panels = this.panels();
140
+ if (i < 0 || i >= panels.length - 1) return false;
141
+ if (this.sizes.length !== panels.length) this.sizes = this.initialSizes(panels);
142
+ const a = panels[i];
143
+ const b = panels[i + 1];
144
+ const sa = this.sizes[i];
145
+ const sb = this.sizes[i + 1];
146
+ // The move lies between the most either panel can give and take.
147
+ const lo = Math.max(a.min - sa, sb - b.max);
148
+ const hi = Math.min(a.max - sa, sb - b.min);
149
+ const d = Math.min(Math.max(delta, lo), hi);
150
+ if (!Number.isFinite(d) || Math.abs(d) < 1e-9) return false;
151
+ const next = [...this.sizes];
152
+ next[i] = Number((sa + d).toFixed(4));
153
+ next[i + 1] = Number((sb - d).toFixed(4));
154
+ this.sizes = next;
155
+ this._apply();
156
+ this.dispatchEvent(new CustomEvent('ui-layout-change', { bubbles: true, detail: { sizes: [...next] } }));
157
+ return true;
158
+ }
159
+
160
+ // Redraw every panel and handle at the current sizes.
161
+ _apply(): void {
162
+ for (const p of this.panels()) p.requestUpdate?.();
163
+ for (const h of this.handles()) h.requestUpdate?.();
164
+ }
165
+
166
+ _rtl(): boolean {
167
+ return typeof getComputedStyle === 'function' && getComputedStyle(this).direction === 'rtl';
168
+ }
169
+
170
+ /** The group's length along its axis, in pixels. */
171
+ extent(): number {
172
+ const box = this.querySelector?.<HTMLElement>('[data-slot="resizable-panel-group"]');
173
+ const r = box?.getBoundingClientRect();
174
+ if (!r) return 0;
175
+ return this.orientation === 'vertical' ? r.height : r.width;
176
+ }
177
+ }
178
+ UiResizablePanelGroup.register('ui-resizable-panel-group');
179
+
180
+ // --------------------------------------------------------------------------
181
+ // <ui-resizable-panel>
182
+ // --------------------------------------------------------------------------
183
+
184
+ export class UiResizablePanel extends WebComponent {
185
+ _id = '';
186
+
187
+ connectedCallback(): void {
188
+ super.connectedCallback?.();
189
+ this._id ||= `ui-resizable-panel-${++uid}`;
190
+ }
191
+
192
+ get min(): number {
193
+ return num(this.getAttribute?.('min-size'), 0);
194
+ }
195
+
196
+ get max(): number {
197
+ return num(this.getAttribute?.('max-size'), 100);
198
+ }
199
+
200
+ // A panel is the flex child itself, so it carries its own share.
201
+ render() {
202
+ const size = groupOf(this)?.sizeOf(this) ?? 100;
203
+ if (typeof this.setAttribute === 'function') {
204
+ if (this._id) this.setAttribute('id', this._id);
205
+ this.setAttribute('data-slot', 'resizable-panel');
206
+ this.setAttribute('data-panel-size', String(Number(size.toFixed(1))));
207
+ this.setAttribute('style', `flex: ${size} 1 0px; overflow: hidden;`);
208
+ }
209
+ return html`<slot></slot>`;
210
+ }
211
+ }
212
+ UiResizablePanel.register('ui-resizable-panel');
213
+
214
+ // --------------------------------------------------------------------------
215
+ // <ui-resizable-handle>
216
+ // --------------------------------------------------------------------------
217
+
218
+ export class UiResizableHandle extends WebComponent({
219
+ withHandle: prop(Boolean, { attribute: 'with-handle' }),
220
+ }) {
221
+ _authored: string | null = null;
222
+ _drag: { at: number; extent: number } | null = null;
223
+
224
+ constructor() {
225
+ super();
226
+ this.withHandle = false;
227
+ }
228
+
229
+ connectedCallback(): void {
230
+ super.connectedCallback?.();
231
+ this.addEventListener('keydown', this._onKeyDown);
232
+ this.addEventListener('pointerdown', this._onPointerDown);
233
+ this.addEventListener('pointermove', this._onPointerMove);
234
+ this.addEventListener('pointerup', this._onPointerUp);
235
+ this.addEventListener('pointercancel', this._onPointerUp);
236
+ }
237
+
238
+ disconnectedCallback(): void {
239
+ this.removeEventListener('keydown', this._onKeyDown);
240
+ this.removeEventListener('pointerdown', this._onPointerDown);
241
+ this.removeEventListener('pointermove', this._onPointerMove);
242
+ this.removeEventListener('pointerup', this._onPointerUp);
243
+ this.removeEventListener('pointercancel', this._onPointerUp);
244
+ super.disconnectedCallback?.();
245
+ }
246
+
247
+ // The panel before this handle, whose size the handle reports.
248
+ _index(): number {
249
+ const group = groupOf(this);
250
+ if (!group) return -1;
251
+ const panels = group.panels();
252
+ let before = -1;
253
+ for (let i = 0; i < panels.length; i++) {
254
+ if (panels[i].compareDocumentPosition?.(this) & 4) before = i;
255
+ }
256
+ return before;
257
+ }
258
+
259
+ // The handle is the separator itself: a flex child that takes focus.
260
+ render() {
261
+ this._authored = takeAuthoredClass(this);
262
+ const group = groupOf(this);
263
+ const vertical = group?.orientation === 'vertical';
264
+ const i = typeof this.compareDocumentPosition === 'function' ? this._index() : -1;
265
+ const panel = i >= 0 ? group?.panels()[i] : null;
266
+ if (typeof this.setAttribute === 'function') {
267
+ this.setAttribute('class', cn(resizableHandleClass(), this._authored));
268
+ this.setAttribute('data-slot', 'resizable-handle');
269
+ this.setAttribute('role', 'separator');
270
+ this.setAttribute('tabindex', '0');
271
+ // A row of panels has upright separators, and a column flat ones.
272
+ this.setAttribute('aria-orientation', vertical ? 'horizontal' : 'vertical');
273
+ if (panel && group) {
274
+ this.setAttribute('aria-controls', panel.id);
275
+ this.setAttribute('aria-valuenow', String(Math.round(group.sizeOf(panel))));
276
+ this.setAttribute('aria-valuemin', String(panel.min));
277
+ this.setAttribute('aria-valuemax', String(panel.max));
278
+ }
279
+ }
280
+ return this.withHandle
281
+ ? html`<div class=${resizableHandleIconClass()}><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" class="size-2.5"><circle cx="9" cy="12" r="1"></circle><circle cx="9" cy="5" r="1"></circle><circle cx="9" cy="19" r="1"></circle><circle cx="15" cy="12" r="1"></circle><circle cx="15" cy="5" r="1"></circle><circle cx="15" cy="19" r="1"></circle></svg></div>`
282
+ : html``;
283
+ }
284
+
285
+ _onKeyDown = (e: KeyboardEvent): void => {
286
+ const group = groupOf(this);
287
+ if (!group) return;
288
+ const i = this._index();
289
+ const vertical = group.orientation === 'vertical';
290
+ const flip = !vertical && group._rtl() ? -1 : 1;
291
+ let delta: number | null = null;
292
+ if (!vertical && e.key === 'ArrowLeft') delta = -STEP * flip;
293
+ else if (!vertical && e.key === 'ArrowRight') delta = STEP * flip;
294
+ else if (vertical && e.key === 'ArrowUp') delta = -STEP;
295
+ else if (vertical && e.key === 'ArrowDown') delta = STEP;
296
+ else if (e.key === 'Home') delta = -100;
297
+ else if (e.key === 'End') delta = 100;
298
+ if (delta === null) return;
299
+ e.preventDefault();
300
+ group.resize(i, delta);
301
+ };
302
+
303
+ _onPointerDown = (e: PointerEvent): void => {
304
+ const group = groupOf(this);
305
+ if (!group || e.button !== 0) return;
306
+ e.preventDefault();
307
+ this.focus();
308
+ const vertical = group.orientation === 'vertical';
309
+ this._drag = { at: vertical ? e.clientY : e.clientX, extent: group.extent() };
310
+ try { this.setPointerCapture(e.pointerId); } catch { /* a pointer the engine does not track */ }
311
+ this.setAttribute('data-resize-handle-state', 'drag');
312
+ };
313
+
314
+ _onPointerMove = (e: PointerEvent): void => {
315
+ const group = groupOf(this);
316
+ if (!this._drag || !group || !this._drag.extent) return;
317
+ const vertical = group.orientation === 'vertical';
318
+ const now = vertical ? e.clientY : e.clientX;
319
+ const px = (now - this._drag.at) * (!vertical && group._rtl() ? -1 : 1);
320
+ if (group.resize(this._index(), (px / this._drag.extent) * 100)) this._drag.at = now;
321
+ };
322
+
323
+ _onPointerUp = (e: PointerEvent): void => {
324
+ if (!this._drag) return;
325
+ this._drag = null;
326
+ try { this.releasePointerCapture(e.pointerId); } catch { /* already released */ }
327
+ this.removeAttribute('data-resize-handle-state');
328
+ };
329
+ }
330
+ UiResizableHandle.register('ui-resizable-handle');
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Scroll area: a region that scrolls inside a fixed size, with a thin,
3
+ * theme-coloured scrollbar. Tier-1 class helper on native overflow; no
4
+ * script, no custom scrollbar element.
5
+ *
6
+ * shadcn parity:
7
+ * ScrollArea (+ its viewport) → scrollAreaClass({ orientation })
8
+ * ScrollBar → the native scrollbar, styled through
9
+ * scrollbar-width and scrollbar-color
10
+ *
11
+ * shadcn draws its own scrollbar with Radix. The platform's scrollbar is
12
+ * styled instead here, which keeps native scrolling, momentum, keyboard
13
+ * scrolling and the browser's own overlay behaviour intact. Give the element
14
+ * a size (`h-72`, `max-h-96`, `w-96`) so it has something to scroll inside.
15
+ *
16
+ * A11y (required for accessible output): a region that scrolls must be
17
+ * reachable by keyboard, so give it `tabindex="0"`, and because a focusable
18
+ * region needs a name, add `role="region"` with an `aria-label` that says what
19
+ * scrolls ("Release notes"). The focus ring is part of the class.
20
+ *
21
+ * Design tokens used: --border, --ring.
22
+ *
23
+ * @example
24
+ * ```html
25
+ * <div class=${cn(scrollAreaClass(), 'h-72 w-48 rounded-md border')} tabindex="0" role="region" aria-label="Tags">
26
+ * <ul class="p-4">${tags.map((t) => html`<li>${t}</li>`)}</ul>
27
+ * </div>
28
+ * ```
29
+ */
30
+ import { cn } from '../lib/utils.ts';
31
+
32
+ const BASE =
33
+ 'cn-scroll-area relative rounded-[inherit] [scrollbar-width:thin] [scrollbar-color:var(--color-border)_transparent] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50';
34
+
35
+ const ORIENTATIONS = {
36
+ vertical: 'overflow-y-auto overflow-x-hidden',
37
+ horizontal: 'overflow-x-auto overflow-y-hidden',
38
+ both: 'overflow-auto',
39
+ } as const;
40
+
41
+ export type ScrollAreaOrientation = keyof typeof ORIENTATIONS;
42
+
43
+ /** The scrolling region. `orientation` picks the axis (default vertical). */
44
+ export function scrollAreaClass(opts: { orientation?: ScrollAreaOrientation } = {}): string {
45
+ return cn(BASE, ORIENTATIONS[opts.orientation ?? 'vertical']);
46
+ }