@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
@@ -0,0 +1,547 @@
1
+ /**
2
+ * The chart's browser half (#1666): the `<ui-chart>` element, and the
3
+ * tooltip and legend markup it draws (shadcn's ChartTooltipContent and
4
+ * ChartLegendContent), with the ChartConfig types they share. `chart.ts`
5
+ * draws the charts on the server with the same markup, and imports and
6
+ * re-exports everything here, so an app imports the chart module alone.
7
+ *
8
+ * A11y (handled by the element): once upgraded, a chart with a tooltip is a
9
+ * focusable `role="application"` named by its `title`, the arrow keys and
10
+ * Home / End step through its points, Escape hides the tooltip, and each
11
+ * step is announced through a polite live region.
12
+ */
13
+ import { WebComponent, html, render } from '@webjsdev/core';
14
+ import { cn } from '../lib/utils.ts';
15
+ import { formatValue, visibleTicks, type Tick } from './chart-geometry.ts';
16
+
17
+ // --------------------------------------------------------------------------
18
+ // Types
19
+ // --------------------------------------------------------------------------
20
+
21
+ /** shadcn's ChartConfig: a label, and a colour or a light and dark pair, per key. */
22
+ export interface ChartConfigItem {
23
+ label?: string;
24
+ /** An icon for the tooltip and legend, a function returning an `html` / `svg` template. */
25
+ icon?: () => unknown;
26
+ color?: string;
27
+ theme?: { light: string; dark: string };
28
+ }
29
+ export type ChartConfig = Record<string, ChartConfigItem>;
30
+
31
+ /** One row of chart data. */
32
+ export type ChartDatum = Record<string, unknown>;
33
+
34
+ export interface Margin { top: number; right: number; bottom: number; left: number }
35
+
36
+ /** One entry of a tooltip or legend payload, Recharts' shape. */
37
+ export interface ChartPayloadItem {
38
+ dataKey: string;
39
+ name: string;
40
+ value: unknown;
41
+ color: string;
42
+ payload: ChartDatum;
43
+ type?: 'none';
44
+ }
45
+
46
+ export interface ChartTooltipOptions {
47
+ /** The hover cursor (a muted band behind bars, a line on lines and areas). Default true. */
48
+ cursor?: boolean;
49
+ /** A point shown from the first paint, Recharts' `defaultIndex`. */
50
+ defaultIndex?: number;
51
+ indicator?: 'dot' | 'line' | 'dashed';
52
+ hideLabel?: boolean;
53
+ hideIndicator?: boolean;
54
+ nameKey?: string;
55
+ labelKey?: string;
56
+ labelFormatter?: (label: unknown, payload: ChartPayloadItem[]) => unknown;
57
+ formatter?: (value: unknown, name: string, item: ChartPayloadItem, index: number, datum: ChartDatum) => unknown;
58
+ /** One colour for every indicator, shadcn's `color`. */
59
+ color?: string;
60
+ class?: string;
61
+ labelClass?: string;
62
+ }
63
+
64
+ export interface ChartLegendOptions {
65
+ verticalAlign?: 'top' | 'bottom';
66
+ nameKey?: string;
67
+ hideIcon?: boolean;
68
+ class?: string;
69
+ /** The height the legend takes from the plot, in viewBox units. Default 28. */
70
+ height?: number;
71
+ }
72
+
73
+ /** What every chart function takes. */
74
+ export interface ChartBaseOptions {
75
+ config: ChartConfig;
76
+ data: ChartDatum[];
77
+ /** Classes for the container, shadcn's ChartContainer `className`. */
78
+ class?: string;
79
+ id?: string;
80
+ /** The accessible name of the chart. */
81
+ title?: string;
82
+ /** Nominal size: the SVG's viewBox. */
83
+ width?: number;
84
+ height?: number;
85
+ margin?: Partial<Margin>;
86
+ tooltip?: ChartTooltipOptions | false;
87
+ legend?: ChartLegendOptions | false;
88
+ /** Recharts' accessibilityLayer: focus and the arrow keys. Default true. */
89
+ accessibilityLayer?: boolean;
90
+ /** SVG `<defs>` content, for gradients (`svg` template). */
91
+ defs?: unknown;
92
+ }
93
+
94
+ /** The container's colour variables: `--color-<key>` per configured colour. */
95
+ export function chartStyle(config: ChartConfig): string {
96
+ return Object.entries(config)
97
+ .map(([key, item]) => {
98
+ const color = item.theme ? `light-dark(${item.theme.light}, ${item.theme.dark})` : item.color;
99
+ return color ? `--color-${key}: ${color};` : '';
100
+ })
101
+ .filter(Boolean)
102
+ .join(' ');
103
+ }
104
+
105
+ // --------------------------------------------------------------------------
106
+ // Tooltip and legend content (shadcn's ChartTooltipContent / ChartLegendContent)
107
+ // --------------------------------------------------------------------------
108
+
109
+ /** shadcn's getPayloadConfigFromPayload: the config entry a payload item names. */
110
+ export function payloadConfig(config: ChartConfig, item: ChartPayloadItem | undefined, key: string): ChartConfigItem | undefined {
111
+ if (!item) return undefined;
112
+ let k = key;
113
+ const own = (item as unknown as Record<string, unknown>)[key];
114
+ if (typeof own === 'string') k = own;
115
+ else if (typeof item.payload?.[key] === 'string') k = item.payload[key] as string;
116
+ return k in config ? config[k] : config[key];
117
+ }
118
+
119
+ /**
120
+ * A tooltip resolved for one point: its label and its rows, with every
121
+ * formatter and config lookup already applied. When every part is a string
122
+ * it is plain data, which is how the chart serves a point (see `frame`).
123
+ */
124
+ export interface ChartTooltipView {
125
+ label: unknown;
126
+ items: Array<{ name: unknown; value: string | null; color: string; icon?: unknown; custom?: unknown }>;
127
+ }
128
+
129
+ /** The view options the browser needs to draw a served point. */
130
+ export type TooltipLook = Pick<ChartTooltipOptions, 'indicator' | 'hideIndicator' | 'class' | 'labelClass'>;
131
+
132
+ /** Resolve a point's tooltip: shadcn's ChartTooltipContent logic, without the markup. */
133
+ export function chartTooltipView(config: ChartConfig, label: unknown, payload: ChartPayloadItem[], o: ChartTooltipOptions = {}): ChartTooltipView {
134
+ let viewLabel: unknown = '';
135
+ if (!o.hideLabel && payload.length) {
136
+ const first = payload[0];
137
+ const key = `${o.labelKey ?? first.dataKey ?? first.name ?? 'value'}`;
138
+ const itemConfig = payloadConfig(config, first, key);
139
+ const value = !o.labelKey && typeof label === 'string' ? (config[label]?.label ?? label) : itemConfig?.label;
140
+ viewLabel = o.labelFormatter ? o.labelFormatter(value, payload) : (value ?? '');
141
+ }
142
+ const items = payload.filter((item) => item.type !== 'none').map((item, index) => {
143
+ const key = `${o.nameKey ?? item.name ?? item.dataKey ?? 'value'}`;
144
+ const itemConfig = payloadConfig(config, item, key);
145
+ const color = o.color ?? (typeof item.payload?.fill === 'string' ? item.payload.fill : item.color);
146
+ const custom = o.formatter && item.value !== undefined && item.name ? o.formatter(item.value, item.name, item, index, item.payload) : undefined;
147
+ return {
148
+ name: itemConfig?.label ?? item.name,
149
+ value: item.value != null ? formatValue(item.value) : null,
150
+ color,
151
+ ...(itemConfig?.icon ? { icon: itemConfig.icon() } : {}),
152
+ ...(custom !== undefined ? { custom } : {}),
153
+ };
154
+ });
155
+ return { label: viewLabel, items };
156
+ }
157
+
158
+ /** A view that is all strings can be served as data and drawn in the browser. */
159
+ export function isPlainView(v: ChartTooltipView): boolean {
160
+ return typeof v.label === 'string' && v.items.every((i) => i.icon === undefined && i.custom === undefined && typeof i.name === 'string');
161
+ }
162
+
163
+ /** Draw a resolved tooltip: shadcn's ChartTooltipContent markup. */
164
+ export function chartTooltipMarkup(view: ChartTooltipView, o: TooltipLook = {}) {
165
+ if (!view.items.length) return '';
166
+ const indicator = o.indicator ?? 'dot';
167
+ const tooltipLabel = view.label === '' || view.label == null ? '' : html`<div class=${cn('font-medium', o.labelClass)}>${view.label}</div>`;
168
+ const nestLabel = view.items.length === 1 && indicator !== 'dot';
169
+ return html`<div class=${cn('cn-chart-tooltip grid min-w-32 items-start', o.class)}>${nestLabel ? '' : tooltipLabel}<div class="grid gap-1.5">${view.items.map((item) => {
170
+ const body = item.custom !== undefined
171
+ ? item.custom
172
+ : html`${item.icon !== undefined
173
+ ? item.icon
174
+ : o.hideIndicator
175
+ ? ''
176
+ : html`<div class=${cn('shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)', {
177
+ 'h-2.5 w-2.5': indicator === 'dot',
178
+ 'w-1': indicator === 'line',
179
+ 'w-0 border-[1.5px] border-dashed bg-transparent': indicator === 'dashed',
180
+ 'my-0.5': nestLabel && indicator === 'dashed',
181
+ })} style=${`--color-bg: ${item.color}; --color-border: ${item.color}`}></div>`}<div class=${cn('flex flex-1 justify-between leading-none', nestLabel ? 'items-end' : 'items-center')}><div class="grid gap-1.5">${nestLabel ? tooltipLabel : ''}<span class="text-muted-foreground">${item.name}</span></div>${item.value != null ? html`<span class="font-mono font-medium text-foreground tabular-nums">${item.value}</span>` : ''}</div>`;
182
+ return html`<div class=${cn('flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground', indicator === 'dot' && 'items-center')}>${body}</div>`;
183
+ })}</div></div>`;
184
+ }
185
+
186
+ /**
187
+ * The tooltip's content for one point: shadcn's ChartTooltipContent.
188
+ * `label` is the point's category (a month, a date), `payload` its series.
189
+ */
190
+ export function chartTooltipContent(config: ChartConfig, label: unknown, payload: ChartPayloadItem[], o: ChartTooltipOptions = {}) {
191
+ return chartTooltipMarkup(chartTooltipView(config, label, payload, o), o);
192
+ }
193
+
194
+ /** The legend: shadcn's ChartLegendContent markup over a series payload. */
195
+ export function chartLegendContent(config: ChartConfig, payload: ChartPayloadItem[], o: ChartLegendOptions = {}) {
196
+ if (!payload.length) return '';
197
+ return html`<div class=${cn('flex items-center justify-center gap-4', o.verticalAlign === 'top' ? 'pb-3' : 'pt-3', o.class)}>${payload
198
+ .filter((item) => item.type !== 'none')
199
+ .map((item) => {
200
+ const itemConfig = payloadConfig(config, item, `${o.nameKey ?? item.dataKey ?? 'value'}`);
201
+ return html`<div class="flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground">${itemConfig?.icon && !o.hideIcon
202
+ ? itemConfig.icon()
203
+ : html`<div class="h-2 w-2 shrink-0 rounded-[2px]" style=${`background-color: ${item.color}`}></div>`}${itemConfig?.label ?? ''}</div>`;
204
+ })}</div>`;
205
+ }
206
+
207
+ // --------------------------------------------------------------------------
208
+ // The element adds the tooltip, cursor and active marks, by pointer and keyboard
209
+ // --------------------------------------------------------------------------
210
+
211
+ export class UiChart extends WebComponent {
212
+ /** The point showing, or -1. */
213
+ activeIndex = -1;
214
+ _resize: ResizeObserver | null = null;
215
+
216
+ connectedCallback(): void {
217
+ super.connectedCallback?.();
218
+ this.addEventListener('pointermove', this._onMove);
219
+ this.addEventListener('pointerleave', this._onLeave);
220
+ this.addEventListener('focusin', this._onFocus);
221
+ this.addEventListener('focusout', this._onBlur);
222
+ this.addEventListener('keydown', this._onKey);
223
+ }
224
+
225
+ firstUpdated(): void {
226
+ // A chart rendered on the client commits its attributes after the
227
+ // element connects, so a first attempt can find the SVG unfinished.
228
+ if (!this._init()) requestAnimationFrame(() => this._init());
229
+ }
230
+
231
+ disconnectedCallback(): void {
232
+ this.removeEventListener('pointermove', this._onMove);
233
+ this.removeEventListener('pointerleave', this._onLeave);
234
+ this.removeEventListener('focusin', this._onFocus);
235
+ this.removeEventListener('focusout', this._onBlur);
236
+ this.removeEventListener('keydown', this._onKey);
237
+ this._resize?.disconnect();
238
+ this._resize = null;
239
+ super.disconnectedCallback?.();
240
+ }
241
+
242
+ render() {
243
+ return html`<slot></slot>`;
244
+ }
245
+
246
+ _svg(): SVGSVGElement | null {
247
+ return typeof this.querySelector === 'function' ? this.querySelector<SVGSVGElement>('svg.ui-chart-surface') : null;
248
+ }
249
+
250
+ _entries(): HTMLElement[] {
251
+ return Array.from(this.querySelectorAll<HTMLElement>('[data-slot="chart-tooltips"] > [data-index]'));
252
+ }
253
+
254
+ _look(): TooltipLook {
255
+ const raw = this.querySelector<HTMLElement>('[data-slot="chart-tooltips"]')?.dataset.look;
256
+ return raw ? (JSON.parse(raw) as TooltipLook) : {};
257
+ }
258
+
259
+ _init(): boolean {
260
+ const s = this._svg();
261
+ if (!s || !s.getAttribute('viewBox')) return false;
262
+ this._watchSize(s);
263
+ if (!s.dataset.hit) return true;
264
+ if (s.dataset.keyboard === 'true') {
265
+ s.setAttribute('tabindex', '0');
266
+ s.setAttribute('role', 'application');
267
+ s.setAttribute('aria-roledescription', 'chart');
268
+ }
269
+ const d = s.dataset.defaultIndex;
270
+ if (d != null) this.show(Number(d));
271
+ return true;
272
+ }
273
+
274
+ /** Lay the chart out again whenever its box changes size. */
275
+ _watchSize(s: SVGSVGElement): void {
276
+ if (this._resize || typeof ResizeObserver !== 'function') return;
277
+ this._resize = new ResizeObserver(() => this._layout(s));
278
+ this._resize.observe(s);
279
+ }
280
+
281
+ /**
282
+ * Fit the served chart to its box, as Recharts lays out at the real size.
283
+ *
284
+ * The server draws at a nominal size, and the SVG scales to its box. Where
285
+ * the box has another shape (a wide chart in a fixed height on a phone), a
286
+ * cartesian chart (`data-fit`) is widened or narrowed to fill it: the
287
+ * viewBox takes the box's aspect, and the plot is stretched along x around
288
+ * its left edge while the margins and the y axis keep their size. That is
289
+ * exact for the marks Recharts would redraw (its scales and the d3 curves
290
+ * are linear in x), so only what has a size of its own is put back: each
291
+ * label and dot is drawn unstretched, and the x axis ticks move to their
292
+ * new places and are thinned again. Without JavaScript the served layout
293
+ * shows, letterboxed in a box of another shape.
294
+ *
295
+ * Then the labels and dots keep their size in pixels. A 12px label in a
296
+ * chart drawn 340px wide on a 450 unit viewBox would read as 9px, so the
297
+ * SVG's font size, in em of its container's, undoes the scale, and each
298
+ * dot is scaled by it around its centre (Recharts' `r` is in pixels).
299
+ */
300
+ _layout(s: SVGSVGElement): void {
301
+ const shown = s.getBoundingClientRect();
302
+ if (!shown.width || !shown.height) return;
303
+ const [, , w0, h] = (s.dataset.viewBox ??= s.getAttribute('viewBox') ?? '').split(/\s+/).map(Number);
304
+ if (!(w0 > 0 && h > 0)) return;
305
+ const round = (v: number) => Math.round(v * 1e4) / 1e4;
306
+ let w = w0;
307
+ let sx = 1;
308
+ const fit = s.dataset.fit === 'x' && s.dataset.plot != null;
309
+ if (fit) {
310
+ const [px, py, pw, ph] = (s.dataset.plot0 ??= s.dataset.plot ?? '').split(' ').map(Number);
311
+ const wide = (h * shown.width) / shown.height;
312
+ const stretch = (pw + wide - w0) / pw;
313
+ if (pw > 0 && stretch > 0.05) {
314
+ w = wide;
315
+ sx = Math.abs(stretch - 1) < 1e-3 ? 1 : stretch;
316
+ }
317
+ const map = (x: number) => (x <= px ? x : x >= px + pw ? x + (sx - 1) * pw : px + (x - px) * sx);
318
+ s.setAttribute('viewBox', `0 0 ${round(sx === 1 ? w0 : w)} ${h}`);
319
+ s.dataset.plot = [px, py, pw * sx, ph].map(round).join(' ');
320
+ const matrix = sx === 1 ? null : `matrix(${round(sx)} 0 0 1 ${round(px * (1 - sx))} 0)`;
321
+ for (const g of Array.from(s.children)) {
322
+ if (g.tagName.toLowerCase() === 'defs' || g.hasAttribute('data-axis')) continue;
323
+ if (matrix) g.setAttribute('transform', matrix);
324
+ else g.removeAttribute('transform');
325
+ for (const t of Array.from(g.querySelectorAll('text'))) {
326
+ const x = Number(t.getAttribute('x'));
327
+ if (matrix && Number.isFinite(x)) t.setAttribute('transform', `matrix(${round(1 / sx)} 0 0 1 ${round(x * (1 - 1 / sx))} 0)`);
328
+ else t.removeAttribute('transform');
329
+ }
330
+ }
331
+ const axis = s.querySelector<SVGGElement>('[data-axis="x"]');
332
+ if (axis) {
333
+ axis.dataset.extent = String(round(sx === 1 ? w0 : w));
334
+ for (const line of Array.from(axis.querySelectorAll('.ui-chart-cartesian-axis-line'))) {
335
+ for (const a of ['x1', 'x2']) {
336
+ const key = `data-${a}0`;
337
+ if (!line.hasAttribute(key)) line.setAttribute(key, line.getAttribute(a) ?? '0');
338
+ line.setAttribute(a, String(round(map(Number(line.getAttribute(key))))));
339
+ }
340
+ }
341
+ for (const t of Array.from(axis.querySelectorAll<SVGGElement>('[data-coord]'))) {
342
+ t.dataset.coord = String(round(map(Number((t.dataset.coord0 ??= t.dataset.coord)))));
343
+ }
344
+ }
345
+ for (const e of this._entries()) {
346
+ if (e.dataset.x != null) e.dataset.x = String(round(map(Number((e.dataset.x0 ??= e.dataset.x)))));
347
+ }
348
+ }
349
+ const k = Math.max((sx === 1 ? w0 : w) / shown.width, h / shown.height);
350
+ if (!(Number.isFinite(k) && k > 0)) return;
351
+ s.style.fontSize = `${round(k)}em`;
352
+ for (const c of Array.from(s.querySelectorAll('circle.ui-chart-dot'))) {
353
+ const cx = Number(c.getAttribute('cx'));
354
+ const cy = Number(c.getAttribute('cy'));
355
+ const a = k / (fit ? sx : 1);
356
+ c.setAttribute('transform', `matrix(${round(a)} 0 0 ${round(k)} ${round(cx * (1 - a))} ${round(cy * (1 - k))})`);
357
+ }
358
+ this._fitTicks(s, k);
359
+ const tip = this.querySelector<HTMLElement>('[data-slot="chart-tooltip"]');
360
+ if (this.activeIndex >= 0 && tip && !tip.hidden) this.show(this.activeIndex);
361
+ }
362
+
363
+ /**
364
+ * Thin each axis's labels again with their real widths, the way Recharts'
365
+ * getTicks does at render: the server could only estimate them, and the
366
+ * labels keep their font size while the chart scales.
367
+ */
368
+ _fitTicks(s: SVGSVGElement, k: number): void {
369
+ for (const axis of Array.from(s.querySelectorAll<SVGGElement>('[data-axis][data-interval]'))) {
370
+ const interval = axis.dataset.interval ?? 'preserveEnd';
371
+ const groups = Array.from(axis.querySelectorAll<SVGGElement>('[data-coord]'));
372
+ const isX = axis.dataset.axis === 'x';
373
+ const ticks: Tick[] = groups.map((g, i) => ({ value: i, label: '', coord: Number(g.dataset.coord) }));
374
+ const size = (t: Tick) => {
375
+ const text = groups[Number(t.value)].querySelector('text');
376
+ if (!text) return 0;
377
+ return isX ? text.getComputedTextLength() : text.getBBox().height;
378
+ };
379
+ // Recharts' edges are the chart's box, with its margins in pixels. Here
380
+ // the margins scale with the chart while the labels do not, so the room
381
+ // between the box and the outer ticks is widened back to its pixels.
382
+ const extent = Number(axis.dataset.extent);
383
+ const coords = ticks.map((t) => t.coord);
384
+ const before = coords.length ? Math.min(...coords) : 0;
385
+ const after = coords.length ? extent - Math.max(...coords) : 0;
386
+ const kept = visibleTicks(ticks, size, -before * (k - 1), extent + after * (k - 1), Number(axis.dataset.gap), /^\d+$/.test(interval) ? Number(interval) : (interval as 'preserveEnd'));
387
+ const at = new Map(kept.map((t) => [Number(t.value), t.at ?? t.coord]));
388
+ groups.forEach((g, i) => {
389
+ const pos = at.get(i);
390
+ if (pos == null) {
391
+ g.setAttribute('visibility', 'hidden');
392
+ return;
393
+ }
394
+ g.removeAttribute('visibility');
395
+ const v = String(Math.round(pos * 1e4) / 1e4);
396
+ for (const el of Array.from(g.querySelectorAll('text, tspan'))) {
397
+ if (isX) el.setAttribute('x', v);
398
+ else if (el.tagName.toLowerCase() === 'text') el.setAttribute('y', v);
399
+ }
400
+ for (const line of Array.from(g.querySelectorAll('line'))) {
401
+ if (isX) { line.setAttribute('x1', v); line.setAttribute('x2', v); } else { line.setAttribute('y1', v); line.setAttribute('y2', v); }
402
+ }
403
+ });
404
+ }
405
+ }
406
+
407
+ /** Where a point's tooltip anchors, in pixels from the chart's wrapper. */
408
+ _anchor(i: number): { x: number; y: number } | null {
409
+ const s = this._svg();
410
+ const e = this._entries()[i];
411
+ const m = s?.getScreenCTM?.();
412
+ const wrap = s?.parentElement;
413
+ if (!s || !e || !m || !wrap) return null;
414
+ const r = wrap.getBoundingClientRect();
415
+ const x = Number(e.dataset.x);
416
+ const y = Number(e.dataset.y);
417
+ return { x: m.a * x + m.c * y + m.e - r.left, y: m.b * x + m.d * y + m.f - r.top };
418
+ }
419
+
420
+ /** Show point `i`, its tooltip at `at` (pixels from the wrapper) or at its anchor. */
421
+ show(i: number, at?: { x: number; y: number }): void {
422
+ const entry = this._entries()[i];
423
+ const wrapper = this.querySelector<HTMLElement>('[data-slot="chart-tooltip"]');
424
+ if (!entry || !wrapper) return;
425
+ for (const g of this.querySelectorAll('[data-slot="chart-cursor"] > [data-index], [data-slot="chart-active"] > [data-index]')) {
426
+ g.setAttribute('visibility', g.getAttribute('data-index') === String(i) ? 'visible' : 'hidden');
427
+ }
428
+ if (i !== this.activeIndex || wrapper.hidden || !wrapper.firstChild) {
429
+ const tip = entry.dataset.tip;
430
+ if (tip) {
431
+ // A served point is data: draw it with the same markup the server uses.
432
+ const box = document.createElement('div');
433
+ render(chartTooltipMarkup(JSON.parse(tip) as ChartTooltipView, this._look()), box);
434
+ wrapper.replaceChildren(...Array.from(box.childNodes));
435
+ } else {
436
+ wrapper.replaceChildren(...Array.from(entry.cloneNode(true).childNodes));
437
+ }
438
+ }
439
+ this.activeIndex = i;
440
+ wrapper.hidden = false;
441
+ const p = at ?? this._anchor(i);
442
+ if (!p) return;
443
+ // Recharts' getTooltipTranslate: 10px right of and below the point, or
444
+ // above and to its left when that would leave the plot area.
445
+ const area = this._plot();
446
+ const x = p.x + 10 + wrapper.offsetWidth > area.right ? Math.max(p.x - wrapper.offsetWidth - 10, area.left) : Math.max(p.x + 10, area.left);
447
+ const y = p.y + 10 + wrapper.offsetHeight > area.bottom ? Math.max(p.y - wrapper.offsetHeight - 10, area.top) : Math.max(p.y + 10, area.top);
448
+ wrapper.style.transform = `translate(${x}px, ${y}px)`;
449
+ }
450
+
451
+ /** The plot area in pixels from the chart's wrapper. */
452
+ _plot(): { left: number; top: number; right: number; bottom: number } {
453
+ const s = this._svg();
454
+ const wrap = s?.parentElement;
455
+ const m = s?.getScreenCTM?.();
456
+ const [x, y, w, h] = (s?.dataset.plot ?? '').split(' ').map(Number);
457
+ if (!s || !wrap || !m || !Number.isFinite(h)) {
458
+ return { left: 0, top: 0, right: wrap?.clientWidth ?? 0, bottom: wrap?.clientHeight ?? 0 };
459
+ }
460
+ const r = wrap.getBoundingClientRect();
461
+ return {
462
+ left: m.a * x + m.e - r.left,
463
+ top: m.d * y + m.f - r.top,
464
+ right: m.a * (x + w) + m.e - r.left,
465
+ bottom: m.d * (y + h) + m.f - r.top,
466
+ };
467
+ }
468
+
469
+ /** Hide the tooltip and the marks. */
470
+ hide(): void {
471
+ const wrapper = this.querySelector<HTMLElement>('[data-slot="chart-tooltip"]');
472
+ if (wrapper) wrapper.hidden = true;
473
+ for (const g of this.querySelectorAll('[data-slot="chart-cursor"] > [data-index], [data-slot="chart-active"] > [data-index]')) g.setAttribute('visibility', 'hidden');
474
+ this.activeIndex = -1;
475
+ }
476
+
477
+ _announce(i: number): void {
478
+ const live = this.querySelector<HTMLElement>('[data-slot="chart-live"]');
479
+ const entry = this._entries()[i];
480
+ if (!live || !entry) return;
481
+ const tip = entry.dataset.tip ? (JSON.parse(entry.dataset.tip) as ChartTooltipView) : null;
482
+ const text = tip
483
+ ? [tip.label, ...tip.items.map((it) => `${it.name} ${it.value ?? ''}`)].join(' ')
484
+ : entry.textContent ?? '';
485
+ live.textContent = text.replace(/\s+/g, ' ').trim();
486
+ }
487
+
488
+ _onMove = (e: PointerEvent): void => {
489
+ const s = this._svg();
490
+ if (!s || !s.dataset.hit || !s.parentElement) return;
491
+ const wrap = s.parentElement.getBoundingClientRect();
492
+ const at = { x: e.clientX - wrap.left, y: e.clientY - wrap.top };
493
+ let index = -1;
494
+ if (s.dataset.hit === 'target') {
495
+ const t = (e.target as Element | null)?.closest?.('[data-index]');
496
+ if (t && s.contains(t)) index = Number(t.getAttribute('data-index'));
497
+ } else {
498
+ const m = s.getScreenCTM?.();
499
+ if (!m) return;
500
+ const inv = m.inverse();
501
+ const v = s.dataset.hit === 'y'
502
+ ? inv.b * e.clientX + inv.d * e.clientY + inv.f
503
+ : inv.a * e.clientX + inv.c * e.clientY + inv.e;
504
+ const axis = s.dataset.hit === 'y' ? 'y' : 'x';
505
+ let best = Infinity;
506
+ this._entries().forEach((en, i) => {
507
+ const d = Math.abs(Number(en.dataset[axis]) - v);
508
+ if (d < best) { best = d; index = i; }
509
+ });
510
+ }
511
+ if (index < 0) this.hide();
512
+ else this.show(index, at);
513
+ };
514
+
515
+ _onLeave = (): void => {
516
+ if (!this.contains(document.activeElement)) this.hide();
517
+ };
518
+
519
+ _onFocus = (e: FocusEvent): void => {
520
+ if (e.target !== this._svg()) return;
521
+ const i = this.activeIndex >= 0 ? this.activeIndex : 0;
522
+ this.show(i);
523
+ this._announce(i);
524
+ };
525
+
526
+ _onBlur = (e: FocusEvent): void => {
527
+ if (e.target === this._svg()) this.hide();
528
+ };
529
+
530
+ _onKey = (e: KeyboardEvent): void => {
531
+ if (e.target !== this._svg()) return;
532
+ const n = this._entries().length;
533
+ if (!n) return;
534
+ const cur = this.activeIndex;
535
+ let next = cur;
536
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') next = Math.min(n - 1, cur + 1);
537
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') next = Math.max(0, cur - 1);
538
+ else if (e.key === 'Home') next = 0;
539
+ else if (e.key === 'End') next = n - 1;
540
+ else if (e.key === 'Escape') { this.hide(); return; }
541
+ else return;
542
+ e.preventDefault();
543
+ this.show(next);
544
+ this._announce(next);
545
+ };
546
+ }
547
+ UiChart.register('ui-chart');