@sableui/react 0.6.2 → 0.7.1

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 (642) hide show
  1. package/AGENTS.md +2 -2
  2. package/CHANGELOG.md +315 -0
  3. package/CONTRIBUTING.md +16 -10
  4. package/DESIGN.md +3 -3
  5. package/README.md +3 -3
  6. package/bin/sable-lint.mjs +18 -0
  7. package/bin/sable.mjs +470 -62
  8. package/dist/blocks/api-keys-block.js +44 -0
  9. package/dist/blocks/api-keys-block.meta.js +21 -0
  10. package/dist/blocks/chat-thread-block.js +17 -0
  11. package/dist/blocks/chat-thread-block.meta.js +20 -0
  12. package/dist/blocks/command-palette-block.js +24 -0
  13. package/dist/blocks/command-palette-block.meta.js +21 -0
  14. package/dist/blocks/cta-band-block.js +27 -0
  15. package/dist/blocks/cta-band-block.meta.js +20 -0
  16. package/dist/blocks/danger-zone-block.js +39 -0
  17. package/dist/blocks/danger-zone-block.meta.js +21 -0
  18. package/dist/blocks/device-comparison-block.js +69 -0
  19. package/dist/blocks/device-comparison-block.meta.js +21 -0
  20. package/dist/blocks/event-card-block.js +40 -0
  21. package/dist/blocks/event-card-block.meta.js +21 -0
  22. package/dist/blocks/faq-block.js +38 -0
  23. package/dist/blocks/faq-block.meta.js +20 -0
  24. package/dist/blocks/feature-grid-block.js +38 -0
  25. package/dist/blocks/feature-grid-block.meta.js +21 -0
  26. package/dist/blocks/feedback-form-block.js +30 -0
  27. package/dist/blocks/feedback-form-block.meta.js +21 -0
  28. package/dist/blocks/goal-progress-block.js +24 -0
  29. package/dist/blocks/goal-progress-block.meta.js +21 -0
  30. package/dist/blocks/hero-block.js +33 -0
  31. package/dist/blocks/hero-block.meta.js +21 -0
  32. package/dist/blocks/index.js +162 -1964
  33. package/dist/blocks/invite-team-block.js +36 -0
  34. package/dist/blocks/invite-team-block.meta.js +20 -0
  35. package/dist/blocks/invoice-history-block.js +41 -0
  36. package/dist/blocks/invoice-history-block.meta.js +21 -0
  37. package/dist/blocks/kpi-sparkline-block.js +29 -0
  38. package/dist/blocks/kpi-sparkline-block.meta.js +20 -0
  39. package/dist/blocks/media-player-block.js +68 -0
  40. package/dist/blocks/media-player-block.meta.js +21 -0
  41. package/dist/blocks/newsletter-block.js +35 -0
  42. package/dist/blocks/newsletter-block.meta.js +21 -0
  43. package/dist/blocks/not-found-block.js +27 -0
  44. package/dist/blocks/not-found-block.meta.js +20 -0
  45. package/dist/blocks/notification-list-block.js +32 -0
  46. package/dist/blocks/notification-list-block.meta.js +21 -0
  47. package/dist/blocks/notification-settings-block.js +25 -0
  48. package/dist/blocks/notification-settings-block.meta.js +20 -0
  49. package/dist/blocks/order-tracking-block.js +26 -0
  50. package/dist/blocks/order-tracking-block.meta.js +20 -0
  51. package/dist/blocks/pricing-card-block.js +46 -0
  52. package/dist/blocks/pricing-card-block.meta.js +21 -0
  53. package/dist/blocks/pricing-table-block.js +88 -0
  54. package/dist/blocks/pricing-table-block.meta.js +20 -0
  55. package/dist/blocks/product-card-block.js +26 -0
  56. package/dist/blocks/product-card-block.meta.js +21 -0
  57. package/dist/blocks/profile-card-block.js +58 -0
  58. package/dist/blocks/profile-card-block.meta.js +21 -0
  59. package/dist/blocks/profile-form-block.js +70 -0
  60. package/dist/blocks/profile-form-block.meta.js +21 -0
  61. package/dist/blocks/revenue-breakdown-block.js +38 -0
  62. package/dist/blocks/revenue-breakdown-block.meta.js +21 -0
  63. package/dist/blocks/sign-in-block.js +38 -0
  64. package/dist/blocks/sign-in-block.meta.js +21 -0
  65. package/dist/blocks/sign-up-block.js +48 -0
  66. package/dist/blocks/sign-up-block.meta.js +21 -0
  67. package/dist/blocks/site-footer-block.js +54 -0
  68. package/dist/blocks/site-footer-block.meta.js +20 -0
  69. package/dist/blocks/stat-row-block.js +28 -0
  70. package/dist/blocks/stat-row-block.meta.js +21 -0
  71. package/dist/blocks/steps-block.js +37 -0
  72. package/dist/blocks/steps-block.meta.js +20 -0
  73. package/dist/blocks/task-list-block.js +52 -0
  74. package/dist/blocks/task-list-block.meta.js +21 -0
  75. package/dist/blocks/team-members-block.js +49 -0
  76. package/dist/blocks/team-members-block.meta.js +21 -0
  77. package/dist/blocks/testimonial-block.js +49 -0
  78. package/dist/blocks/testimonial-block.meta.js +20 -0
  79. package/dist/blocks/traffic-sources-block.js +39 -0
  80. package/dist/blocks/traffic-sources-block.meta.js +21 -0
  81. package/dist/blocks/traffic-trend-block.js +61 -0
  82. package/dist/blocks/traffic-trend-block.meta.js +21 -0
  83. package/dist/blocks/upload-list-block.js +39 -0
  84. package/dist/blocks/upload-list-block.meta.js +21 -0
  85. package/dist/blocks/verify-code-block.js +28 -0
  86. package/dist/blocks/verify-code-block.meta.js +21 -0
  87. package/dist/blocks/wallet-block.js +48 -0
  88. package/dist/blocks/wallet-block.meta.js +21 -0
  89. package/dist/components/accordion/accordion.js +63 -0
  90. package/dist/components/accordion/accordion.meta.js +155 -0
  91. package/dist/components/accordion/index.js +15 -0
  92. package/dist/components/app-header/app-header.js +30 -0
  93. package/dist/components/app-header/app-header.meta.js +88 -0
  94. package/dist/components/app-header/index.js +7 -0
  95. package/dist/components/app-shell/app-shell-dock.js +37 -0
  96. package/dist/components/app-shell/app-shell.js +67 -0
  97. package/dist/components/app-shell/app-shell.meta.js +176 -0
  98. package/dist/components/app-shell/index.js +7 -0
  99. package/dist/components/area-chart/area-chart.js +10 -0
  100. package/dist/components/area-chart/area-chart.meta.js +218 -0
  101. package/dist/components/area-chart/index.js +7 -0
  102. package/dist/components/attachment/attachment.js +176 -0
  103. package/dist/components/attachment/attachment.meta.js +179 -0
  104. package/dist/components/attachment/attachment.variants.js +47 -0
  105. package/dist/components/attachment/index.js +7 -0
  106. package/dist/components/avatar/avatar.js +192 -0
  107. package/dist/components/avatar/avatar.meta.js +233 -0
  108. package/dist/components/avatar/avatar.variants.js +44 -0
  109. package/dist/components/avatar/index.js +22 -0
  110. package/dist/components/badge/badge.js +26 -0
  111. package/dist/components/badge/badge.meta.js +171 -0
  112. package/dist/components/badge/badge.variants.js +103 -0
  113. package/dist/components/badge/index.js +11 -0
  114. package/dist/components/banner/banner.js +76 -0
  115. package/dist/components/banner/banner.meta.js +172 -0
  116. package/dist/components/banner/banner.variants.js +44 -0
  117. package/dist/components/banner/index.js +9 -0
  118. package/dist/components/bar-chart/bar-chart.js +10 -0
  119. package/dist/components/bar-chart/bar-chart.meta.js +245 -0
  120. package/dist/components/bar-chart/index.js +7 -0
  121. package/dist/components/bottom-nav/bottom-nav.js +63 -0
  122. package/dist/components/bottom-nav/bottom-nav.meta.js +95 -0
  123. package/dist/components/bottom-nav/index.js +11 -0
  124. package/dist/components/breadcrumbs/breadcrumbs.js +90 -0
  125. package/dist/components/breadcrumbs/breadcrumbs.meta.js +111 -0
  126. package/dist/components/breadcrumbs/index.js +17 -0
  127. package/dist/components/browser/browser.js +39 -0
  128. package/dist/components/browser/browser.meta.js +80 -0
  129. package/dist/components/browser/index.js +7 -0
  130. package/dist/components/bubble/bubble.js +110 -0
  131. package/dist/components/bubble/bubble.meta.js +158 -0
  132. package/dist/components/bubble/bubble.variants.js +90 -0
  133. package/dist/components/bubble/index.js +13 -0
  134. package/dist/components/button/button.js +87 -0
  135. package/dist/components/button/button.meta.js +302 -0
  136. package/dist/components/button/button.variants.js +137 -0
  137. package/dist/components/button/index.js +9 -0
  138. package/dist/components/calendar/calendar.js +89 -0
  139. package/dist/components/calendar/calendar.meta.js +136 -0
  140. package/dist/components/calendar/index.js +7 -0
  141. package/dist/components/card/card.js +203 -0
  142. package/dist/components/card/card.meta.js +212 -0
  143. package/dist/components/card/index.js +23 -0
  144. package/dist/components/carousel/carousel.js +428 -0
  145. package/dist/components/carousel/carousel.meta.js +100 -0
  146. package/dist/components/carousel/index.js +7 -0
  147. package/dist/components/chat-composer/chat-composer.js +174 -0
  148. package/dist/components/chat-composer/chat-composer.meta.js +241 -0
  149. package/dist/components/chat-composer/chat-composer.variants.js +17 -0
  150. package/dist/components/chat-composer/index.js +7 -0
  151. package/dist/components/checkbox/checkbox-mark.js +28 -0
  152. package/dist/components/checkbox/checkbox.js +30 -0
  153. package/dist/components/checkbox/checkbox.meta.js +127 -0
  154. package/dist/components/checkbox/index.js +7 -0
  155. package/dist/components/checkbox-card/checkbox-card.js +94 -0
  156. package/dist/components/checkbox-card/checkbox-card.meta.js +154 -0
  157. package/dist/components/checkbox-card/checkbox-card.variants.js +43 -0
  158. package/dist/components/checkbox-card/index.js +11 -0
  159. package/dist/components/code/code.js +19 -0
  160. package/dist/components/code/code.meta.js +71 -0
  161. package/dist/components/code/index.js +7 -0
  162. package/dist/components/code-block/code-block.js +84 -0
  163. package/dist/components/code-block/code-block.meta.js +103 -0
  164. package/dist/components/code-block/index.js +8 -0
  165. package/dist/components/collapsible/collapsible.js +38 -0
  166. package/dist/components/collapsible/collapsible.meta.js +117 -0
  167. package/dist/components/collapsible/index.js +15 -0
  168. package/dist/components/color-field/color-field.js +293 -0
  169. package/dist/components/color-field/color-field.meta.js +142 -0
  170. package/dist/components/color-field/color.js +69 -0
  171. package/dist/components/color-field/index.js +15 -0
  172. package/dist/components/combobox/combobox.js +486 -0
  173. package/dist/components/combobox/combobox.meta.js +217 -0
  174. package/dist/components/combobox/index.js +37 -0
  175. package/dist/components/command-menu/command-menu-trigger.js +122 -0
  176. package/dist/components/command-menu/command-menu.js +433 -0
  177. package/dist/components/command-menu/command-menu.meta.js +279 -0
  178. package/dist/components/command-menu/index.js +21 -0
  179. package/dist/components/context-card/context-card.js +62 -0
  180. package/dist/components/context-card/context-card.meta.js +106 -0
  181. package/dist/components/context-card/index.js +17 -0
  182. package/dist/components/context-menu/context-menu.js +92 -0
  183. package/dist/components/context-menu/context-menu.meta.js +138 -0
  184. package/dist/components/context-menu/index.js +23 -0
  185. package/dist/components/data-table/data-table.js +142 -0
  186. package/dist/components/data-table/data-table.meta.js +146 -0
  187. package/dist/components/data-table/index.js +9 -0
  188. package/dist/components/date-picker/date-picker.js +196 -0
  189. package/dist/components/date-picker/date-picker.meta.js +164 -0
  190. package/dist/components/date-picker/index.js +7 -0
  191. package/dist/components/date-tile/date-tile.js +29 -0
  192. package/dist/components/date-tile/date-tile.meta.js +72 -0
  193. package/dist/components/date-tile/index.js +7 -0
  194. package/dist/components/destructive-action-modal/destructive-action-modal.js +130 -0
  195. package/dist/components/destructive-action-modal/destructive-action-modal.meta.js +136 -0
  196. package/dist/components/destructive-action-modal/index.js +9 -0
  197. package/dist/components/dialog/dialog.js +207 -0
  198. package/dist/components/dialog/dialog.meta.js +239 -0
  199. package/dist/components/dialog/index.js +45 -0
  200. package/dist/components/disclosure-picker/disclosure-picker.js +417 -0
  201. package/dist/components/disclosure-picker/disclosure-picker.meta.js +213 -0
  202. package/dist/components/disclosure-picker/index.js +21 -0
  203. package/dist/components/empty-state/empty-state.js +52 -0
  204. package/dist/components/empty-state/empty-state.meta.js +158 -0
  205. package/dist/components/empty-state/index.js +7 -0
  206. package/dist/components/entity/entity.js +70 -0
  207. package/dist/components/entity/entity.meta.js +108 -0
  208. package/dist/components/entity/entity.variants.js +16 -0
  209. package/dist/components/entity/index.js +7 -0
  210. package/dist/components/feedback/feedback.js +93 -0
  211. package/dist/components/feedback/feedback.meta.js +109 -0
  212. package/dist/components/feedback/index.js +7 -0
  213. package/dist/components/fieldset/fieldset.js +80 -0
  214. package/dist/components/fieldset/fieldset.meta.js +160 -0
  215. package/dist/components/fieldset/index.js +17 -0
  216. package/dist/components/file-dropzone/file-dropzone.js +193 -0
  217. package/dist/components/file-dropzone/file-dropzone.meta.js +210 -0
  218. package/dist/components/file-dropzone/file-dropzone.variants.js +26 -0
  219. package/dist/components/file-dropzone/index.js +13 -0
  220. package/dist/components/font-picker/font-picker.js +77 -0
  221. package/dist/components/font-picker/font-picker.meta.js +119 -0
  222. package/dist/components/font-picker/index.js +7 -0
  223. package/dist/components/form/form.js +145 -0
  224. package/dist/components/form/form.meta.js +142 -0
  225. package/dist/components/form/index.js +11 -0
  226. package/dist/components/gliding-highlight/gliding-highlight.js +50 -0
  227. package/dist/components/gliding-highlight/gliding-highlight.meta.js +135 -0
  228. package/dist/components/gliding-highlight/index.js +9 -0
  229. package/dist/components/gradient-art/gradient-art.js +168 -0
  230. package/dist/components/gradient-art/gradient-art.meta.js +81 -0
  231. package/dist/components/gradient-art/index.js +7 -0
  232. package/dist/components/gradient-art/renderer.js +336 -0
  233. package/dist/components/inline-status/index.js +7 -0
  234. package/dist/components/inline-status/inline-status.js +33 -0
  235. package/dist/components/inline-status/inline-status.meta.js +83 -0
  236. package/dist/components/inline-status/inline-status.variants.js +18 -0
  237. package/dist/components/input/index.js +7 -0
  238. package/dist/components/input/input.js +33 -0
  239. package/dist/components/input/input.meta.js +155 -0
  240. package/dist/components/kbd/index.js +8 -0
  241. package/dist/components/kbd/kbd.js +54 -0
  242. package/dist/components/kbd/kbd.meta.js +95 -0
  243. package/dist/components/label/index.js +7 -0
  244. package/dist/components/label/label.js +51 -0
  245. package/dist/components/label/label.meta.js +98 -0
  246. package/dist/components/line-chart/index.js +7 -0
  247. package/dist/components/line-chart/line-chart.js +10 -0
  248. package/dist/components/line-chart/line-chart.meta.js +222 -0
  249. package/dist/components/marker/index.js +7 -0
  250. package/dist/components/marker/marker.js +39 -0
  251. package/dist/components/marker/marker.meta.js +132 -0
  252. package/dist/components/marker/marker.variants.js +25 -0
  253. package/dist/components/marquee/index.js +7 -0
  254. package/dist/components/marquee/marquee.js +146 -0
  255. package/dist/components/marquee/marquee.meta.js +106 -0
  256. package/dist/components/media-image/index.js +7 -0
  257. package/dist/components/media-image/media-image.js +56 -0
  258. package/dist/components/media-image/media-image.meta.js +92 -0
  259. package/dist/components/media-tile/index.js +7 -0
  260. package/dist/components/media-tile/media-tile.js +135 -0
  261. package/dist/components/media-tile/media-tile.meta.js +133 -0
  262. package/dist/components/media-tile/media-tile.variants.js +48 -0
  263. package/dist/components/menu/index.js +33 -0
  264. package/dist/components/menu/menu.js +168 -0
  265. package/dist/components/menu/menu.meta.js +176 -0
  266. package/dist/components/message/index.js +7 -0
  267. package/dist/components/message/message.js +83 -0
  268. package/dist/components/message/message.meta.js +150 -0
  269. package/dist/components/message/message.variants.js +41 -0
  270. package/dist/components/message-scroller/index.js +9 -0
  271. package/dist/components/message-scroller/message-scroller.js +300 -0
  272. package/dist/components/message-scroller/message-scroller.meta.js +172 -0
  273. package/dist/components/meter/index.js +20 -0
  274. package/dist/components/meter/meter.js +112 -0
  275. package/dist/components/meter/meter.meta.js +227 -0
  276. package/dist/components/meter/meter.variants.js +61 -0
  277. package/dist/components/middle-truncate/index.js +7 -0
  278. package/dist/components/middle-truncate/middle-truncate.js +28 -0
  279. package/dist/components/middle-truncate/middle-truncate.meta.js +77 -0
  280. package/dist/components/note/index.js +9 -0
  281. package/dist/components/note/note.js +73 -0
  282. package/dist/components/note/note.meta.js +112 -0
  283. package/dist/components/note/note.variants.js +22 -0
  284. package/dist/components/notification-badge/index.js +15 -0
  285. package/dist/components/notification-badge/notification-badge.js +48 -0
  286. package/dist/components/notification-badge/notification-badge.meta.js +107 -0
  287. package/dist/components/notification-badge/notification-badge.variants.js +57 -0
  288. package/dist/components/number-field/index.js +7 -0
  289. package/dist/components/number-field/number-field.js +70 -0
  290. package/dist/components/number-field/number-field.meta.js +109 -0
  291. package/dist/components/otp-field/index.js +7 -0
  292. package/dist/components/otp-field/otp-field.js +70 -0
  293. package/dist/components/otp-field/otp-field.meta.js +197 -0
  294. package/dist/components/overflow-menu/index.js +7 -0
  295. package/dist/components/overflow-menu/overflow-menu.js +26 -0
  296. package/dist/components/overflow-menu/overflow-menu.meta.js +100 -0
  297. package/dist/components/page-header/index.js +7 -0
  298. package/dist/components/page-header/page-header.js +34 -0
  299. package/dist/components/page-header/page-header.meta.js +104 -0
  300. package/dist/components/page-loader/index.js +7 -0
  301. package/dist/components/page-loader/page-loader.js +37 -0
  302. package/dist/components/page-loader/page-loader.meta.js +85 -0
  303. package/dist/components/pagination/index.js +7 -0
  304. package/dist/components/pagination/pagination.js +105 -0
  305. package/dist/components/pagination/pagination.meta.js +141 -0
  306. package/dist/components/panel-group/index.js +10 -0
  307. package/dist/components/panel-group/panel-group.js +168 -0
  308. package/dist/components/panel-group/panel-group.meta.js +153 -0
  309. package/dist/components/panel-section/index.js +9 -0
  310. package/dist/components/panel-section/panel-section.js +115 -0
  311. package/dist/components/panel-section/panel-section.meta.js +156 -0
  312. package/dist/components/phone/index.js +7 -0
  313. package/dist/components/phone/phone.js +50 -0
  314. package/dist/{chunk-KFZ43RKU.js → components/phone/phone.meta.js} +3 -50
  315. package/dist/{chunk-NEQNXI2G.js → components/phone/status-icons.js} +4 -4
  316. package/dist/components/pie-chart/index.js +7 -0
  317. package/dist/components/pie-chart/pie-chart.js +191 -0
  318. package/dist/components/pie-chart/pie-chart.meta.js +210 -0
  319. package/dist/components/pill/index.js +9 -0
  320. package/dist/components/pill/pill.js +24 -0
  321. package/dist/components/pill/pill.meta.js +108 -0
  322. package/dist/components/pill/pill.variants.js +65 -0
  323. package/dist/components/popover/index.js +23 -0
  324. package/dist/components/popover/popover.js +100 -0
  325. package/dist/components/popover/popover.meta.js +136 -0
  326. package/dist/components/progress/index.js +19 -0
  327. package/dist/components/progress/progress.js +70 -0
  328. package/dist/components/progress/progress.meta.js +171 -0
  329. package/dist/components/progress/progress.variants.js +17 -0
  330. package/dist/components/radar-chart/index.js +7 -0
  331. package/dist/components/radar-chart/radar-chart.js +161 -0
  332. package/dist/components/radar-chart/radar-chart.meta.js +204 -0
  333. package/dist/components/radial-chart/index.js +7 -0
  334. package/dist/components/radial-chart/radial-chart.js +175 -0
  335. package/dist/components/radial-chart/radial-chart.meta.js +216 -0
  336. package/dist/components/radio/index.js +8 -0
  337. package/dist/components/radio/radio.js +39 -0
  338. package/dist/components/radio/radio.meta.js +104 -0
  339. package/dist/components/radio-card/index.js +7 -0
  340. package/dist/components/radio-card/radio-card.js +81 -0
  341. package/dist/components/radio-card/radio-card.meta.js +144 -0
  342. package/dist/components/radio-card/radio-card.variants.js +43 -0
  343. package/dist/components/relative-time/index.js +7 -0
  344. package/dist/components/relative-time/relative-time.js +47 -0
  345. package/dist/components/relative-time/relative-time.meta.js +77 -0
  346. package/dist/components/scroller/index.js +7 -0
  347. package/dist/components/scroller/scroller.js +111 -0
  348. package/dist/components/scroller/scroller.meta.js +118 -0
  349. package/dist/components/scrub-field/index.js +7 -0
  350. package/dist/components/scrub-field/scrub-field.js +124 -0
  351. package/dist/components/scrub-field/scrub-field.meta.js +139 -0
  352. package/dist/components/search-input/index.js +7 -0
  353. package/dist/components/search-input/search-input.js +91 -0
  354. package/dist/components/search-input/search-input.meta.js +129 -0
  355. package/dist/components/section-header/index.js +7 -0
  356. package/dist/components/section-header/section-header.js +39 -0
  357. package/dist/components/section-header/section-header.meta.js +174 -0
  358. package/dist/components/segmented-bar/index.js +14 -0
  359. package/dist/components/segmented-bar/segmented-bar.js +26 -0
  360. package/dist/components/segmented-bar/segmented-bar.meta.js +108 -0
  361. package/dist/components/segmented-bar/segmented-bar.variants.js +39 -0
  362. package/dist/components/select/index.js +25 -0
  363. package/dist/components/select/select.js +191 -0
  364. package/dist/components/select/select.meta.js +189 -0
  365. package/dist/components/separator/index.js +7 -0
  366. package/dist/components/separator/separator.js +42 -0
  367. package/dist/components/separator/separator.meta.js +84 -0
  368. package/dist/components/settings-menu/index.js +11 -0
  369. package/dist/components/settings-menu/settings-menu.js +101 -0
  370. package/dist/components/settings-menu/settings-menu.meta.js +177 -0
  371. package/dist/components/settings-menu/settings-menu.variants.js +15 -0
  372. package/dist/components/sheet/index.js +29 -0
  373. package/dist/components/sheet/sheet.js +121 -0
  374. package/dist/components/sheet/sheet.meta.js +167 -0
  375. package/dist/components/sheet/sheet.variants.js +21 -0
  376. package/dist/components/show-more/index.js +7 -0
  377. package/dist/components/show-more/show-more.js +87 -0
  378. package/dist/components/show-more/show-more.meta.js +79 -0
  379. package/dist/components/side-nav/index.js +13 -0
  380. package/dist/components/side-nav/side-nav.js +75 -0
  381. package/dist/components/side-nav/side-nav.meta.js +139 -0
  382. package/dist/components/side-nav/side-nav.variants.js +34 -0
  383. package/dist/components/sidebar/index.js +21 -0
  384. package/dist/components/sidebar/sidebar.js +196 -0
  385. package/dist/components/sidebar/sidebar.meta.js +118 -0
  386. package/dist/components/skeleton/index.js +7 -0
  387. package/dist/components/skeleton/skeleton.js +16 -0
  388. package/dist/components/skeleton/skeleton.meta.js +90 -0
  389. package/dist/components/slider/index.js +21 -0
  390. package/dist/components/slider/slider.js +115 -0
  391. package/dist/components/slider/slider.meta.js +214 -0
  392. package/dist/components/sparkline/index.js +7 -0
  393. package/dist/components/sparkline/sparkline.js +84 -0
  394. package/dist/components/sparkline/sparkline.meta.js +147 -0
  395. package/dist/components/spinner/index.js +7 -0
  396. package/dist/components/spinner/spinner.js +59 -0
  397. package/dist/components/spinner/spinner.meta.js +118 -0
  398. package/dist/components/status-bar/index.js +9 -0
  399. package/dist/components/status-bar/status-bar.js +40 -0
  400. package/dist/components/status-bar/status-bar.meta.js +117 -0
  401. package/dist/components/status-dot/index.js +9 -0
  402. package/dist/components/status-dot/status-dot.js +40 -0
  403. package/dist/components/status-dot/status-dot.meta.js +113 -0
  404. package/dist/components/status-dot/status-dot.variants.js +28 -0
  405. package/dist/components/stepper/index.js +17 -0
  406. package/dist/components/stepper/stepper.js +161 -0
  407. package/dist/components/stepper/stepper.meta.js +190 -0
  408. package/dist/components/stepper/stepper.variants.js +72 -0
  409. package/dist/components/streaming-text/index.js +7 -0
  410. package/dist/components/streaming-text/streaming-text.js +55 -0
  411. package/dist/components/streaming-text/streaming-text.meta.js +147 -0
  412. package/dist/components/switch/index.js +7 -0
  413. package/dist/components/switch/switch.js +26 -0
  414. package/dist/components/switch/switch.meta.js +133 -0
  415. package/dist/components/table/index.js +23 -0
  416. package/dist/components/table/table.js +117 -0
  417. package/dist/components/table/table.meta.js +143 -0
  418. package/dist/components/tabs/index.js +17 -0
  419. package/dist/components/tabs/tabs.js +58 -0
  420. package/dist/components/tabs/tabs.meta.js +120 -0
  421. package/dist/components/textarea/index.js +7 -0
  422. package/dist/components/textarea/textarea.js +38 -0
  423. package/dist/components/textarea/textarea.meta.js +117 -0
  424. package/dist/components/theme-selector/index.js +11 -0
  425. package/dist/components/theme-selector/theme-selector.js +145 -0
  426. package/dist/components/theme-selector/theme-selector.meta.js +181 -0
  427. package/dist/components/theme-switcher/index.js +7 -0
  428. package/dist/components/theme-switcher/theme-switcher.js +106 -0
  429. package/dist/components/theme-switcher/theme-switcher.meta.js +99 -0
  430. package/dist/components/thinking-orb/index.js +9 -0
  431. package/dist/components/thinking-orb/thinking-orb.js +126 -0
  432. package/dist/components/thinking-orb/thinking-orb.meta.js +142 -0
  433. package/dist/components/thinking-orb/thinking-orb.render.js +252 -0
  434. package/dist/components/toast/index.js +29 -0
  435. package/dist/components/toast/toast.js +254 -0
  436. package/dist/components/toast/toast.meta.js +261 -0
  437. package/dist/components/toggle/index.js +13 -0
  438. package/dist/components/toggle/toggle.js +51 -0
  439. package/dist/components/toggle/toggle.meta.js +129 -0
  440. package/dist/components/toolbar/index.js +27 -0
  441. package/dist/components/toolbar/toolbar.js +80 -0
  442. package/dist/components/toolbar/toolbar.meta.js +272 -0
  443. package/dist/components/toolbar/toolbar.variants.js +16 -0
  444. package/dist/components/tooltip/index.js +21 -0
  445. package/dist/components/tooltip/tooltip.js +74 -0
  446. package/dist/components/tooltip/tooltip.meta.js +156 -0
  447. package/dist/components/tree/index.js +12 -0
  448. package/dist/components/tree/tree.js +364 -0
  449. package/dist/components/tree/tree.meta.js +334 -0
  450. package/dist/components/video/index.js +7 -0
  451. package/dist/components/video/video.js +59 -0
  452. package/dist/components/video/video.meta.js +81 -0
  453. package/dist/components/workspace/index.js +9 -0
  454. package/dist/components/workspace/workspace.js +79 -0
  455. package/dist/components/workspace/workspace.meta.js +183 -0
  456. package/dist/foundations/accessibility.js +107 -0
  457. package/dist/foundations/index.js +25 -792
  458. package/dist/foundations/motion.js +135 -0
  459. package/dist/foundations/scrolling.js +62 -0
  460. package/dist/foundations/shape.js +113 -0
  461. package/dist/foundations/spacing.js +121 -0
  462. package/dist/foundations/surfaces.js +107 -0
  463. package/dist/foundations/types.js +0 -0
  464. package/dist/foundations/typography.js +152 -0
  465. package/dist/icon/Icon.js +30 -0
  466. package/dist/icon/IconProvider.js +27 -0
  467. package/dist/icon/compose.js +13 -0
  468. package/dist/icon/index.d.ts +13 -5
  469. package/dist/icon/index.js +13 -2
  470. package/dist/icon/registry.js +0 -0
  471. package/dist/icon-sets/brands.generated.js +123 -0
  472. package/dist/icon-sets/brands.js +10 -123
  473. package/dist/icon-sets/reicon.d.ts +3 -1
  474. package/dist/icon-sets/reicon.js +209 -1
  475. package/dist/index.d.ts +618 -34
  476. package/dist/index.js +211 -11351
  477. package/dist/ios/chrome.js +36 -0
  478. package/dist/ios/index.js +19 -315
  479. package/dist/ios/liquid-glass.js +103 -0
  480. package/dist/ios/native-app.js +46 -0
  481. package/dist/ios/navigation.js +63 -0
  482. package/dist/ios/phone-frame.js +64 -0
  483. package/dist/ios/preview-theme.js +83 -0
  484. package/dist/ios/preview.js +10 -137
  485. package/dist/ios/sheet.js +85 -0
  486. package/dist/ios/theme.js +19 -0
  487. package/dist/layout/AspectBox.js +27 -0
  488. package/dist/layout/Bleed.js +15 -0
  489. package/dist/layout/Center.js +21 -0
  490. package/dist/layout/Columns.js +70 -0
  491. package/dist/layout/Grid.js +50 -0
  492. package/dist/layout/GridOverlay.js +41 -0
  493. package/dist/layout/Page.js +11 -0
  494. package/dist/layout/Region.js +39 -0
  495. package/dist/layout/Row.js +45 -0
  496. package/dist/layout/SafeArea.js +26 -0
  497. package/dist/layout/Spacer.js +9 -0
  498. package/dist/layout/SplitPane.js +55 -0
  499. package/dist/layout/Stack.js +42 -0
  500. package/dist/layout/_responsive.js +16 -0
  501. package/dist/layout/_safeArea.js +18 -0
  502. package/dist/layout/index.d.ts +30 -8
  503. package/dist/layout/index.js +14 -2
  504. package/dist/lib/anchored-scroll.js +7 -0
  505. package/dist/lib/bleed.js +7 -0
  506. package/dist/lib/chart/cartesian.js +365 -0
  507. package/dist/lib/chart/chart-frame.js +163 -0
  508. package/dist/lib/chart/chart-legend.js +13 -0
  509. package/dist/lib/chart/chart-tooltip.js +38 -0
  510. package/dist/lib/chart/format.js +24 -0
  511. package/dist/lib/chart/geometry.js +114 -0
  512. package/dist/lib/chart/motion.js +34 -0
  513. package/dist/lib/chart/scale.js +72 -0
  514. package/dist/lib/chart/types.js +45 -0
  515. package/dist/lib/chart/use-arrival.js +41 -0
  516. package/dist/{chunk-SRQWQUTW.js → lib/cn.js} +5 -5
  517. package/dist/lib/component-guidance.js +215 -0
  518. package/dist/lib/density.js +54 -0
  519. package/dist/lib/field-shell.js +11 -0
  520. package/dist/lib/glyphs.js +9 -0
  521. package/dist/lib/heading-row.js +36 -0
  522. package/dist/lib/highlight-glide.js +84 -0
  523. package/dist/lib/hit-target.js +5 -0
  524. package/dist/lib/meta.js +0 -0
  525. package/dist/lib/portal-theme-scope.js +74 -0
  526. package/dist/{chunk-FKZXAFIY.js → lib/presentation.js} +8 -3
  527. package/dist/lib/refs.js +14 -0
  528. package/dist/lib/scrub-gesture.js +50 -0
  529. package/dist/lib/segmented.js +13 -0
  530. package/dist/lib/selection-card.js +41 -0
  531. package/dist/lib/status-tone.js +13 -0
  532. package/dist/lib/taxonomy.js +214 -0
  533. package/dist/lib/trim-label.js +20 -0
  534. package/dist/lib/use-copy.js +27 -0
  535. package/dist/lib/use-edge-fade.js +32 -0
  536. package/dist/lib/use-isomorphic-layout-effect.js +8 -0
  537. package/dist/lib/use-resize-observer.js +18 -0
  538. package/dist/lib/use-scroll-activity.js +52 -0
  539. package/dist/lib/use-wheel-to-horizontal.js +65 -0
  540. package/dist/motion/MotionProvider.js +75 -0
  541. package/dist/motion/Presence.js +112 -0
  542. package/dist/motion/Reveal.js +42 -0
  543. package/dist/motion/TextReveal.js +61 -0
  544. package/dist/motion/index.js +24 -0
  545. package/dist/motion/useInView.js +36 -0
  546. package/dist/motion/useReducedMotion.js +25 -0
  547. package/dist/motion/viewTransition.js +47 -0
  548. package/dist/patterns/auth-page.js +90 -0
  549. package/dist/patterns/auth-page.meta.js +27 -0
  550. package/dist/patterns/brand-landing-page.js +341 -0
  551. package/dist/patterns/brand-landing-page.meta.js +28 -0
  552. package/dist/patterns/chat-panel.js +185 -0
  553. package/dist/patterns/chat-panel.meta.js +31 -0
  554. package/dist/patterns/dashboard-page.js +332 -0
  555. package/dist/patterns/dashboard-page.meta.js +29 -0
  556. package/dist/patterns/feed-page.js +205 -0
  557. package/dist/patterns/feed-page.meta.js +25 -0
  558. package/dist/patterns/index.js +34 -2140
  559. package/dist/patterns/landing-page.js +356 -0
  560. package/dist/patterns/landing-page.meta.js +26 -0
  561. package/dist/patterns/list-detail-page.js +373 -0
  562. package/dist/patterns/list-detail-page.meta.js +24 -0
  563. package/dist/patterns/settings-page.js +268 -0
  564. package/dist/patterns/settings-page.meta.js +27 -0
  565. package/dist/presets/index.d.ts +7 -1
  566. package/dist/presets/index.js +53 -185
  567. package/dist/styles.css +118 -3
  568. package/dist/{theme-provider-kQszHYji.d.ts → theme-provider-S0NVJs2Y.d.ts} +6 -1
  569. package/dist/{chunk-NETUFI34.js → themes/_contract.js} +14 -2
  570. package/dist/themes/atelier/index.js +17 -1
  571. package/dist/themes/contrast.js +288 -0
  572. package/dist/themes/ember/ember.css +6 -6
  573. package/dist/themes/ember/index.js +16 -1
  574. package/dist/themes/index.d.ts +1 -1
  575. package/dist/themes/index.js +3 -8
  576. package/dist/themes/meridian/index.js +16 -1
  577. package/dist/themes/poppy/index.js +17 -1
  578. package/dist/themes/prism/index.js +17 -1
  579. package/dist/themes/prism/prism.css +2 -2
  580. package/dist/themes/registry.js +59 -0
  581. package/dist/themes/sable/index.js +16 -1
  582. package/dist/{chunk-EFLC4NA3.js → themes/theme-provider.js} +38 -54
  583. package/dist/themes/verdant/index.js +17 -1
  584. package/llms/blocks/media-player-block.md +20 -7
  585. package/llms/blocks/product-card-block.md +6 -4
  586. package/llms/blocks/task-list-block.md +1 -1
  587. package/llms/blocks/traffic-sources-block.md +1 -1
  588. package/llms/blocks/traffic-trend-block.md +5 -3
  589. package/llms/blocks/verify-code-block.md +1 -1
  590. package/llms/components/app-shell.md +5 -2
  591. package/llms/components/avatar.md +25 -3
  592. package/llms/components/button.md +20 -1
  593. package/llms/components/card.md +1 -1
  594. package/llms/components/disclosure-picker.md +168 -0
  595. package/llms/components/font-picker.md +104 -0
  596. package/llms/components/media-image.md +98 -0
  597. package/llms/components/media-tile.md +143 -0
  598. package/llms/components/page-header.md +6 -5
  599. package/llms/components/pie-chart.md +2 -2
  600. package/llms/components/radial-chart.md +1 -1
  601. package/llms/components/section-header.md +144 -0
  602. package/llms/components/sheet.md +10 -0
  603. package/llms/components/sidebar.md +4 -3
  604. package/llms/components/slider.md +14 -2
  605. package/llms/components/theme-selector.md +44 -4
  606. package/llms/components/tree.md +3 -3
  607. package/llms/layout/grid.md +24 -3
  608. package/llms/layout/region.md +16 -3
  609. package/llms/patterns/dashboard-page.md +3 -6
  610. package/llms/patterns/feed-page.md +4 -4
  611. package/llms/patterns/list-detail-page.md +1 -0
  612. package/llms/patterns/settings-page.md +2 -5
  613. package/llms/reference/utilities.md +84 -4
  614. package/llms/tasks/building-a-page.md +34 -3
  615. package/llms/tasks/converting-an-app.md +14 -4
  616. package/llms/tasks/creating-a-preset.md +4 -1
  617. package/llms/tasks/reviewing-a-design.md +19 -0
  618. package/llms/tasks/using-presets.md +19 -0
  619. package/llms-full.txt +1066 -78
  620. package/llms.txt +26 -9
  621. package/package.json +1 -1
  622. package/registry.json +2342 -164
  623. package/scripts/agent-setup.mjs +90 -0
  624. package/scripts/design-presets.mjs +59 -6
  625. package/scripts/grade.mjs +195 -29
  626. package/scripts/lint-rules.mjs +486 -10
  627. package/scripts/review-evidence.mjs +28 -1
  628. package/skills/sable/SKILL.md +67 -24
  629. package/targets/ios.json +45 -0
  630. package/dist/chunk-3IWZYBGH.js +0 -398
  631. package/dist/chunk-7MG4SHYX.js +0 -15
  632. package/dist/chunk-7QSDYBXO.js +0 -7421
  633. package/dist/chunk-ADLLDWLW.js +0 -15
  634. package/dist/chunk-C4Z3CF54.js +0 -15
  635. package/dist/chunk-EDXLM7YL.js +0 -5078
  636. package/dist/chunk-EHH4MHO6.js +0 -14
  637. package/dist/chunk-K7RUHUGC.js +0 -14
  638. package/dist/chunk-KO3NAEBF.js +0 -15
  639. package/dist/chunk-L4IEIQQA.js +0 -14
  640. package/dist/chunk-QJ6FWTUG.js +0 -40
  641. package/dist/chunk-VVW4UCDI.js +0 -4908
  642. package/dist/chunk-XAZGMY73.js +0 -187
@@ -0,0 +1,300 @@
1
+ "use client";
2
+
3
+ // src/components/message-scroller/message-scroller.tsx
4
+ import { useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
5
+ import { Icon } from "../../icon/index.js";
6
+ import { cn } from "../../lib/cn.js";
7
+ import { useDensity } from "../../lib/density.js";
8
+ import { useIsomorphicLayoutEffect } from "../../lib/use-isomorphic-layout-effect.js";
9
+ import { useScrollActivity } from "../../lib/use-scroll-activity.js";
10
+ import { useMotion } from "../../motion/MotionProvider.js";
11
+ import { Button } from "../button/index.js";
12
+ import { SimpleTooltip } from "../tooltip/index.js";
13
+ import { jsx, jsxs } from "react/jsx-runtime";
14
+ var DEFAULT_FOLLOW_THRESHOLD = 64;
15
+ var GAP_CLASSES = {
16
+ comfortable: {
17
+ sm: "gap-2 [--message-gap:calc(var(--spacing)*2)]",
18
+ md: "gap-4 [--message-gap:calc(var(--spacing)*4)]",
19
+ lg: "gap-6 [--message-gap:calc(var(--spacing)*6)]"
20
+ },
21
+ compact: {
22
+ sm: "gap-1.5 [--message-gap:calc(var(--spacing)*1.5)]",
23
+ md: "gap-3 [--message-gap:calc(var(--spacing)*3)]",
24
+ lg: "gap-4 [--message-gap:calc(var(--spacing)*4)]"
25
+ }
26
+ };
27
+ function MessageScroller({
28
+ ref,
29
+ autoFollow = true,
30
+ followThreshold = DEFAULT_FOLLOW_THRESHOLD,
31
+ onFollowChange,
32
+ initialScroll = "bottom",
33
+ jumpToLatest = true,
34
+ jumpToLatestLabel = "Jump to latest",
35
+ gap = "md",
36
+ onVisibleMessagesChange,
37
+ className,
38
+ children,
39
+ onScroll,
40
+ ...props
41
+ }) {
42
+ const viewportRef = useRef(null);
43
+ const contentRef = useRef(null);
44
+ const { enabled: motionEnabled } = useMotion();
45
+ const density = useDensity();
46
+ const trackActivity = useScrollActivity();
47
+ const setViewport = useCallback(
48
+ (node) => {
49
+ trackActivity(node);
50
+ viewportRef.current = node;
51
+ },
52
+ [trackActivity]
53
+ );
54
+ const [atBottom, setAtBottom] = useState(true);
55
+ const followingRef = useRef(autoFollow);
56
+ followingRef.current = autoFollow && atBottom;
57
+ const thresholdRef = useRef(followThreshold);
58
+ thresholdRef.current = followThreshold;
59
+ const scrollBehavior = useCallback(
60
+ (animate) => animate !== false && motionEnabled ? "smooth" : "auto",
61
+ [motionEnabled]
62
+ );
63
+ const anchor = useRef({
64
+ node: null,
65
+ top: 0
66
+ });
67
+ const captureAnchor = useCallback(() => {
68
+ const content = contentRef.current;
69
+ if (!content) return;
70
+ const node = content.querySelector("[data-message-id]") ?? content.firstElementChild;
71
+ anchor.current = { node, top: node ? node.offsetTop : 0 };
72
+ }, []);
73
+ const scrollToBottomNow = useCallback((behavior) => {
74
+ const viewport = viewportRef.current;
75
+ if (!viewport) return;
76
+ viewport.scrollTo({ top: viewport.scrollHeight, behavior });
77
+ }, []);
78
+ const observer = useRef(null);
79
+ const observed = useRef(/* @__PURE__ */ new Map());
80
+ const visible = useRef(/* @__PURE__ */ new Set());
81
+ const reported = useRef("");
82
+ const onVisibleRef = useRef(onVisibleMessagesChange);
83
+ onVisibleRef.current = onVisibleMessagesChange;
84
+ const reportVisible = useCallback(() => {
85
+ const content = contentRef.current;
86
+ const notify = onVisibleRef.current;
87
+ if (!content || !notify) return;
88
+ const ids = [];
89
+ for (const node of content.querySelectorAll("[data-message-id]")) {
90
+ const id = node.dataset.messageId;
91
+ if (id && visible.current.has(id)) ids.push(id);
92
+ }
93
+ const key = ids.join("\0");
94
+ if (key === reported.current) return;
95
+ reported.current = key;
96
+ notify(ids);
97
+ }, []);
98
+ const syncObservedMessages = useCallback(() => {
99
+ const io = observer.current;
100
+ const content = contentRef.current;
101
+ if (!io || !content) return;
102
+ const nodes = new Set(
103
+ content.querySelectorAll("[data-message-id]")
104
+ );
105
+ for (const [node, id] of observed.current) {
106
+ if (nodes.has(node)) continue;
107
+ io.unobserve(node);
108
+ observed.current.delete(node);
109
+ visible.current.delete(id);
110
+ }
111
+ for (const node of nodes) {
112
+ if (observed.current.has(node)) continue;
113
+ const id = node.dataset.messageId;
114
+ if (!id) continue;
115
+ observed.current.set(node, id);
116
+ io.observe(node);
117
+ }
118
+ reportVisible();
119
+ }, [reportVisible]);
120
+ const onContentChange = useCallback(() => {
121
+ const viewport = viewportRef.current;
122
+ const content = contentRef.current;
123
+ if (!viewport || !content) return;
124
+ if (followingRef.current) {
125
+ scrollToBottomNow("auto");
126
+ } else {
127
+ const { node, top } = anchor.current;
128
+ if (node?.isConnected && node.parentElement === content) {
129
+ const shift = node.offsetTop - top;
130
+ if (shift !== 0) viewport.scrollTop += shift;
131
+ }
132
+ }
133
+ captureAnchor();
134
+ syncObservedMessages();
135
+ }, [captureAnchor, scrollToBottomNow, syncObservedMessages]);
136
+ useEffect(() => {
137
+ const viewport = viewportRef.current;
138
+ const content = contentRef.current;
139
+ if (!viewport || !content) return;
140
+ const mutations = new MutationObserver(onContentChange);
141
+ mutations.observe(content, {
142
+ childList: true,
143
+ subtree: true,
144
+ characterData: true
145
+ });
146
+ const resizes = new ResizeObserver(onContentChange);
147
+ resizes.observe(content);
148
+ return () => {
149
+ mutations.disconnect();
150
+ resizes.disconnect();
151
+ };
152
+ }, [onContentChange]);
153
+ useEffect(() => {
154
+ if (!onVisibleMessagesChange) return;
155
+ const viewport = viewportRef.current;
156
+ if (!viewport) return;
157
+ observer.current = new IntersectionObserver(
158
+ (entries) => {
159
+ for (const entry of entries) {
160
+ const id = entry.target.dataset.messageId;
161
+ if (!id) continue;
162
+ if (entry.isIntersecting) visible.current.add(id);
163
+ else visible.current.delete(id);
164
+ }
165
+ reportVisible();
166
+ },
167
+ { root: viewport }
168
+ );
169
+ syncObservedMessages();
170
+ return () => {
171
+ observer.current?.disconnect();
172
+ observer.current = null;
173
+ observed.current.clear();
174
+ visible.current.clear();
175
+ reported.current = "";
176
+ };
177
+ }, [onVisibleMessagesChange, reportVisible, syncObservedMessages]);
178
+ useIsomorphicLayoutEffect(() => {
179
+ const viewport = viewportRef.current;
180
+ if (!viewport) return;
181
+ if (typeof initialScroll === "object") {
182
+ const target = viewport.querySelector(
183
+ `[data-message-id="${CSS.escape(initialScroll.messageId)}"]`
184
+ );
185
+ if (target) {
186
+ target.scrollIntoView({ block: "center", behavior: "auto" });
187
+ } else {
188
+ viewport.scrollTop = viewport.scrollHeight;
189
+ }
190
+ } else if (initialScroll === "top") {
191
+ viewport.scrollTop = 0;
192
+ } else {
193
+ viewport.scrollTop = viewport.scrollHeight;
194
+ }
195
+ const distance = viewport.scrollHeight - viewport.scrollTop - viewport.clientHeight;
196
+ setAtBottom(distance <= thresholdRef.current);
197
+ captureAnchor();
198
+ }, []);
199
+ const setFollowing = useCallback(
200
+ (next) => {
201
+ setAtBottom((prev) => {
202
+ if (prev === next) return prev;
203
+ onFollowChange?.(next && autoFollow);
204
+ return next;
205
+ });
206
+ },
207
+ [autoFollow, onFollowChange]
208
+ );
209
+ const handleScroll = useCallback(
210
+ (event) => {
211
+ const el = event.currentTarget;
212
+ const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
213
+ setFollowing(distance <= thresholdRef.current);
214
+ captureAnchor();
215
+ onScroll?.(event);
216
+ },
217
+ [captureAnchor, onScroll, setFollowing]
218
+ );
219
+ useImperativeHandle(
220
+ ref,
221
+ () => ({
222
+ get element() {
223
+ return viewportRef.current;
224
+ },
225
+ scrollToBottom: (options) => {
226
+ scrollToBottomNow(scrollBehavior(options?.animate));
227
+ },
228
+ scrollToTop: (options) => {
229
+ viewportRef.current?.scrollTo({
230
+ top: 0,
231
+ behavior: scrollBehavior(options?.animate)
232
+ });
233
+ },
234
+ scrollToMessage: (id, options) => {
235
+ const viewport = viewportRef.current;
236
+ if (!viewport) return false;
237
+ const target = viewport.querySelector(
238
+ `[data-message-id="${CSS.escape(id)}"]`
239
+ );
240
+ if (!target) return false;
241
+ target.scrollIntoView({
242
+ block: options?.block ?? "center",
243
+ behavior: scrollBehavior(options?.animate)
244
+ });
245
+ return true;
246
+ },
247
+ isFollowing: () => followingRef.current
248
+ }),
249
+ [scrollBehavior, scrollToBottomNow]
250
+ );
251
+ const showJump = jumpToLatest && !atBottom;
252
+ return /* @__PURE__ */ jsxs(
253
+ "div",
254
+ {
255
+ ref: setViewport,
256
+ onScroll: handleScroll,
257
+ className: cn(
258
+ // `relative` is load-bearing twice over: it makes the viewport the
259
+ // offsetParent the prepend anchor is measured against, and it is the
260
+ // containing block the jump control sticks inside.
261
+ "relative scrollbar-quiet overflow-y-auto overscroll-contain",
262
+ className
263
+ ),
264
+ ...props,
265
+ children: [
266
+ /* @__PURE__ */ jsx(
267
+ "div",
268
+ {
269
+ ref: contentRef,
270
+ className: cn("flex flex-col", GAP_CLASSES[density][gap]),
271
+ children
272
+ }
273
+ ),
274
+ showJump ? (
275
+ /* Sticky rather than absolutely positioned over a wrapper — that is
276
+ what lets `className` stay on the scrolling element instead of
277
+ moving to a wrapper the consumer then has to reach past. A
278
+ zero-height last child pins to the bottom edge while the reader is
279
+ scrolled up and costs no scroll height. */
280
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none sticky bottom-4 flex h-0 items-end justify-center", children: /* @__PURE__ */ jsx(SimpleTooltip, { content: jumpToLatestLabel, children: /* @__PURE__ */ jsx(
281
+ Button,
282
+ {
283
+ type: "button",
284
+ variant: "floating",
285
+ size: "icon-sm",
286
+ "aria-label": jumpToLatestLabel,
287
+ onClick: () => scrollToBottomNow(scrollBehavior(true)),
288
+ className: "pointer-events-auto animate-fade-up",
289
+ children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", className: "text-base" })
290
+ }
291
+ ) }) })
292
+ ) : null
293
+ ]
294
+ }
295
+ );
296
+ }
297
+ MessageScroller.displayName = "MessageScroller";
298
+ export {
299
+ MessageScroller
300
+ };
@@ -0,0 +1,172 @@
1
+ // src/components/message-scroller/message-scroller.meta.ts
2
+ var messageScrollerMeta = {
3
+ name: "MessageScroller",
4
+ summary: "Scroll container for a conversation. Auto-follows new messages until the reader scrolls away, holds position when older history is prepended, and exposes scroll commands and visibility tracking through its ref.",
5
+ status: "stable",
6
+ keywords: [
7
+ "chat",
8
+ "conversation",
9
+ "messages",
10
+ "thread",
11
+ "transcript",
12
+ "stick to bottom",
13
+ "auto scroll",
14
+ "streaming",
15
+ "infinite scroll",
16
+ "inbox",
17
+ "ai chat",
18
+ "support chat"
19
+ ],
20
+ usage: {
21
+ description: "The scroll region a conversation lives in. It owns the scrolling and nothing else \u2014 not your messages, not your AI state, not your transport or persistence \u2014 so you bring the content renderer and it handles the behaviors that make streaming chat feel right: pinning to the newest message, releasing when the reader scrolls up, keeping the view still when older history loads above, jumping to a specific message, restoring a saved read position, and reporting what is actually on screen.",
22
+ bestPractices: [
23
+ {
24
+ guidance: "do",
25
+ description: "Bound it the way you would bound any scroll box \u2014 `flex-1 min-h-0` inside a flex column, or `max-h-96`. `className` lands on the element that actually scrolls, so the obvious bound is the correct one (same contract as Scroller)."
26
+ },
27
+ {
28
+ guidance: "do",
29
+ description: "Give every Message a `messageId`. It is the handle for `scrollToMessage`, `initialScroll`, and `onVisibleMessagesChange` \u2014 a message without one is invisible to all three."
30
+ },
31
+ {
32
+ guidance: "do",
33
+ description: "Prepend older history directly into `children` when the reader reaches the top. The scroller anchors on the first rendered message and re-adds the height that appeared above it, so the view does not jump."
34
+ },
35
+ {
36
+ guidance: "do",
37
+ description: "Set the rhythm between messages with the `gap` prop, not with a flex class on `className` \u2014 the messages are laid out in a column inside the scroll region, not directly on it."
38
+ },
39
+ {
40
+ guidance: "do",
41
+ description: "Restore a reopened thread with `initialScroll={{ messageId: lastRead }}` instead of dropping the reader at the bottom of a conversation they have not finished."
42
+ },
43
+ {
44
+ guidance: "do",
45
+ description: 'Wrap a docked agent panel in `<Density value="compact">`. The scroller tightens its rhythm and every message inside it drops to the workspace type tier \u2014 one attribute for the whole conversation, no per-component sizing.'
46
+ },
47
+ {
48
+ guidance: "dont",
49
+ description: "Do not call `scrollToBottom` on every incoming token. Auto-follow already does it, and doing it yourself fights the reader who scrolled up to read something."
50
+ },
51
+ {
52
+ guidance: "dont",
53
+ description: "Do not expect `ref` to be the DOM node \u2014 it is a command handle (`scrollToBottom`, `scrollToMessage`, `isFollowing`). Reach for `ref.current.element` when you genuinely need the element."
54
+ },
55
+ {
56
+ guidance: "dont",
57
+ description: "Do not wrap it in a positioned div to place a jump-to-latest button. It ships one, stuck to the bottom edge from inside the scroll region, which is why `className` gets to stay on the scrolling element."
58
+ },
59
+ {
60
+ guidance: "dont",
61
+ description: "Do not use it for an ordinary long list. That is `Scroller` \u2014 this one's follow-the-bottom behavior is wrong for content the reader is browsing rather than receiving."
62
+ }
63
+ ],
64
+ anatomy: [
65
+ {
66
+ name: "Scroll region",
67
+ required: true,
68
+ description: "The element that scrolls. Carries `className`: sizing, padding, and background."
69
+ },
70
+ {
71
+ name: "Message column",
72
+ required: true,
73
+ description: "The flex column holding the children, spaced by `gap`. Publishes `--message-gap` so `<Message grouped>` can close it."
74
+ },
75
+ {
76
+ name: "Jump to latest",
77
+ required: false,
78
+ description: "A control stuck to the bottom edge, shown only while the reader is scrolled away from the newest message."
79
+ }
80
+ ]
81
+ },
82
+ related: {
83
+ components: ["Message", "Bubble", "Marker", "Attachment", "Scroller"]
84
+ },
85
+ props: [
86
+ {
87
+ name: "ref",
88
+ type: "Ref<MessageScrollerHandle>",
89
+ description: "Imperative commands, not the DOM node: `scrollToBottom(opts)`, `scrollToTop(opts)`, `scrollToMessage(id, opts)` (returns false when the message is not rendered), `isFollowing()`, and `element` for the scrolling node itself."
90
+ },
91
+ {
92
+ name: "autoFollow",
93
+ type: "boolean",
94
+ default: "true",
95
+ description: "Keep the newest message in view as content arrives, until the reader scrolls away from the bottom. Set false for a transcript that must never move under the reader."
96
+ },
97
+ {
98
+ name: "followThreshold",
99
+ type: "number",
100
+ default: "64",
101
+ description: "Distance from the bottom, in px, that still counts as following. A band rather than a pixel, so a token arriving mid-frame does not flicker the state."
102
+ },
103
+ {
104
+ name: "onFollowChange",
105
+ type: "(following: boolean) => void",
106
+ description: "Notified when the viewport pins to, or releases from, the newest message."
107
+ },
108
+ {
109
+ name: "initialScroll",
110
+ type: '"bottom" | "top" | { messageId: string }',
111
+ default: '"bottom"',
112
+ description: "Where a freshly mounted thread lands. Pass a messageId to restore a saved read position. Applied once, on mount \u2014 changing it later will not yank a reader mid-conversation."
113
+ },
114
+ {
115
+ name: "jumpToLatest",
116
+ type: "boolean",
117
+ default: "true",
118
+ description: "Show the jump-to-latest control while the reader is scrolled away from the newest message."
119
+ },
120
+ {
121
+ name: "jumpToLatestLabel",
122
+ type: "string",
123
+ default: '"Jump to latest"',
124
+ description: "Accessible label and tooltip for that control."
125
+ },
126
+ {
127
+ name: "gap",
128
+ type: '"sm" | "md" | "lg"',
129
+ default: '"md"',
130
+ description: "Vertical rhythm between messages. Also published as `--message-gap`, which `<Message grouped>` reads to collapse the gap within a run."
131
+ },
132
+ {
133
+ name: "onVisibleMessagesChange",
134
+ type: "(ids: string[]) => void",
135
+ description: "Ids of the messages currently intersecting the viewport, in DOM order. The hook for read receipts, mark-as-seen, and unread counters."
136
+ },
137
+ {
138
+ name: "...div props",
139
+ type: 'Omit<ComponentPropsWithRef<"div">, "ref">',
140
+ description: "Spread onto the scrolling element. `className` bounds and pads the scroll region; `onScroll` composes with the component's own."
141
+ }
142
+ ],
143
+ variants: { gap: ["sm", "md", "lg"] },
144
+ tokensUsed: ["border", "secondary", "secondary-foreground", "ring"],
145
+ a11y: [
146
+ "Native overflow, so keyboard scrolling (arrows, Page Up/Down, Home/End) and the OS scrollbar work unchanged; the scrollbar is styled thin, not replaced.",
147
+ "Overscroll is contained, so a wheel gesture that runs out of conversation does not start scrolling the page behind it.",
148
+ "The jump-to-latest control is a real button with an accessible label, reachable by keyboard, and only present when there is somewhere to jump to.",
149
+ "Smooth scrolling is used only when motion is enabled \u2014 `prefers-reduced-motion` and <MotionProvider> off both collapse every scroll command to an instant jump."
150
+ ],
151
+ examples: [
152
+ {
153
+ label: "Streaming conversation",
154
+ code: '<MessageScroller className="flex-1 min-h-0 px-4 py-6">{messages.map((m) => (<Message key={m.id} messageId={m.id} align={m.mine ? "end" : "start"}><Bubble variant={m.mine ? "primary" : "muted"} align={m.mine ? "end" : "start"}>{m.body}</Bubble></Message>))}{pending ? <Marker icon="spinner" spin shimmer>Thinking\u2026</Marker> : null}</MessageScroller>'
155
+ },
156
+ {
157
+ label: "Scroll to a message on demand",
158
+ code: 'function Thread({ messages, replyTo }) {\n const thread = useRef(null)\n return (\n <>\n <Button onClick={() => thread.current?.scrollToMessage(replyTo)}>Show original</Button>\n <MessageScroller ref={thread} className="max-h-96">\n {messages.map((m) => (<Message key={m.id} messageId={m.id}><Bubble>{m.body}</Bubble></Message>))}\n </MessageScroller>\n </>\n )\n}'
159
+ },
160
+ {
161
+ label: "Restore a saved read position and track receipts",
162
+ code: '<MessageScroller className="h-96" initialScroll={{ messageId: lastRead }} onVisibleMessagesChange={(ids) => markSeen(ids)}>{messages.map((m) => (<Message key={m.id} messageId={m.id}><Bubble>{m.body}</Bubble></Message>))}</MessageScroller>'
163
+ },
164
+ {
165
+ label: "Prepend older history without moving the view",
166
+ code: '<MessageScroller className="h-96" gap="sm">{hasMore ? <Button variant="secondary" loadingLabel="Loading\u2026" onClick={loadOlder}>Load earlier messages</Button> : null}{messages.map((m) => (<Message key={m.id} messageId={m.id}><Bubble>{m.body}</Bubble></Message>))}</MessageScroller>'
167
+ }
168
+ ]
169
+ };
170
+ export {
171
+ messageScrollerMeta
172
+ };
@@ -0,0 +1,20 @@
1
+ // src/components/meter/index.ts
2
+ import {
3
+ Meter,
4
+ MeterIndicator,
5
+ MeterLabel,
6
+ MeterTrack,
7
+ MeterValue
8
+ } from "./meter.js";
9
+ import { meterIndicatorVariants, meterTrackVariants } from "./meter.variants.js";
10
+ import { meterMeta } from "./meter.meta.js";
11
+ export {
12
+ Meter,
13
+ MeterIndicator,
14
+ MeterLabel,
15
+ MeterTrack,
16
+ MeterValue,
17
+ meterIndicatorVariants,
18
+ meterMeta,
19
+ meterTrackVariants
20
+ };
@@ -0,0 +1,112 @@
1
+ // src/components/meter/meter.tsx
2
+ import { Meter as Base } from "@base-ui/react/meter";
3
+ import { createContext, useContext } from "react";
4
+ import { cn } from "../../lib/cn.js";
5
+ import {
6
+ meterIndicatorVariants,
7
+ meterRingValueVariants,
8
+ meterRingVariants,
9
+ meterTrackVariants
10
+ } from "./meter.variants.js";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ var ToneContext = createContext("primary");
13
+ var SizeContext = createContext(void 0);
14
+ var RING_TONE_STROKE = {
15
+ primary: "var(--primary)",
16
+ standard: "var(--tone-standard)",
17
+ success: "var(--success)",
18
+ warning: "var(--tone-warning)",
19
+ destructive: "var(--destructive)"
20
+ };
21
+ function MeterRing({
22
+ value,
23
+ min = 0,
24
+ max = 100,
25
+ strokeWidth,
26
+ showValue,
27
+ tone,
28
+ size
29
+ }) {
30
+ const ratio = value == null || max === min ? 0 : Math.min(1, Math.max(0, (value - min) / (max - min)));
31
+ const radius = 50 - strokeWidth;
32
+ const circumference = 2 * Math.PI * radius;
33
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
34
+ /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 100 100", className: "size-full", "aria-hidden": "true", focusable: "false", children: [
35
+ /* @__PURE__ */ jsx("circle", { cx: 50, cy: 50, r: radius, fill: "none", strokeWidth, style: { stroke: "var(--secondary)" } }),
36
+ /* @__PURE__ */ jsx(
37
+ "circle",
38
+ {
39
+ cx: 50,
40
+ cy: 50,
41
+ r: radius,
42
+ fill: "none",
43
+ strokeWidth,
44
+ strokeLinecap: "round",
45
+ strokeDasharray: circumference,
46
+ strokeDashoffset: circumference * (1 - ratio),
47
+ transform: "rotate(-90 50 50)",
48
+ className: "transition-[stroke-dashoffset] duration-(--motion-duration-slow) ease-decelerate",
49
+ style: { stroke: RING_TONE_STROKE[tone] }
50
+ }
51
+ )
52
+ ] }),
53
+ showValue ? /* @__PURE__ */ jsx(MeterValue, { className: meterRingValueVariants({ size }) }) : null
54
+ ] });
55
+ }
56
+ function Meter({ className, children, tone = "primary", shape = "bar", size, strokeWidth = 6, showValue, ...props }) {
57
+ if (shape === "ring") {
58
+ return /* @__PURE__ */ jsx(ToneContext.Provider, { value: tone, children: /* @__PURE__ */ jsx(Base.Root, { className: cn(meterRingVariants({ size }), className), ...props, children: children ?? /* @__PURE__ */ jsx(MeterRing, { value: props.value ?? null, min: props.min, max: props.max, strokeWidth, showValue, tone, size }) }) });
59
+ }
60
+ return /* @__PURE__ */ jsx(ToneContext.Provider, { value: tone, children: /* @__PURE__ */ jsx(SizeContext.Provider, { value: size, children: /* @__PURE__ */ jsx(Base.Root, { className: cn("w-full", className), ...props, children: children ?? /* @__PURE__ */ jsx(MeterTrack, {}) }) }) });
61
+ }
62
+ Meter.displayName = "Meter";
63
+ function MeterTrack({ className, children, size, ...props }) {
64
+ const inherited = useContext(SizeContext);
65
+ return /* @__PURE__ */ jsx(
66
+ Base.Track,
67
+ {
68
+ className: cn(meterTrackVariants({ size: size ?? inherited }), className),
69
+ ...props,
70
+ children: children ?? /* @__PURE__ */ jsx(MeterIndicator, {})
71
+ }
72
+ );
73
+ }
74
+ MeterTrack.displayName = "MeterTrack";
75
+ function MeterIndicator({ className, tone, ...props }) {
76
+ const inherited = useContext(ToneContext);
77
+ return /* @__PURE__ */ jsx(
78
+ Base.Indicator,
79
+ {
80
+ className: cn(meterIndicatorVariants({ tone: tone ?? inherited }), className),
81
+ ...props
82
+ }
83
+ );
84
+ }
85
+ MeterIndicator.displayName = "MeterIndicator";
86
+ function MeterLabel({ className, ...props }) {
87
+ return /* @__PURE__ */ jsx(
88
+ Base.Label,
89
+ {
90
+ className: cn("text-label-md text-foreground", className),
91
+ ...props
92
+ }
93
+ );
94
+ }
95
+ MeterLabel.displayName = "MeterLabel";
96
+ function MeterValue({ className, ...props }) {
97
+ return /* @__PURE__ */ jsx(
98
+ Base.Value,
99
+ {
100
+ className: cn("text-mono-sm text-muted-foreground", className),
101
+ ...props
102
+ }
103
+ );
104
+ }
105
+ MeterValue.displayName = "MeterValue";
106
+ export {
107
+ Meter,
108
+ MeterIndicator,
109
+ MeterLabel,
110
+ MeterTrack,
111
+ MeterValue
112
+ };