@webjsdev/ui 0.3.17 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (360) hide show
  1. package/README.md +67 -8
  2. package/THIRD_PARTY_NOTICES.md +349 -0
  3. package/package.json +4 -2
  4. package/packages/registry/blocks/_shared/placeholder.svg +1 -0
  5. package/packages/registry/blocks/charts/chart-area-axes.ts +72 -0
  6. package/packages/registry/blocks/charts/chart-area-default.ts +64 -0
  7. package/packages/registry/blocks/charts/chart-area-gradient.ts +82 -0
  8. package/packages/registry/blocks/charts/chart-area-icons.ts +77 -0
  9. package/packages/registry/blocks/charts/chart-area-interactive.ts +204 -0
  10. package/packages/registry/blocks/charts/chart-area-legend.ts +72 -0
  11. package/packages/registry/blocks/charts/chart-area-linear.ts +64 -0
  12. package/packages/registry/blocks/charts/chart-area-stacked-expand.ts +77 -0
  13. package/packages/registry/blocks/charts/chart-area-stacked.ts +71 -0
  14. package/packages/registry/blocks/charts/chart-area-step.ts +68 -0
  15. package/packages/registry/blocks/charts/chart-bar-active.ts +93 -0
  16. package/packages/registry/blocks/charts/chart-bar-default.ts +60 -0
  17. package/packages/registry/blocks/charts/chart-bar-horizontal.ts +62 -0
  18. package/packages/registry/blocks/charts/chart-bar-interactive.ts +185 -0
  19. package/packages/registry/blocks/charts/chart-bar-label-custom.ts +78 -0
  20. package/packages/registry/blocks/charts/chart-bar-label.ts +66 -0
  21. package/packages/registry/blocks/charts/chart-bar-mixed.ts +87 -0
  22. package/packages/registry/blocks/charts/chart-bar-multiple.ts +67 -0
  23. package/packages/registry/blocks/charts/chart-bar-negative.ts +61 -0
  24. package/packages/registry/blocks/charts/chart-bar-stacked.ts +68 -0
  25. package/packages/registry/blocks/charts/chart-line-default.ts +61 -0
  26. package/packages/registry/blocks/charts/chart-line-dots-colors.ts +86 -0
  27. package/packages/registry/blocks/charts/chart-line-dots-custom.ts +75 -0
  28. package/packages/registry/blocks/charts/chart-line-dots.ts +65 -0
  29. package/packages/registry/blocks/charts/chart-line-interactive.ts +185 -0
  30. package/packages/registry/blocks/charts/chart-line-label-custom.ts +94 -0
  31. package/packages/registry/blocks/charts/chart-line-label.ts +73 -0
  32. package/packages/registry/blocks/charts/chart-line-linear.ts +61 -0
  33. package/packages/registry/blocks/charts/chart-line-multiple.ts +71 -0
  34. package/packages/registry/blocks/charts/chart-line-step.ts +61 -0
  35. package/packages/registry/blocks/charts/chart-pie-donut-active.ts +86 -0
  36. package/packages/registry/blocks/charts/chart-pie-donut-text.ts +89 -0
  37. package/packages/registry/blocks/charts/chart-pie-donut.ts +77 -0
  38. package/packages/registry/blocks/charts/chart-pie-interactive.ts +120 -0
  39. package/packages/registry/blocks/charts/chart-pie-label-custom.ts +82 -0
  40. package/packages/registry/blocks/charts/chart-pie-label-list.ts +86 -0
  41. package/packages/registry/blocks/charts/chart-pie-label.ts +77 -0
  42. package/packages/registry/blocks/charts/chart-pie-legend.ts +79 -0
  43. package/packages/registry/blocks/charts/chart-pie-separator-none.ts +77 -0
  44. package/packages/registry/blocks/charts/chart-pie-simple.ts +77 -0
  45. package/packages/registry/blocks/charts/chart-pie-stacked.ts +99 -0
  46. package/packages/registry/blocks/charts/chart-radar-default.ts +61 -0
  47. package/packages/registry/blocks/charts/chart-radar-dots.ts +61 -0
  48. package/packages/registry/blocks/charts/chart-radar-grid-circle-fill.ts +61 -0
  49. package/packages/registry/blocks/charts/chart-radar-grid-circle-no-lines.ts +61 -0
  50. package/packages/registry/blocks/charts/chart-radar-grid-circle.ts +61 -0
  51. package/packages/registry/blocks/charts/chart-radar-grid-custom.ts +61 -0
  52. package/packages/registry/blocks/charts/chart-radar-grid-fill.ts +61 -0
  53. package/packages/registry/blocks/charts/chart-radar-grid-none.ts +60 -0
  54. package/packages/registry/blocks/charts/chart-radar-icons.ts +76 -0
  55. package/packages/registry/blocks/charts/chart-radar-label-custom.ts +77 -0
  56. package/packages/registry/blocks/charts/chart-radar-legend.ts +70 -0
  57. package/packages/registry/blocks/charts/chart-radar-lines-only.ts +68 -0
  58. package/packages/registry/blocks/charts/chart-radar-multiple.ts +68 -0
  59. package/packages/registry/blocks/charts/chart-radar-radius.ts +68 -0
  60. package/packages/registry/blocks/charts/chart-radial-grid.ts +80 -0
  61. package/packages/registry/blocks/charts/chart-radial-label.ts +85 -0
  62. package/packages/registry/blocks/charts/chart-radial-shape.ts +81 -0
  63. package/packages/registry/blocks/charts/chart-radial-simple.ts +79 -0
  64. package/packages/registry/blocks/charts/chart-radial-stacked.ts +69 -0
  65. package/packages/registry/blocks/charts/chart-radial-text.ts +82 -0
  66. package/packages/registry/blocks/charts/chart-tooltip-advanced.ts +84 -0
  67. package/packages/registry/blocks/charts/chart-tooltip-default.ts +62 -0
  68. package/packages/registry/blocks/charts/chart-tooltip-formatter.ts +75 -0
  69. package/packages/registry/blocks/charts/chart-tooltip-icons.ts +68 -0
  70. package/packages/registry/blocks/charts/chart-tooltip-indicator-line.ts +62 -0
  71. package/packages/registry/blocks/charts/chart-tooltip-indicator-none.ts +62 -0
  72. package/packages/registry/blocks/charts/chart-tooltip-label-custom.ts +65 -0
  73. package/packages/registry/blocks/charts/chart-tooltip-label-formatter.ts +66 -0
  74. package/packages/registry/blocks/charts/chart-tooltip-label-none.ts +62 -0
  75. package/packages/registry/blocks/dashboard-01/components/app-sidebar.ts +108 -0
  76. package/packages/registry/blocks/dashboard-01/components/chart-area-interactive.ts +276 -0
  77. package/packages/registry/blocks/dashboard-01/components/dashboard-data.ts +89 -0
  78. package/packages/registry/blocks/dashboard-01/components/data-table.ts +644 -0
  79. package/packages/registry/blocks/dashboard-01/components/nav-documents.ts +65 -0
  80. package/packages/registry/blocks/dashboard-01/components/nav-main.ts +61 -0
  81. package/packages/registry/blocks/dashboard-01/components/nav-secondary.ts +40 -0
  82. package/packages/registry/blocks/dashboard-01/components/nav-user.ts +66 -0
  83. package/packages/registry/blocks/dashboard-01/components/section-cards.ts +59 -0
  84. package/packages/registry/blocks/dashboard-01/components/site-header.ts +52 -0
  85. package/packages/registry/blocks/dashboard-01/page.ts +39 -0
  86. package/packages/registry/blocks/login-01/components/login-form.ts +70 -0
  87. package/packages/registry/blocks/login-01/page.ts +19 -0
  88. package/packages/registry/blocks/login-02/components/login-form.ts +68 -0
  89. package/packages/registry/blocks/login-02/page.ts +36 -0
  90. package/packages/registry/blocks/login-03/components/login-form.ts +89 -0
  91. package/packages/registry/blocks/login-03/page.ts +28 -0
  92. package/packages/registry/blocks/login-04/components/login-form.ts +91 -0
  93. package/packages/registry/blocks/login-04/page.ts +20 -0
  94. package/packages/registry/blocks/login-05/components/login-form.ts +75 -0
  95. package/packages/registry/blocks/login-05/page.ts +19 -0
  96. package/packages/registry/blocks/preview/cards/activate-agent-dialog.ts +77 -0
  97. package/packages/registry/blocks/preview/cards/analytics-card.ts +64 -0
  98. package/packages/registry/blocks/preview/cards/anomaly-alert.ts +35 -0
  99. package/packages/registry/blocks/preview/cards/bar-chart-card.ts +91 -0
  100. package/packages/registry/blocks/preview/cards/book-appointment.ts +51 -0
  101. package/packages/registry/blocks/preview/cards/codespaces-card.ts +172 -0
  102. package/packages/registry/blocks/preview/cards/contributions-activity.ts +63 -0
  103. package/packages/registry/blocks/preview/cards/contributors.ts +51 -0
  104. package/packages/registry/blocks/preview/cards/environment-variables.ts +47 -0
  105. package/packages/registry/blocks/preview/cards/feedback-form.ts +61 -0
  106. package/packages/registry/blocks/preview/cards/file-upload.ts +51 -0
  107. package/packages/registry/blocks/preview/cards/github-profile.ts +66 -0
  108. package/packages/registry/blocks/preview/cards/icon-preview-grid.ts +47 -0
  109. package/packages/registry/blocks/preview/cards/invite-team.ts +78 -0
  110. package/packages/registry/blocks/preview/cards/invoice.ts +91 -0
  111. package/packages/registry/blocks/preview/cards/live-waveform.ts +330 -0
  112. package/packages/registry/blocks/preview/cards/no-team-members.ts +61 -0
  113. package/packages/registry/blocks/preview/cards/not-found.ts +46 -0
  114. package/packages/registry/blocks/preview/cards/observability-card.ts +44 -0
  115. package/packages/registry/blocks/preview/cards/pie-chart-card.ts +84 -0
  116. package/packages/registry/blocks/preview/cards/report-bug.ts +71 -0
  117. package/packages/registry/blocks/preview/cards/shipping-address.ts +79 -0
  118. package/packages/registry/blocks/preview/cards/shortcuts.ts +57 -0
  119. package/packages/registry/blocks/preview/cards/skeleton-loading.ts +37 -0
  120. package/packages/registry/blocks/preview/cards/sleep-report.ts +85 -0
  121. package/packages/registry/blocks/preview/cards/style-overview.ts +64 -0
  122. package/packages/registry/blocks/preview/cards/typography-specimen.ts +107 -0
  123. package/packages/registry/blocks/preview/cards/ui-elements.ts +164 -0
  124. package/packages/registry/blocks/preview/cards/usage-card.ts +63 -0
  125. package/packages/registry/blocks/preview/cards/visitors.ts +71 -0
  126. package/packages/registry/blocks/preview/cards/weekly-fitness-summary.ts +54 -0
  127. package/packages/registry/blocks/preview/page.ts +103 -0
  128. package/packages/registry/blocks/preview-02/cards/account-access.ts +70 -0
  129. package/packages/registry/blocks/preview-02/cards/card-overview.ts +75 -0
  130. package/packages/registry/blocks/preview-02/cards/claimable-balance.ts +54 -0
  131. package/packages/registry/blocks/preview-02/cards/contribution-history.ts +80 -0
  132. package/packages/registry/blocks/preview-02/cards/cover-art.ts +41 -0
  133. package/packages/registry/blocks/preview-02/cards/dividend-income.ts +76 -0
  134. package/packages/registry/blocks/preview-02/cards/empty-connect-bank.ts +38 -0
  135. package/packages/registry/blocks/preview-02/cards/empty-distribute-track.ts +38 -0
  136. package/packages/registry/blocks/preview-02/cards/empty-explore-catalog.ts +39 -0
  137. package/packages/registry/blocks/preview-02/cards/faq.ts +79 -0
  138. package/packages/registry/blocks/preview-02/cards/front-door.ts +40 -0
  139. package/packages/registry/blocks/preview-02/cards/index-investing.ts +31 -0
  140. package/packages/registry/blocks/preview-02/cards/kitchen-island.ts +90 -0
  141. package/packages/registry/blocks/preview-02/cards/loading-card.ts +34 -0
  142. package/packages/registry/blocks/preview-02/cards/new-milestone.ts +53 -0
  143. package/packages/registry/blocks/preview-02/cards/notification-settings.ts +126 -0
  144. package/packages/registry/blocks/preview-02/cards/payments.ts +88 -0
  145. package/packages/registry/blocks/preview-02/cards/payout-threshold.ts +92 -0
  146. package/packages/registry/blocks/preview-02/cards/power-usage.ts +84 -0
  147. package/packages/registry/blocks/preview-02/cards/preferences.ts +89 -0
  148. package/packages/registry/blocks/preview-02/cards/qr-connect.ts +54 -0
  149. package/packages/registry/blocks/preview-02/cards/receiving-method.ts +89 -0
  150. package/packages/registry/blocks/preview-02/cards/recent-transactions.ts +101 -0
  151. package/packages/registry/blocks/preview-02/cards/release-catalog.ts +73 -0
  152. package/packages/registry/blocks/preview-02/cards/roller-shades.ts +110 -0
  153. package/packages/registry/blocks/preview-02/cards/savings-progress.ts +68 -0
  154. package/packages/registry/blocks/preview-02/cards/savings-targets.ts +132 -0
  155. package/packages/registry/blocks/preview-02/cards/sidebar-nav.ts +88 -0
  156. package/packages/registry/blocks/preview-02/cards/social-links.ts +57 -0
  157. package/packages/registry/blocks/preview-02/cards/stock-performance.ts +106 -0
  158. package/packages/registry/blocks/preview-02/cards/syncing-state.ts +37 -0
  159. package/packages/registry/blocks/preview-02/cards/transfer-funds.ts +111 -0
  160. package/packages/registry/blocks/preview-02/cards/upcoming-payments.ts +69 -0
  161. package/packages/registry/blocks/preview-02/page.ts +111 -0
  162. package/packages/registry/blocks/preview-03/cards/files-chat.ts +75 -0
  163. package/packages/registry/blocks/preview-03/cards/group-chat.ts +114 -0
  164. package/packages/registry/blocks/preview-03/cards/reasoning-chat.ts +88 -0
  165. package/packages/registry/blocks/preview-03/cards/simple-chat.ts +53 -0
  166. package/packages/registry/blocks/preview-03/components/chat-card.ts +126 -0
  167. package/packages/registry/blocks/preview-03/components/chat-player.ts +174 -0
  168. package/packages/registry/blocks/preview-03/components/part-file.ts +77 -0
  169. package/packages/registry/blocks/preview-03/components/part-reasoning.ts +25 -0
  170. package/packages/registry/blocks/preview-03/components/part-source.ts +48 -0
  171. package/packages/registry/blocks/preview-03/components/part-text.ts +69 -0
  172. package/packages/registry/blocks/preview-03/components/part-tool.ts +71 -0
  173. package/packages/registry/blocks/preview-03/components/prompt-input.ts +86 -0
  174. package/packages/registry/blocks/preview-03/page.ts +39 -0
  175. package/packages/registry/blocks/sidebar-01/components/app-sidebar.ts +113 -0
  176. package/packages/registry/blocks/sidebar-01/components/search-form.ts +33 -0
  177. package/packages/registry/blocks/sidebar-01/components/version-switcher.ts +50 -0
  178. package/packages/registry/blocks/sidebar-01/page.ts +58 -0
  179. package/packages/registry/blocks/sidebar-02/components/app-sidebar.ts +131 -0
  180. package/packages/registry/blocks/sidebar-02/components/search-form.ts +33 -0
  181. package/packages/registry/blocks/sidebar-02/components/version-switcher.ts +50 -0
  182. package/packages/registry/blocks/sidebar-02/page.ts +53 -0
  183. package/packages/registry/blocks/sidebar-03/components/app-sidebar.ts +134 -0
  184. package/packages/registry/blocks/sidebar-03/page.ts +60 -0
  185. package/packages/registry/blocks/sidebar-04/components/app-sidebar.ts +136 -0
  186. package/packages/registry/blocks/sidebar-04/page.ts +58 -0
  187. package/packages/registry/blocks/sidebar-05/components/app-sidebar.ts +147 -0
  188. package/packages/registry/blocks/sidebar-05/components/search-form.ts +33 -0
  189. package/packages/registry/blocks/sidebar-05/page.ts +58 -0
  190. package/packages/registry/blocks/sidebar-06/components/app-sidebar.ts +105 -0
  191. package/packages/registry/blocks/sidebar-06/components/nav-main.ts +56 -0
  192. package/packages/registry/blocks/sidebar-06/components/sidebar-opt-in-form.ts +44 -0
  193. package/packages/registry/blocks/sidebar-06/page.ts +57 -0
  194. package/packages/registry/blocks/sidebar-07/components/app-sidebar.ts +108 -0
  195. package/packages/registry/blocks/sidebar-07/components/nav-main.ts +61 -0
  196. package/packages/registry/blocks/sidebar-07/components/nav-projects.ts +65 -0
  197. package/packages/registry/blocks/sidebar-07/components/nav-user.ts +70 -0
  198. package/packages/registry/blocks/sidebar-07/components/team-switcher.ts +66 -0
  199. package/packages/registry/blocks/sidebar-07/page.ts +59 -0
  200. package/packages/registry/blocks/sidebar-08/components/app-sidebar.ts +122 -0
  201. package/packages/registry/blocks/sidebar-08/components/nav-main.ts +68 -0
  202. package/packages/registry/blocks/sidebar-08/components/nav-projects.ts +65 -0
  203. package/packages/registry/blocks/sidebar-08/components/nav-secondary.ts +40 -0
  204. package/packages/registry/blocks/sidebar-08/components/nav-user.ts +70 -0
  205. package/packages/registry/blocks/sidebar-08/page.ts +59 -0
  206. package/packages/registry/blocks/sidebar-09/components/app-sidebar.ts +213 -0
  207. package/packages/registry/blocks/sidebar-09/components/nav-user.ts +70 -0
  208. package/packages/registry/blocks/sidebar-09/page.ts +52 -0
  209. package/packages/registry/blocks/sidebar-10/components/app-sidebar.ts +125 -0
  210. package/packages/registry/blocks/sidebar-10/components/nav-actions.ts +84 -0
  211. package/packages/registry/blocks/sidebar-10/components/nav-favorites.ts +66 -0
  212. package/packages/registry/blocks/sidebar-10/components/nav-main.ts +37 -0
  213. package/packages/registry/blocks/sidebar-10/components/nav-secondary.ts +43 -0
  214. package/packages/registry/blocks/sidebar-10/components/nav-workspaces.ts +78 -0
  215. package/packages/registry/blocks/sidebar-10/components/team-switcher.ts +63 -0
  216. package/packages/registry/blocks/sidebar-10/page.ts +46 -0
  217. package/packages/registry/blocks/sidebar-11/components/app-sidebar.ts +114 -0
  218. package/packages/registry/blocks/sidebar-11/page.ts +63 -0
  219. package/packages/registry/blocks/sidebar-12/components/app-sidebar.ts +63 -0
  220. package/packages/registry/blocks/sidebar-12/components/calendars.ts +53 -0
  221. package/packages/registry/blocks/sidebar-12/components/date-picker.ts +26 -0
  222. package/packages/registry/blocks/sidebar-12/components/nav-user.ts +70 -0
  223. package/packages/registry/blocks/sidebar-12/page.ts +43 -0
  224. package/packages/registry/blocks/sidebar-13/components/settings-dialog.ts +114 -0
  225. package/packages/registry/blocks/sidebar-13/page.ts +21 -0
  226. package/packages/registry/blocks/sidebar-14/components/app-sidebar.ts +120 -0
  227. package/packages/registry/blocks/sidebar-14/page.ts +55 -0
  228. package/packages/registry/blocks/sidebar-15/components/calendars.ts +53 -0
  229. package/packages/registry/blocks/sidebar-15/components/date-picker.ts +26 -0
  230. package/packages/registry/blocks/sidebar-15/components/nav-favorites.ts +66 -0
  231. package/packages/registry/blocks/sidebar-15/components/nav-main.ts +35 -0
  232. package/packages/registry/blocks/sidebar-15/components/nav-secondary.ts +43 -0
  233. package/packages/registry/blocks/sidebar-15/components/nav-user.ts +70 -0
  234. package/packages/registry/blocks/sidebar-15/components/nav-workspaces.ts +75 -0
  235. package/packages/registry/blocks/sidebar-15/components/sidebar-left.ts +126 -0
  236. package/packages/registry/blocks/sidebar-15/components/sidebar-right.ts +62 -0
  237. package/packages/registry/blocks/sidebar-15/components/team-switcher.ts +63 -0
  238. package/packages/registry/blocks/sidebar-15/page.ts +47 -0
  239. package/packages/registry/blocks/sidebar-16/components/app-sidebar.ts +124 -0
  240. package/packages/registry/blocks/sidebar-16/components/nav-main.ts +67 -0
  241. package/packages/registry/blocks/sidebar-16/components/nav-projects.ts +65 -0
  242. package/packages/registry/blocks/sidebar-16/components/nav-secondary.ts +40 -0
  243. package/packages/registry/blocks/sidebar-16/components/nav-user.ts +70 -0
  244. package/packages/registry/blocks/sidebar-16/components/search-form.ts +27 -0
  245. package/packages/registry/blocks/sidebar-16/components/site-header.ts +42 -0
  246. package/packages/registry/blocks/sidebar-16/page.ts +38 -0
  247. package/packages/registry/blocks/signup-01/components/signup-form.ts +78 -0
  248. package/packages/registry/blocks/signup-01/page.ts +19 -0
  249. package/packages/registry/blocks/signup-02/components/signup-form.ts +78 -0
  250. package/packages/registry/blocks/signup-02/page.ts +36 -0
  251. package/packages/registry/blocks/signup-03/components/signup-form.ts +79 -0
  252. package/packages/registry/blocks/signup-03/page.ts +28 -0
  253. package/packages/registry/blocks/signup-04/components/signup-form.ts +100 -0
  254. package/packages/registry/blocks/signup-04/page.ts +20 -0
  255. package/packages/registry/blocks/signup-05/components/signup-form.ts +75 -0
  256. package/packages/registry/blocks/signup-05/page.ts +20 -0
  257. package/packages/registry/components/accordion.ts +20 -7
  258. package/packages/registry/components/alert-dialog.ts +58 -13
  259. package/packages/registry/components/alert.ts +11 -6
  260. package/packages/registry/components/attachment.ts +119 -0
  261. package/packages/registry/components/avatar.ts +17 -8
  262. package/packages/registry/components/badge.ts +16 -9
  263. package/packages/registry/components/breadcrumb.ts +6 -6
  264. package/packages/registry/components/bubble.ts +95 -0
  265. package/packages/registry/components/button-group.ts +73 -0
  266. package/packages/registry/components/button.ts +35 -25
  267. package/packages/registry/components/calendar.ts +566 -0
  268. package/packages/registry/components/card.ts +8 -8
  269. package/packages/registry/components/carousel.ts +352 -0
  270. package/packages/registry/components/chart-element.ts +547 -0
  271. package/packages/registry/components/chart-geometry.ts +457 -0
  272. package/packages/registry/components/chart.ts +932 -0
  273. package/packages/registry/components/checkbox.ts +22 -84
  274. package/packages/registry/components/code-block.ts +191 -0
  275. package/packages/registry/components/collapsible.ts +5 -2
  276. package/packages/registry/components/combobox.ts +802 -0
  277. package/packages/registry/components/command.ts +618 -0
  278. package/packages/registry/components/context-menu.ts +302 -0
  279. package/packages/registry/components/dialog.ts +156 -45
  280. package/packages/registry/components/direction.ts +43 -0
  281. package/packages/registry/components/drawer.ts +226 -0
  282. package/packages/registry/components/dropdown-menu.ts +262 -83
  283. package/packages/registry/components/empty.ts +8 -8
  284. package/packages/registry/components/field.ts +20 -18
  285. package/packages/registry/components/floating.ts +124 -0
  286. package/packages/registry/components/hover-card.ts +19 -8
  287. package/packages/registry/components/input-group.ts +118 -0
  288. package/packages/registry/components/input-otp.ts +365 -0
  289. package/packages/registry/components/input.ts +3 -3
  290. package/packages/registry/components/item.ts +134 -0
  291. package/packages/registry/components/kbd.ts +2 -2
  292. package/packages/registry/components/label.ts +1 -1
  293. package/packages/registry/components/marker.ts +63 -0
  294. package/packages/registry/components/menubar.ts +388 -0
  295. package/packages/registry/components/message-scroller.ts +470 -0
  296. package/packages/registry/components/message.ts +69 -0
  297. package/packages/registry/components/native-select.ts +5 -5
  298. package/packages/registry/components/navigation-menu.ts +564 -0
  299. package/packages/registry/components/pagination.ts +5 -5
  300. package/packages/registry/components/popover.ts +30 -84
  301. package/packages/registry/components/progress.ts +7 -3
  302. package/packages/registry/components/questionnaire.ts +840 -0
  303. package/packages/registry/components/radio-group.ts +18 -73
  304. package/packages/registry/components/resizable.ts +330 -0
  305. package/packages/registry/components/scroll-area.ts +46 -0
  306. package/packages/registry/components/select.ts +650 -0
  307. package/packages/registry/components/separator.ts +1 -1
  308. package/packages/registry/components/sheet.ts +128 -0
  309. package/packages/registry/components/sidebar.ts +457 -0
  310. package/packages/registry/components/skeleton.ts +1 -1
  311. package/packages/registry/components/slider.ts +333 -0
  312. package/packages/registry/components/sonner.ts +74 -7
  313. package/packages/registry/components/spinner.ts +7 -4
  314. package/packages/registry/components/switch.ts +117 -9
  315. package/packages/registry/components/table.ts +11 -9
  316. package/packages/registry/components/tabs.ts +76 -25
  317. package/packages/registry/components/textarea.ts +1 -1
  318. package/packages/registry/components/toggle-group.ts +30 -11
  319. package/packages/registry/components/toggle.ts +20 -13
  320. package/packages/registry/components/tooltip.ts +68 -7
  321. package/packages/registry/components/trace.ts +75 -0
  322. package/packages/registry/lib/dom.ts +3 -4
  323. package/packages/registry/lib/icons-hugeicons.ts +955 -0
  324. package/packages/registry/lib/icons-phosphor.ts +955 -0
  325. package/packages/registry/lib/icons-remixicon.ts +955 -0
  326. package/packages/registry/lib/icons-tabler.ts +955 -0
  327. package/packages/registry/lib/icons.ts +768 -0
  328. package/packages/registry/lib/utils.ts +52 -8
  329. package/packages/registry/registry.json +4056 -72
  330. package/packages/registry/styles/shadcn-tailwind.css +654 -0
  331. package/packages/registry/styles/style-luma.css +1987 -0
  332. package/packages/registry/styles/style-lyra.css +1965 -0
  333. package/packages/registry/styles/style-maia.css +1987 -0
  334. package/packages/registry/styles/style-mira.css +1992 -0
  335. package/packages/registry/styles/style-new-york.css +1597 -0
  336. package/packages/registry/styles/style-nova.css +1990 -0
  337. package/packages/registry/styles/style-rhea.css +1987 -0
  338. package/packages/registry/styles/style-sera.css +1977 -0
  339. package/packages/registry/styles/style-vega.css +1990 -0
  340. package/packages/registry/styles/supplement.json +54 -0
  341. package/packages/registry/styles/tw-animate.css +6 -0
  342. package/packages/registry/themes/base-colors.js +8 -2
  343. package/packages/registry/themes/fonts.js +120 -0
  344. package/packages/registry/themes/index.css +2 -0
  345. package/packages/registry/themes/items.js +61 -0
  346. package/packages/registry/themes/preset.js +302 -0
  347. package/packages/registry/themes/themes.js +1193 -0
  348. package/src/commands/add.js +266 -14
  349. package/src/commands/diff.js +34 -20
  350. package/src/commands/info.js +7 -0
  351. package/src/commands/init.js +127 -10
  352. package/src/commands/list.js +43 -11
  353. package/src/commands/view.js +33 -5
  354. package/src/lint/rules/no-restyle.js +1 -1
  355. package/src/registry/extract.js +194 -5
  356. package/src/registry/icons.js +31 -0
  357. package/src/registry/local.js +15 -1
  358. package/src/registry/schema.js +13 -0
  359. package/src/registry/style-bake.js +506 -0
  360. package/src/utils/theme.js +110 -21
@@ -5,7 +5,16 @@ import prompts from 'prompts';
5
5
  import { writeConfig, CONFIG_FILE } from '../utils/get-config.js';
6
6
  import { logger } from '../utils/logger.js';
7
7
  import { getRegistryItem, DEFAULT_REGISTRY_URL } from '../registry/fetcher.js';
8
- import { ensureTheme } from '../utils/theme.js';
8
+ import { ensureTheme, presetThemeBlock } from '../utils/theme.js';
9
+ import { STYLE_NAMES } from '../registry/style-bake.js';
10
+ import {
11
+ ICON_LIBRARIES,
12
+ decodePreset,
13
+ getIconLibrary,
14
+ isPresetCode,
15
+ presetFontUrls,
16
+ resolvePresetConfig,
17
+ } from '../../packages/registry/themes/preset.js';
9
18
 
10
19
  const BASE_COLORS = ['neutral', 'stone', 'zinc', 'mauve', 'olive', 'mist', 'taupe'];
11
20
 
@@ -50,11 +59,46 @@ export const init = new Command()
50
59
  .option('-y, --yes', 'skip confirmation prompts', false)
51
60
  .option('--base-color <color>', `base color (${BASE_COLORS.join('|')})`)
52
61
  .option('--css <path>', 'path to the project Tailwind CSS file')
53
- .option('-o, --overwrite', 'replace an existing alias map and existing helper files', false)
62
+ .option('-o, --overwrite', 'replace an existing alias map, existing helper files and the theme block', false)
63
+ .option('--preset <code>', 'apply a design-system preset code from webjs.dev/ui/create (style, colors, font, radius, icons)')
64
+ .option('--style <name>', `component style (${STYLE_NAMES.join('|')})`)
65
+ .option('--icons <library>', `icon library (${ICON_LIBRARIES.map((l) => l.name).join('|')})`)
54
66
  .option('--registry <url>', 'registry base URL', DEFAULT_REGISTRY_URL)
55
67
  .action(async (opts) => {
56
68
  const cwd = opts.cwd;
57
69
 
70
+ // A preset is the configurator's whole design system in one code (#1666).
71
+ // An explicit flag beside it wins over the field it names, so a code can
72
+ // be reused with one choice changed.
73
+ /** @type {import('../../packages/registry/themes/preset.js').PresetConfig | null} */
74
+ let preset = null;
75
+ if (opts.preset) {
76
+ const decoded = isPresetCode(opts.preset) ? decodePreset(opts.preset) : null;
77
+ if (!decoded) {
78
+ logger.error(`"${opts.preset}" is not a preset code. Copy one from ${logger.cyan('https://webjs.dev/ui/create')}.`);
79
+ process.exit(1);
80
+ }
81
+ const resolved = resolvePresetConfig({
82
+ ...decoded,
83
+ ...(opts.style ? { style: opts.style } : null),
84
+ ...(opts.icons ? { iconLibrary: opts.icons } : null),
85
+ ...(opts.baseColor ? { baseColor: opts.baseColor } : null),
86
+ });
87
+ if (resolved.error) {
88
+ logger.error(`Preset ${opts.preset}: ${resolved.error}.`);
89
+ process.exit(1);
90
+ }
91
+ preset = resolved.config;
92
+ }
93
+ if (opts.style && !STYLE_NAMES.includes(opts.style)) {
94
+ logger.error(`Unknown style "${opts.style}". Use one of: ${STYLE_NAMES.join(', ')}.`);
95
+ process.exit(1);
96
+ }
97
+ if (opts.icons && !getIconLibrary(opts.icons)) {
98
+ logger.error(`Unknown icon library "${opts.icons}". Use one of: ${ICON_LIBRARIES.map((l) => l.name).join(', ')}.`);
99
+ process.exit(1);
100
+ }
101
+
58
102
  // Re-running `init` on a project that already has one must not RELOCATE it.
59
103
  // The alias map decides where cn() lives and what every already-added
60
104
  // component imports, and `tailwind.css` decides which stylesheet the app
@@ -97,7 +141,7 @@ export const init = new Command()
97
141
 
98
142
  /** @type {{ baseColor: string, css: string }} */
99
143
  let answers = {
100
- baseColor: opts.baseColor || initialBaseColor,
144
+ baseColor: (preset && preset.baseColor) || opts.baseColor || initialBaseColor,
101
145
  css: opts.css || initialCss,
102
146
  };
103
147
 
@@ -105,7 +149,7 @@ export const init = new Command()
105
149
  const r = await prompts(
106
150
  [
107
151
  {
108
- type: opts.baseColor ? null : 'select',
152
+ type: opts.baseColor || preset ? null : 'select',
109
153
  name: 'baseColor',
110
154
  message: 'Base color?',
111
155
  choices: BASE_COLORS.map((c) => ({ title: c, value: c })),
@@ -127,9 +171,12 @@ export const init = new Command()
127
171
  // unrecognised key through here would write a file that `getConfig` (and
128
172
  // therefore `add` / `diff` / `info`) throws on. Preserving a project's
129
173
  // settings means its VALUES, not arbitrary extra fields.
174
+ // A style or icon library the command names replaces the stored one,
175
+ // since naming it is the request; otherwise a re-run keeps what is there.
176
+ const iconLibrary = (preset && preset.iconLibrary) || opts.icons || (keep && existing.iconLibrary) || 'lucide';
130
177
  const config = {
131
178
  $schema: 'https://ui.webjs.dev/schema.json',
132
- style: (keep && existing.style) || 'default',
179
+ style: (preset && preset.style) || opts.style || (keep && existing.style) || 'default',
133
180
  tailwind: {
134
181
  css: answers.css,
135
182
  baseColor: answers.baseColor,
@@ -138,7 +185,7 @@ export const init = new Command()
138
185
  : true,
139
186
  },
140
187
  aliases,
141
- iconLibrary: (keep && existing.iconLibrary) || 'lucide',
188
+ iconLibrary,
142
189
  };
143
190
 
144
191
  writeConfig(cwd, config);
@@ -147,17 +194,49 @@ export const init = new Command()
147
194
  // Pull lib/utils + the chosen theme from the registry and write them in.
148
195
  await writeLibUtils(cwd, aliases.utils, opts.registry, opts.overwrite);
149
196
 
197
+ // The icon library is written only when the command names one, since it
198
+ // is a large file an app that draws no kit icons does not need.
199
+ if (preset || opts.icons) await writeIcons(cwd, aliases.utils, iconLibrary, opts.registry, opts.overwrite);
200
+
201
+ // A preset's tokens are its own palette over the kit's theme file.
202
+ let block;
203
+ if (preset) {
204
+ try {
205
+ const neutral = await getRegistryItem('theme-neutral', opts.registry);
206
+ block = presetThemeBlock(neutral.files[0].content || '', preset);
207
+ } catch (e) {
208
+ logger.error(`Could not build the theme for preset ${opts.preset}: ${e.message}`);
209
+ process.exit(1);
210
+ }
211
+ }
212
+
150
213
  // The theme tokens are what the class helpers render against. A silent
151
214
  // failure here (the old behaviour) left an unstyled install with a clean
152
215
  // exit code, the exact trap for an autonomous agent, so hard-fail (#983).
153
- const theme = await ensureTheme(cwd, answers.baseColor, answers.css, opts.registry);
216
+ // A preset, or --overwrite, replaces an existing block in place (#1666).
217
+ const theme = await ensureTheme(cwd, answers.baseColor, answers.css, opts.registry, {
218
+ replace: Boolean(preset || opts.overwrite),
219
+ block,
220
+ });
154
221
  if (theme.status === 'failed') {
155
222
  logger.error(`Could not write theme tokens into ${answers.css}: ${theme.error}`);
156
223
  logger.info('The class helpers render against these tokens, so this must succeed.');
157
224
  process.exit(1);
158
225
  }
159
226
  if (theme.status === 'written') logger.success(`Wrote theme into ${answers.css}`);
160
- else logger.info(`Theme already present in ${answers.css}: skipping.`);
227
+ else if (theme.status === 'replaced') logger.success(`Replaced the theme in ${answers.css}`);
228
+ else if (theme.status === 'legacy') {
229
+ logger.warn(`The theme block in ${answers.css} predates the end marker, so it was left as it is.`);
230
+ logger.info(`To replace it, delete the block (from ${logger.cyan('/* @webjsdev/ui theme */')} to the end of its rules) and re-run init.`);
231
+ } else logger.info(`Theme already present in ${answers.css}: skipping.`);
232
+
233
+ if (preset) {
234
+ const urls = presetFontUrls(preset);
235
+ if (urls.length) {
236
+ logger.info('The preset names its fonts in the theme. Load the faces, either self-hosted under public/ or from:');
237
+ for (const url of urls) logger.info(` ${url}`);
238
+ }
239
+ }
161
240
 
162
241
  logger.break();
163
242
  logger.success('Done.');
@@ -201,8 +280,8 @@ async function writeLibUtils(cwd, utilsAlias, registryUrl, overwrite) {
201
280
  }
202
281
 
203
282
  // The onBeforeCache() DOM helper lives in a SEPARATE module (#819) because
204
- // it references `document`, so keeping it out of cn()'s file prevents the
205
- // elision analyzer pinning every page that imports cn to the browser.
283
+ // it references `document`, so keeping it out of cn()'s file keeps cn()
284
+ // free of browser globals for the pages and layouts that import it.
206
285
  // Overlay components import it from `../lib/dom.ts`, so write it as a
207
286
  // sibling of the utils file, which lands it at lib/utils/dom.ts next to
208
287
  // cn.ts. `add` reads that same adjacency when it rewrites the import.
@@ -224,6 +303,44 @@ async function writeLibUtils(cwd, utilsAlias, registryUrl, overwrite) {
224
303
  }
225
304
  }
226
305
 
306
+ /**
307
+ * Write the chosen icon library as the utils file's sibling `icons.ts`, the
308
+ * path a block's icon import is rewritten to (#1666). Naming a library is a
309
+ * request to switch, so a file that is still one of the five libraries as
310
+ * shipped is replaced. A file the app has edited is kept unless `--overwrite`
311
+ * says otherwise, the same rule as the other helpers.
312
+ */
313
+ async function writeIcons(cwd, utilsAlias, library, registryUrl, overwrite) {
314
+ const lib = getIconLibrary(library);
315
+ if (!lib) return;
316
+ const target = join(dirname(join(cwd, utilsAlias.replace(/^@\//, '') + '.ts')), 'icons.ts');
317
+ const rel = relative(cwd, target);
318
+ try {
319
+ const item = await getRegistryItem(lib.item, registryUrl);
320
+ const content = item.files && item.files[0] ? item.files[0].content || '' : '';
321
+ if (!content) throw new Error(`${lib.item} has no content`);
322
+ if (existsSync(target) && !overwrite) {
323
+ const current = readFileSync(target, 'utf8');
324
+ if (current === content) {
325
+ logger.info(`${rel} is already ${lib.title}: keeping it.`);
326
+ return;
327
+ }
328
+ const pristine = await Promise.all(
329
+ ICON_LIBRARIES.map((l) => getRegistryItem(l.item, registryUrl).then((it) => it.files[0].content, () => null)),
330
+ );
331
+ if (!pristine.includes(current)) {
332
+ logger.warn(`${rel} has been edited, so it was kept. Re-run with --overwrite to replace it with ${lib.title}.`);
333
+ return;
334
+ }
335
+ }
336
+ ensureDir(dirname(target));
337
+ writeFileSync(target, content, 'utf8');
338
+ logger.success(`Wrote ${rel} (${lib.title})`);
339
+ } catch (e) {
340
+ logger.warn(`Could not fetch ${lib.item} from the registry (${e.message}).`);
341
+ }
342
+ }
343
+
227
344
  function relative(cwd, p) {
228
345
  return p.startsWith(cwd) ? p.slice(cwd.length + 1) : p;
229
346
  }
@@ -1,25 +1,57 @@
1
1
  import { Command } from 'commander';
2
2
  import { getRegistryIndex, DEFAULT_REGISTRY_URL } from '../registry/fetcher.js';
3
+ import { uiBlocks, BLOCK_DEFINITION } from '../registry/extract.js';
3
4
  import { logger } from '../utils/logger.js';
4
5
 
6
+ const TYPES = ['ui', 'block', 'chart', 'all'];
7
+
8
+ /** The three labelled groups `list` prints, in order. */
9
+ const GROUPS = [
10
+ ['ui', 'Components'],
11
+ ['block', `Blocks (${BLOCK_DEFINITION})`],
12
+ ['chart', 'Charts'],
13
+ ];
14
+
5
15
  export const list = new Command()
6
16
  .name('list')
7
17
  .alias('search')
8
- .description('List components available in the registry')
9
- .argument('[filter]', 'filter by substring')
18
+ .description('List the components, blocks and charts in the registry')
19
+ .argument('[filter]', 'filter by substring of the name')
20
+ .option('--type <type>', `ui, block, chart or all (${TYPES.join(' | ')})`, 'all')
21
+ .option('--category <name>', 'only blocks and charts in this category (e.g. login, sidebar, area)')
22
+ .option('--json', 'print one compact JSON array of { name, type, categories, description }')
10
23
  .option('--registry <url>', 'registry base URL', DEFAULT_REGISTRY_URL)
11
24
  .action(async (filter, opts) => {
12
- const items = await getRegistryIndex(opts.registry);
13
- const ui = items.filter((i) => i.type === 'registry:ui');
14
- const filtered = filter ? ui.filter((i) => i.name.includes(filter)) : ui;
15
- if (!filtered.length) {
25
+ if (!TYPES.includes(opts.type)) {
26
+ logger.error(`Unknown --type "${opts.type}". Use one of: ${TYPES.join(', ')}.`);
27
+ process.exit(1);
28
+ }
29
+ const index = await getRegistryIndex(opts.registry);
30
+ const items = uiBlocks({ type: opts.type, category: opts.category }, index)
31
+ .filter((i) => !filter || i.name.includes(filter));
32
+
33
+ // The JSON form is the whole of stdout, so nothing else is printed.
34
+ if (opts.json) {
35
+ console.log(JSON.stringify(items));
36
+ return;
37
+ }
38
+ if (!items.length) {
16
39
  logger.info('No matches.');
17
40
  return;
18
41
  }
19
- for (const i of filtered) {
20
- const desc = i.description ? logger.dim(': ' + i.description) : '';
21
- logger.info(` ${logger.cyan(i.name)}${desc}`);
42
+ for (const [type, label] of GROUPS) {
43
+ const group = items.filter((i) => i.type === type);
44
+ if (!group.length) continue;
45
+ logger.info(logger.bold(`${label}:`));
46
+ for (const i of group) {
47
+ const desc = i.description ? logger.dim(': ' + i.description) : '';
48
+ logger.info(` ${logger.cyan(i.name)}${desc}`);
49
+ }
50
+ logger.info('');
22
51
  }
23
- logger.info('');
24
- logger.info(`${filtered.length} component${filtered.length === 1 ? '' : 's'}.`);
52
+ const count = (type, word) => {
53
+ const n = items.filter((i) => i.type === type).length;
54
+ return n ? `${n} ${word}${n === 1 ? '' : 's'}` : null;
55
+ };
56
+ logger.info([count('ui', 'component'), count('block', 'block'), count('chart', 'chart')].filter(Boolean).join(', ') + '.');
25
57
  });
@@ -1,34 +1,62 @@
1
1
  import { Command } from 'commander';
2
2
  import { getRegistryItem, DEFAULT_REGISTRY_URL, isDefaultRegistry } from '../registry/fetcher.js';
3
- import { uiComponent, renderComponentText } from '../registry/extract.js';
3
+ import { uiComponent, renderComponentText, itemKind, projectBlock, renderBlockText } from '../registry/extract.js';
4
4
  import { logger } from '../utils/logger.js';
5
+ import { getConfig } from '../utils/get-config.js';
6
+ import { bakeForStyle } from '../registry/style-bake.js';
7
+
8
+ /**
9
+ * The style to bake with: `--style`, else the project's components.json, else
10
+ * the default. Outside a project (no components.json) there is no config to
11
+ * read, which is not an error for `view`.
12
+ */
13
+ function styleFor(opts) {
14
+ if (opts.style) return opts.style;
15
+ try { return getConfig(process.cwd())?.style; } catch { return undefined; }
16
+ }
5
17
 
6
18
  export const view = new Command()
7
19
  .name('view')
8
20
  .description("Print a registry item's source (and the paste-ready example) to stdout")
9
- .argument('<name>', 'component name')
21
+ .argument('<name>', 'component, block or chart name')
10
22
  .option('--registry <url>', 'registry base URL', DEFAULT_REGISTRY_URL)
11
23
  .option('--source', 'print only the raw source, not the projected view')
24
+ .option('--style <name>', 'the style to bake the source with (default: components.json, else new-york)')
25
+ .option('--json', 'a block or chart: print the projection as one JSON document')
26
+ .option('--files-only', 'a block or chart: print the file list and stop before the sources')
12
27
  .action(async (name, opts) => {
28
+ const style = styleFor(opts);
29
+
30
+ // A block or chart (D18) prints what it is, how to install it and where
31
+ // its files land, then the sources, all from the projector the MCP `ui`
32
+ // tool shares. Resolved first, since a block has no component projection.
33
+ const item = await getRegistryItem(name, opts.registry);
34
+ const kind = itemKind(item);
35
+ if (kind === 'block' || kind === 'chart') {
36
+ const block = projectBlock(item, { style, source: !opts.filesOnly });
37
+ console.log(opts.json ? JSON.stringify(block, null, 2) : renderBlockText(block));
38
+ return;
39
+ }
13
40
  // For a local registry:ui component, lead with the projected view (helper
14
41
  // signatures + the paste-ready @example + deps). This is the human /
15
42
  // offline path to the example that `add` strips from the copied file, and
16
43
  // it shares ONE projector with the MCP `ui` tool (`registry/extract.js`).
17
44
  // The projection reads the LOCAL packaged registry, so it only applies to
18
45
  // the default registry (a custom --registry gets the raw fetched source).
19
- const projected = opts.source || !isDefaultRegistry(opts.registry) ? null : uiComponent(name);
46
+ const projected = opts.source || !isDefaultRegistry(opts.registry) ? null : uiComponent(name, { style });
20
47
  if (projected) {
21
48
  console.log(renderComponentText(projected));
22
49
  console.log('');
23
50
  logger.info(logger.dim('# --- full source ---'));
24
51
  }
25
52
 
26
- const item = await getRegistryItem(name, opts.registry);
27
53
  logger.info(logger.dim(`# ${item.name}: ${item.type}`));
28
54
  if (item.description) logger.info(logger.dim(`# ${item.description}`));
29
55
  for (const f of item.files || []) {
30
56
  logger.info('');
31
57
  logger.info(logger.dim(`# ${f.path}`));
32
- console.log(f.content || '');
58
+ // Baked, so the printed source is the plain Tailwind `add` would write
59
+ // (#1666). A custom registry's file with no cn-* name passes unchanged.
60
+ console.log(bakeForStyle(f.content || '', style));
33
61
  }
34
62
  });
@@ -11,7 +11,7 @@
11
11
  * invented: a helper matching neither authored shape yields no value list.
12
12
  *
13
13
  * `allow` takes category names and class-group ids. The documented starting
14
- * configuration is `["layout", "rounded"]`, which is what lets the skill's
14
+ * configuration is `["layout", "rounded"]`, which is what lets the kit's
15
15
  * sanctioned one-off (`cn(buttonClass({ size: 'none' }), 'w-9 h-9
16
16
  * rounded-full')`) pass: `w-9 h-9` is layout, and `rounded-full` is the plain
17
17
  * radius group granted by name without opening the whole `shape` category.
@@ -19,6 +19,7 @@
19
19
  */
20
20
 
21
21
  import { loadRegistryItem, loadRegistryIndex, isCustomElementSource } from './local.js';
22
+ import { bakeForStyle } from './style-bake.js';
22
23
  import { extractExample } from './example.js';
23
24
 
24
25
  /**
@@ -243,17 +244,23 @@ export function extractDocHeader(src) {
243
244
  * Project one registry component into the agent-facing shape. Returns null when
244
245
  * the name is not a `registry:ui` component.
245
246
  *
247
+ * The source is BAKED first (#1666): the registry is in base form, and what an
248
+ * agent copies from this projection must be the plain Tailwind an app gets,
249
+ * never a `cn-*` name. `style` is the app's `components.json` style, and an
250
+ * absent one means `new-york`, the kit's default look.
251
+ *
246
252
  * @param {string} name
253
+ * @param {{ style?: string }} [opts]
247
254
  * @returns {{
248
255
  * name: string, tier: 1|2, type: string,
249
256
  * description: string, helpers: string[], example: string,
250
257
  * dependencies: string[], registryDependencies: string[],
251
258
  * } | null}
252
259
  */
253
- export function uiComponent(name) {
260
+ export function uiComponent(name, opts = {}) {
254
261
  const item = loadRegistryItem(name);
255
262
  if (!item || item.type !== 'registry:ui') return null;
256
- const src = (item.files || []).map((f) => f.content || '').join('\n');
263
+ const src = (item.files || []).map((f) => bakeForStyle(f.content || '', opts.style)).join('\n');
257
264
  const tier = isCustomElementSource(src) ? 2 : 1;
258
265
  return {
259
266
  name: item.name,
@@ -267,11 +274,25 @@ export function uiComponent(name) {
267
274
  };
268
275
  }
269
276
 
277
+ /**
278
+ * A component's files baked for a style, as `webjs ui view` prints them and
279
+ * `add` writes them (paths are the registry's). The /ui docs' Manual tab
280
+ * shows these, so the page and the CLI cannot disagree about the source.
281
+ *
282
+ * @param {string} name
283
+ * @param {{ style?: string }} [opts]
284
+ * @returns {Array<{ path: string, content: string }> | null}
285
+ */
286
+ export function uiComponentFiles(name, opts = {}) {
287
+ const item = loadRegistryItem(name);
288
+ if (!item) return null;
289
+ return (item.files || []).map((f) => ({ path: f.path, content: bakeForStyle(f.content || '', opts.style) }));
290
+ }
291
+
270
292
  /**
271
293
  * The kit inventory: one compact entry per `registry:ui` component (name, tier,
272
- * helper signatures, npm deps). The no-args payload for the MCP `ui` tool and
273
- * the `references/ui-kit.md` skill surface, so an agent reaches for a helper
274
- * instead of expanding Tailwind by hand.
294
+ * helper signatures, npm deps). The no-args payload for the MCP `ui` tool, so
295
+ * an agent reaches for a helper instead of expanding Tailwind by hand.
275
296
  *
276
297
  * @returns {Array<{ name: string, tier: 1|2, helpers: string[], dependencies: string[] }>}
277
298
  */
@@ -290,6 +311,174 @@ export function uiInventory() {
290
311
  .sort((a, b) => a.name.localeCompare(b.name));
291
312
  }
292
313
 
314
+ /* -------------------- blocks and charts (#1666, D18) -------------------- */
315
+
316
+ /**
317
+ * What a block is, in the one phrasing every agent-facing surface uses. A
318
+ * block and a chart are both `registry:block` items on the wire (shadcn
319
+ * parity), told apart by a chart's `chart` category.
320
+ */
321
+ export const BLOCK_DEFINITION = 'a ready-made view you install and then edit';
322
+
323
+ /** The category that marks a `registry:block` as a chart. */
324
+ export const CHART_CATEGORY = 'chart';
325
+
326
+ /**
327
+ * The agent-facing kind of a registry item: `ui` for a component, `chart` for
328
+ * a block carrying the `chart` category, `block` for any other block, and
329
+ * null for everything else (a lib, a theme).
330
+ *
331
+ * @param {{ type?: string, categories?: string[] }} item
332
+ * @returns {'ui' | 'block' | 'chart' | null}
333
+ */
334
+ export function itemKind(item) {
335
+ if (!item) return null;
336
+ if (item.type === 'registry:ui') return 'ui';
337
+ if (item.type !== 'registry:block') return null;
338
+ return (item.categories || []).includes(CHART_CATEGORY) ? 'chart' : 'block';
339
+ }
340
+
341
+ /**
342
+ * The category a block is grouped under in a compact listing: its LAST, most
343
+ * specific category (`login` for `['authentication', 'login']`, `area` for
344
+ * `['chart', 'area']`), so each name appears once. A block with none is
345
+ * grouped under `other`. Filtering by category still matches every one.
346
+ *
347
+ * @param {{ categories?: string[] }} item
348
+ * @returns {string}
349
+ */
350
+ export function primaryCategory(item) {
351
+ const cats = (item.categories || []).filter((c) => c !== CHART_CATEGORY);
352
+ return cats.length ? cats[cats.length - 1] : 'other';
353
+ }
354
+
355
+ /**
356
+ * One compact entry per block or chart (and per component when `type` asks
357
+ * for them): `{ name, type, categories, description }`, sorted by name. The
358
+ * shape `webjsui list --json` prints and the MCP `ui` tool's filtered
359
+ * listing returns.
360
+ *
361
+ * @param {{ type?: 'ui' | 'block' | 'chart' | 'all', category?: string }} [opts]
362
+ * `type` defaults to `block` plus `chart`; `all` adds the components.
363
+ * @param {any[]} [index] the registry index, the packaged one by default
364
+ * @returns {Array<{ name: string, type: 'ui' | 'block' | 'chart', categories: string[], description: string }>}
365
+ */
366
+ export function uiBlocks(opts = {}, index = loadRegistryIndex()) {
367
+ const want = opts.type || 'blocks';
368
+ const keep = (/** @type {string|null} */ kind) =>
369
+ kind !== null && (
370
+ want === 'all' ? true
371
+ : want === 'blocks' ? kind === 'block' || kind === 'chart'
372
+ : kind === want
373
+ );
374
+ return index
375
+ .map((i) => ({ i, kind: itemKind(i) }))
376
+ .filter(({ i, kind }) => keep(kind) && (!opts.category || (i.categories || []).includes(opts.category)))
377
+ .map(({ i, kind }) => ({
378
+ name: i.name,
379
+ type: /** @type {'ui' | 'block' | 'chart'} */ (kind),
380
+ categories: i.categories || [],
381
+ description: i.description || '',
382
+ }))
383
+ .sort((a, b) => a.name.localeCompare(b.name));
384
+ }
385
+
386
+ /**
387
+ * The blocks and charts as NAME LISTS grouped by {@link primaryCategory}, with
388
+ * no descriptions: `{ blocks: { login: [...] }, charts: { area: [...] } }`.
389
+ * The no-argument MCP `ui` payload carries this, so it stays cheap however
390
+ * many blocks the kit ships.
391
+ *
392
+ * @param {any[]} [index]
393
+ * @returns {{ blocks: Record<string, string[]>, charts: Record<string, string[]> }}
394
+ */
395
+ export function uiBlockIndex(index = loadRegistryIndex()) {
396
+ /** @type {{ blocks: Record<string, string[]>, charts: Record<string, string[]> }} */
397
+ const out = { blocks: {}, charts: {} };
398
+ for (const b of uiBlocks({}, index)) {
399
+ const group = b.type === 'chart' ? out.charts : out.blocks;
400
+ (group[primaryCategory(b)] ??= []).push(b.name);
401
+ }
402
+ return out;
403
+ }
404
+
405
+ /** The command that installs a registry item, as every printed hint spells it (invariant 8). */
406
+ export function installCommand(name) {
407
+ return `npx @webjsdev/ui add ${name}`;
408
+ }
409
+
410
+ /**
411
+ * Project one block (or chart) item into the agent-facing shape: what it is,
412
+ * how to install it, and the files it writes with their targets. Pure over
413
+ * the item, so `view` can project an item fetched from a custom registry.
414
+ * Returns null when the item is not a block.
415
+ *
416
+ * The sources are left out unless `source` is true, since the cheap path is
417
+ * to install the block and read the files on disk. When included they are
418
+ * BAKED (#1666), so no `cn-*` name reaches an agent, but their imports stay
419
+ * registry-relative: `add` is what rewrites them to the app's aliases.
420
+ *
421
+ * @param {any} item a registry item with its files
422
+ * @param {{ style?: string, source?: boolean }} [opts]
423
+ */
424
+ export function projectBlock(item, opts = {}) {
425
+ const kind = itemKind(item);
426
+ if (kind !== 'block' && kind !== 'chart') return null;
427
+ return {
428
+ name: item.name,
429
+ type: kind,
430
+ title: item.title || item.name,
431
+ description: item.description || '',
432
+ categories: item.categories || [],
433
+ install: installCommand(item.name),
434
+ dependencies: item.dependencies || [],
435
+ registryDependencies: item.registryDependencies || [],
436
+ ...(item.cssVars ? { cssVars: item.cssVars } : {}),
437
+ files: (item.files || []).map((f) => ({
438
+ path: f.path,
439
+ type: f.type,
440
+ target: f.target || f.path,
441
+ ...(opts.source ? { content: bakeForStyle(f.content || '', opts.style) } : {}),
442
+ })),
443
+ };
444
+ }
445
+
446
+ /**
447
+ * {@link projectBlock} for a block in the packaged registry, by name. Null
448
+ * when the name is not a block.
449
+ *
450
+ * @param {string} name
451
+ * @param {{ style?: string, source?: boolean }} [opts]
452
+ */
453
+ export function uiBlock(name, opts = {}) {
454
+ const item = loadRegistryItem(name);
455
+ return item ? projectBlock(item, opts) : null;
456
+ }
457
+
458
+ /**
459
+ * Render a block projection as human-readable text for `webjsui view`: the
460
+ * description, categories, dependencies, the install command and the file
461
+ * list with targets. The sources, when the projection carries them, follow.
462
+ *
463
+ * @param {ReturnType<typeof projectBlock>} b
464
+ * @returns {string}
465
+ */
466
+ export function renderBlockText(b) {
467
+ if (!b) return '';
468
+ const lines = [`# ${b.name} (${b.type})`];
469
+ if (b.description) lines.push('', b.description);
470
+ if (b.categories.length) lines.push('', `categories: ${b.categories.join(', ')}`);
471
+ if (b.registryDependencies.length) lines.push(`registry deps: ${b.registryDependencies.join(', ')}`);
472
+ if (b.dependencies.length) lines.push(`npm: ${b.dependencies.join(', ')}`);
473
+ lines.push('', `Install: ${b.install}`, '', 'Files:');
474
+ for (const f of b.files) lines.push(` ${f.target}`);
475
+ for (const f of b.files) {
476
+ if (f.content === undefined) continue;
477
+ lines.push('', `# --- ${f.target} ---`, f.content.replace(/\n$/, ''));
478
+ }
479
+ return lines.join('\n');
480
+ }
481
+
293
482
  /**
294
483
  * Render a component projection as human-readable text for `webjsui view`.
295
484
  * Shares the SAME {@link uiComponent} data the MCP `ui` tool returns, so the
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The app's icon library in a resolved install tree (#1666).
3
+ *
4
+ * Registry items depend on `lib-icons` (the Lucide file). The other four
5
+ * libraries export the same function names and land at the same path, so an
6
+ * app whose `components.json` names one of them gets that library's file in
7
+ * place of Lucide's, and a block's icons draw in the library the app chose.
8
+ *
9
+ * @module registry/icons
10
+ */
11
+
12
+ import { getRegistryItem } from './fetcher.js';
13
+ import { getIconLibrary } from '../../packages/registry/themes/preset.js';
14
+
15
+ /**
16
+ * Replace `lib-icons` in a resolved tree with the item for `iconLibrary`.
17
+ * A tree without `lib-icons`, Lucide, or an unknown library name is
18
+ * returned as it is.
19
+ *
20
+ * @param {any[]} tree the items `resolveTree` returned
21
+ * @param {string | undefined} iconLibrary `components.json` `iconLibrary`
22
+ * @param {string} [registryUrl]
23
+ * @returns {Promise<any[]>}
24
+ */
25
+ export async function withIconLibrary(tree, iconLibrary, registryUrl) {
26
+ const lib = getIconLibrary(iconLibrary || 'lucide');
27
+ if (!lib || lib.item === 'lib-icons') return tree;
28
+ if (!tree.some((it) => it.name === 'lib-icons')) return tree;
29
+ const chosen = await getRegistryItem(lib.item, registryUrl);
30
+ return tree.map((it) => (it.name === 'lib-icons' ? chosen : it));
31
+ }