@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,132 @@
1
+ // src/components/marker/marker.meta.ts
2
+ var markerMeta = {
3
+ name: "Marker",
4
+ summary: "A non-message row in a conversation: streaming status, system note, bordered notice, or a labelled rule for date breaks. Quieter than the message tier by design.",
5
+ status: "stable",
6
+ keywords: [
7
+ "chat status",
8
+ "typing indicator",
9
+ "thinking",
10
+ "streaming",
11
+ "tool call",
12
+ "system message",
13
+ "date separator",
14
+ "date break",
15
+ "conversation divider"
16
+ ],
17
+ usage: {
18
+ description: 'Everything in a conversation that is not a message. Date breaks, "Carla joined", "Thinking\u2026", "Ran search \u2014 3 results", "Message failed to send". One component because they share one job: annotate the stream without competing with it.',
19
+ bestPractices: [
20
+ {
21
+ guidance: "do",
22
+ description: 'Use `status` with `icon="spinner" spin` for work in flight, and add `shimmer` while text is actually streaming. The shimmer is scale-aware, so it freezes with the rest of the system under reduced motion.'
23
+ },
24
+ {
25
+ guidance: "do",
26
+ description: 'Use `variant="separator"` for date breaks. The label sits between two rules, which reads as a division of the transcript rather than as another thing someone said.'
27
+ },
28
+ {
29
+ guidance: "do",
30
+ description: `Replace a status marker's text as the work progresses \u2014 "Thinking\u2026" \u2192 "Searching the docs" \u2192 "Writing the answer". It is a live region, so each change is announced.`
31
+ },
32
+ {
33
+ guidance: "do",
34
+ description: "Reach for `bordered` only when a note needs containing \u2014 an error, an escalation, a retention notice. Boxing routine system events makes a transcript look like a list of alerts."
35
+ },
36
+ {
37
+ guidance: "dont",
38
+ description: "Do not style a Marker up to message weight. Its whole value is being below that tier; a marker as loud as a message competes with the conversation it is annotating."
39
+ },
40
+ {
41
+ guidance: "dont",
42
+ description: 'Do not leave a status marker mounted after the work finishes. A permanent "Thinking\u2026" is a live region that never resolves, which is worse than no status at all.'
43
+ },
44
+ {
45
+ guidance: "dont",
46
+ description: "Do not use it for a message from a person or an assistant. That is `Message` + `Bubble` \u2014 a marker has no author and no side."
47
+ },
48
+ {
49
+ guidance: "dont",
50
+ description: "Do not set `live` on a `separator` or on a run of `note` markers. Announcing every date break and join event turns the live region into noise and buries the status that mattered."
51
+ }
52
+ ]
53
+ },
54
+ related: {
55
+ components: [
56
+ "Message",
57
+ "Bubble",
58
+ "MessageScroller",
59
+ "InlineStatus",
60
+ "Separator"
61
+ ]
62
+ },
63
+ props: [
64
+ {
65
+ name: "variant",
66
+ type: '"status" | "note" | "bordered" | "separator"',
67
+ default: '"status"',
68
+ description: "`status` for live activity, `note` for a system event, `bordered` for a note that needs containing, `separator` for a labelled rule."
69
+ },
70
+ {
71
+ name: "icon",
72
+ type: "string",
73
+ description: "Semantic icon name shown before the label, resolved through IconProvider."
74
+ },
75
+ {
76
+ name: "spin",
77
+ type: "boolean",
78
+ default: "false",
79
+ description: 'Spin the icon \u2014 pair with `icon="spinner"` for work in flight.'
80
+ },
81
+ {
82
+ name: "shimmer",
83
+ type: "boolean",
84
+ default: "false",
85
+ description: "Sweep the label while something is streaming, via the scale-aware `motion-text-shimmer` recipe (freezes under reduced motion)."
86
+ },
87
+ {
88
+ name: "live",
89
+ type: "boolean",
90
+ default: "true for `status`, false otherwise",
91
+ description: "Announce the label to assistive tech as it changes. On for `status`, because a screen-reader user otherwise gets silence for the whole generation and no way to tell a slow answer from a dead one."
92
+ },
93
+ {
94
+ name: "...div props",
95
+ type: 'ComponentPropsWithRef<"div">',
96
+ description: "Spread onto the row."
97
+ }
98
+ ],
99
+ variants: { variant: ["status", "note", "bordered", "separator"] },
100
+ tokensUsed: ["muted-foreground", "muted", "border", "foreground"],
101
+ a11y: [
102
+ '`status` markers render as `role="status"` with `aria-live="polite"`, so a change of activity is announced without interrupting whatever is being read.',
103
+ "The other variants are silent by default and can opt in with `live` \u2014 announcing every date break and join event would bury the status that mattered.",
104
+ "The separator's rules are `aria-hidden`, leaving only the label in the accessibility tree; the shimmer is decoration over readable text, not a replacement for it.",
105
+ "`motion-text-shimmer` keeps the label opaque through every frame \u2014 the gradient runs muted-foreground \u2192 foreground rather than fading to transparent, so the text never becomes unreadable mid-animation, and `--motion-scale` freezes it entirely under reduced motion."
106
+ ],
107
+ examples: [
108
+ {
109
+ label: "Streaming status",
110
+ code: '<Marker icon="spinner" spin shimmer>Thinking\u2026</Marker>'
111
+ },
112
+ {
113
+ label: "Date break",
114
+ code: '<Marker variant="separator">Yesterday</Marker>'
115
+ },
116
+ {
117
+ label: "System note",
118
+ code: '<Marker variant="note" icon="user">Carla joined the conversation</Marker>'
119
+ },
120
+ {
121
+ label: "A notice that needs containing",
122
+ code: '<Marker variant="bordered" icon="warning">This conversation will be archived in 7 days.</Marker>'
123
+ },
124
+ {
125
+ label: "In a transcript",
126
+ code: '<MessageScroller className="h-96">\n <Marker variant="separator">Today</Marker>\n <Message messageId="m1"><Bubble>Can you summarise the release?</Bubble></Message>\n <Marker variant="note" icon="sparkles">Ran changelog \u2014 12 entries</Marker>\n <Marker icon="spinner" spin shimmer>Writing the answer</Marker>\n</MessageScroller>'
127
+ }
128
+ ]
129
+ };
130
+ export {
131
+ markerMeta
132
+ };
@@ -0,0 +1,25 @@
1
+ // src/components/marker/marker.variants.ts
2
+ import { cva } from "class-variance-authority";
3
+ var markerVariants = cva(
4
+ "flex w-full items-center gap-2 text-body-xs text-muted-foreground",
5
+ {
6
+ variants: {
7
+ variant: {
8
+ /** Live activity — "Thinking…", "Searching the docs". */
9
+ status: "justify-center py-0.5",
10
+ /** A system note — "Carla joined", "Conversation assigned to Support". */
11
+ note: "justify-center py-0.5",
12
+ /** A note that needs a container — errors, escalations, retention notices. */
13
+ bordered: "justify-center rounded-md border border-border bg-muted/40 px-3 py-2",
14
+ /** A labelled rule — the date break. */
15
+ separator: "gap-3 py-1"
16
+ }
17
+ },
18
+ defaultVariants: { variant: "status" }
19
+ }
20
+ );
21
+ var markerRuleVariants = cva("w-auto flex-1");
22
+ export {
23
+ markerRuleVariants,
24
+ markerVariants
25
+ };
@@ -0,0 +1,7 @@
1
+ // src/components/marquee/index.ts
2
+ import { Marquee } from "./marquee.js";
3
+ import { marqueeMeta } from "./marquee.meta.js";
4
+ export {
5
+ Marquee,
6
+ marqueeMeta
7
+ };
@@ -0,0 +1,146 @@
1
+ "use client";
2
+
3
+ // src/components/marquee/marquee.tsx
4
+ import { useCallback, useMemo, useRef, useState } from "react";
5
+ import { cn } from "../../lib/cn.js";
6
+ import { PlayPauseGlyph } from "../../lib/glyphs.js";
7
+ import { mergeRefs } from "../../lib/refs.js";
8
+ import { useResizeObserver } from "../../lib/use-resize-observer.js";
9
+ import { useMotion } from "../../motion/MotionProvider.js";
10
+ import { Button } from "../button/button.js";
11
+ import { jsx, jsxs } from "react/jsx-runtime";
12
+ function Marquee({
13
+ children,
14
+ direction = "left",
15
+ speed = 40,
16
+ gap = "calc(var(--spacing) * 8)",
17
+ pauseOnHover = true,
18
+ controls = false,
19
+ play,
20
+ onPlayChange,
21
+ fade = false,
22
+ label,
23
+ className,
24
+ style,
25
+ ref,
26
+ ...props
27
+ }) {
28
+ const { enabled } = useMotion();
29
+ const [userPaused, setUserPaused] = useState(false);
30
+ const isPaused = play != null ? !play : userPaused;
31
+ const togglePlay = () => {
32
+ if (play != null) onPlayChange?.(!play);
33
+ else setUserPaused((p) => !p);
34
+ };
35
+ const containerRef = useRef(null);
36
+ const groupRef = useRef(null);
37
+ const [copies, setCopies] = useState(2);
38
+ const [metrics, setMetrics] = useState({ distance: 0, duration: 0 });
39
+ const vertical = direction === "up" || direction === "down";
40
+ const reverse = direction === "right" || direction === "down";
41
+ const measure = useCallback(() => {
42
+ const container = containerRef.current;
43
+ const group = groupRef.current;
44
+ if (!container || !group) return;
45
+ const cs = getComputedStyle(group);
46
+ const gapPx = Number.parseFloat(vertical ? cs.rowGap : cs.columnGap) || 0;
47
+ const groupSize = vertical ? group.offsetHeight : group.offsetWidth;
48
+ const containerSize = vertical ? container.offsetHeight : container.offsetWidth;
49
+ if (groupSize <= 0) return;
50
+ const distance = groupSize + gapPx;
51
+ const duration = distance / speed;
52
+ const needed = Math.min(
53
+ 8,
54
+ Math.max(2, Math.ceil(containerSize / distance) + 1)
55
+ );
56
+ setCopies((c) => c === needed ? c : needed);
57
+ setMetrics(
58
+ (m) => Math.abs(m.distance - distance) < 0.5 && Math.abs(m.duration - duration) < 0.01 ? m : { distance, duration }
59
+ );
60
+ }, [speed, vertical]);
61
+ useResizeObserver(measure, [containerRef, groupRef]);
62
+ const setContainer = useMemo(() => mergeRefs(containerRef, ref), [ref]);
63
+ const animate = enabled && metrics.duration > 0;
64
+ const trackStyle = { gap };
65
+ if (animate) {
66
+ trackStyle["--sable-marquee-distance"] = `${metrics.distance}px`;
67
+ trackStyle.animationName = vertical ? "sable-marquee-y" : "sable-marquee-x";
68
+ trackStyle.animationDuration = `${metrics.duration}s`;
69
+ trackStyle.animationTimingFunction = "linear";
70
+ trackStyle.animationIterationCount = "infinite";
71
+ trackStyle.animationDirection = reverse ? "reverse" : "normal";
72
+ trackStyle.willChange = "transform";
73
+ if (isPaused) trackStyle.animationPlayState = "paused";
74
+ }
75
+ const groups = animate ? copies : 1;
76
+ const fadeMask = fade ? (
77
+ // design-lint-disable-next-line inline-color -- CSS edge-fade mask: #000 is alpha-mask machinery (only the mask alpha matters), not a rendered color
78
+ `linear-gradient(${vertical ? "to bottom" : "to right"}, transparent, #000 calc(var(--spacing) * 8), #000 calc(100% - var(--spacing) * 8), transparent)`
79
+ ) : void 0;
80
+ return /* @__PURE__ */ jsxs(
81
+ "div",
82
+ {
83
+ ref: setContainer,
84
+ "data-sable-marquee": "",
85
+ "data-pause-on-hover": pauseOnHover ? "" : void 0,
86
+ role: label ? "group" : void 0,
87
+ "aria-label": label,
88
+ className: cn(
89
+ "group/marquee relative max-w-full overflow-hidden",
90
+ // When motion is off, fall back to a normal scroll region.
91
+ !animate && (vertical ? "overflow-y-auto overscroll-contain scrollbar-quiet" : "overflow-x-auto overscroll-x-contain scrollbar-quiet"),
92
+ className
93
+ ),
94
+ style: { ...style, maskImage: fadeMask, WebkitMaskImage: fadeMask },
95
+ ...props,
96
+ children: [
97
+ controls && animate && // The floating Button — the same control that sits over Carousel's
98
+ // slides and MessageScroller's thread, read over moving content.
99
+ /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ variant: "floating",
103
+ size: "icon-xs",
104
+ onClick: togglePlay,
105
+ "aria-label": isPaused ? "Play" : "Pause",
106
+ className: "absolute end-2 top-2 z-10",
107
+ children: /* @__PURE__ */ jsx(PlayPauseGlyph, { playing: !isPaused })
108
+ }
109
+ ),
110
+ /* @__PURE__ */ jsx(
111
+ "div",
112
+ {
113
+ "data-sable-marquee-track": "",
114
+ className: cn(
115
+ "flex",
116
+ // Vertical track is absolute ONLY while animating, so it doesn't
117
+ // drive container height (the feedback loop). When motion is
118
+ // off it stays in-flow so the scroll fallback has content.
119
+ vertical ? animate ? "absolute inset-x-0 top-0 flex-col" : "flex-col" : "w-max"
120
+ ),
121
+ style: trackStyle,
122
+ children: Array.from({ length: groups }, (_, i) => /* @__PURE__ */ jsx(
123
+ "div",
124
+ {
125
+ ref: i === 0 ? groupRef : void 0,
126
+ "aria-hidden": i > 0 ? true : void 0,
127
+ inert: i > 0 || void 0,
128
+ className: cn(
129
+ "flex shrink-0 items-center",
130
+ vertical ? "flex-col" : "w-max"
131
+ ),
132
+ style: { gap },
133
+ children
134
+ },
135
+ i
136
+ ))
137
+ }
138
+ )
139
+ ]
140
+ }
141
+ );
142
+ }
143
+ Marquee.displayName = "Marquee";
144
+ export {
145
+ Marquee
146
+ };
@@ -0,0 +1,106 @@
1
+ // src/components/marquee/marquee.meta.ts
2
+ var marqueeMeta = {
3
+ name: "Marquee",
4
+ summary: "Seamless, constant-speed infinite loop (logos, tags, testimonials). Zero-dependency: duplicates children to fill the track and advances exactly one group + gap per iteration so it never seams. Pauses on hover/focus; freezes to a scroll region when motion is off/reduced.",
5
+ status: "stable",
6
+ keywords: [
7
+ "marquee",
8
+ "ticker",
9
+ "scrolling",
10
+ "ambient"
11
+ ],
12
+ usage: {
13
+ description: "Use Marquee for decorative or ambient continuous content where motion supports the surface.",
14
+ bestPractices: [
15
+ {
16
+ guidance: "do",
17
+ description: "Use it for low-priority repeated content such as logos, tags, or lightweight highlights."
18
+ },
19
+ {
20
+ guidance: "do",
21
+ description: "Respect reduced motion and keep the content understandable without relying on animation."
22
+ },
23
+ {
24
+ guidance: "dont",
25
+ description: "Do not put critical messages, controls, or required reading inside Marquee."
26
+ },
27
+ {
28
+ guidance: "dont",
29
+ description: "Do not put content that must be read in a Marquee. It moves continuously, so anything longer than a logo or a short label cannot be read reliably \u2014 and it must stop for prefers-reduced-motion."
30
+ }
31
+ ]
32
+ },
33
+ related: {
34
+ components: [
35
+ "Scroller",
36
+ "Carousel",
37
+ "Badge"
38
+ ]
39
+ },
40
+ props: [
41
+ {
42
+ name: "direction",
43
+ type: '"left" | "right" | "up" | "down"',
44
+ default: '"left"',
45
+ description: 'Scroll direction; up/down switch to a vertical loop, which needs a bounded height (e.g. className="h-56").'
46
+ },
47
+ {
48
+ name: "speed",
49
+ type: "number",
50
+ default: "40",
51
+ description: "Constant speed in px/s \u2014 independent of content length."
52
+ },
53
+ {
54
+ name: "gap",
55
+ type: "string",
56
+ default: '"calc(var(--spacing) * 8)"',
57
+ description: "Gap between items (any CSS length). Use a spacing-scale value (calc(var(--spacing) * n)) so it moves with density."
58
+ },
59
+ {
60
+ name: "pauseOnHover",
61
+ type: "boolean",
62
+ default: "true",
63
+ description: "Pause while hovered or keyboard-focused (WCAG 2.2.2)."
64
+ },
65
+ {
66
+ name: "controls",
67
+ type: "boolean",
68
+ default: "false",
69
+ description: "Render a visible pause/play control \u2014 recommended for WCAG 2.2.2 when content auto-scrolls."
70
+ },
71
+ {
72
+ name: "fade",
73
+ type: "boolean",
74
+ default: "false",
75
+ description: "Fade the leading/trailing edges with a mask."
76
+ },
77
+ {
78
+ name: "label",
79
+ type: "string",
80
+ description: "Accessible label for the scrolling region."
81
+ }
82
+ ],
83
+ tokensUsed: [],
84
+ a11y: [
85
+ "Duplicate groups are aria-hidden, so screen readers read the content once.",
86
+ "Pauses on hover and focus-within; under prefers-reduced-motion / MotionProvider off it stops and becomes a normal scroll region.",
87
+ "Decorative by default \u2014 pass a label only when the row conveys meaning."
88
+ ],
89
+ examples: [
90
+ {
91
+ label: "Logo row",
92
+ code: '<Marquee>{logos.map((l) => <img key={l.id} src={l.src} alt={l.name} className="h-8" />)}</Marquee>'
93
+ },
94
+ {
95
+ label: "Reverse, faster",
96
+ code: '<Marquee direction="right" speed={70}>{tags.map((t) => <Badge key={t} appearance="outline">{t}</Badge>)}</Marquee>'
97
+ },
98
+ {
99
+ label: "Vertical",
100
+ code: '<Marquee direction="up" className="h-64">{items}</Marquee>'
101
+ }
102
+ ]
103
+ };
104
+ export {
105
+ marqueeMeta
106
+ };
@@ -0,0 +1,7 @@
1
+ // src/components/media-image/index.ts
2
+ import { MediaImage } from "./media-image.js";
3
+ import { mediaImageMeta } from "./media-image.meta.js";
4
+ export {
5
+ MediaImage,
6
+ mediaImageMeta
7
+ };
@@ -0,0 +1,56 @@
1
+ "use client";
2
+
3
+ // src/components/media-image/media-image.tsx
4
+ import { Avatar as Base } from "@base-ui/react/avatar";
5
+ import { useState } from "react";
6
+ import { cn } from "../../lib/cn.js";
7
+ import { GradientArt } from "../gradient-art/index.js";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ function MediaImage({
10
+ src,
11
+ alt = "",
12
+ seed,
13
+ fallback,
14
+ fit = "cover",
15
+ srcSet,
16
+ sizes,
17
+ loading = "lazy",
18
+ className,
19
+ ...props
20
+ }) {
21
+ const [tracked, setTracked] = useState({ src, status: "idle" });
22
+ const status = !src ? "error" : tracked.src === src ? tracked.status : "idle";
23
+ const showFallback = status === "error";
24
+ const named = status !== "loaded" && alt ? { role: "img", "aria-label": alt } : null;
25
+ return /* @__PURE__ */ jsxs(
26
+ Base.Root,
27
+ {
28
+ render: /* @__PURE__ */ jsx("div", {}),
29
+ "data-slot": "media-image",
30
+ "data-status": status,
31
+ className: cn("relative block size-full overflow-hidden bg-muted", className),
32
+ ...named,
33
+ ...props,
34
+ children: [
35
+ src ? /* @__PURE__ */ jsx(
36
+ Base.Image,
37
+ {
38
+ src,
39
+ srcSet,
40
+ sizes,
41
+ alt,
42
+ loading,
43
+ decoding: "async",
44
+ onLoadingStatusChange: (next) => setTracked({ src, status: next }),
45
+ className: cn("size-full motion-fade", fit === "contain" ? "object-contain" : "object-cover")
46
+ }
47
+ ) : null,
48
+ showFallback ? /* @__PURE__ */ jsx("div", { "data-slot": "media-image-fallback", "aria-hidden": true, className: "absolute inset-0", children: fallback ?? /* @__PURE__ */ jsx(GradientArt, { seed: seed ?? (alt || void 0), className: "size-full" }) }) : null
49
+ ]
50
+ }
51
+ );
52
+ }
53
+ MediaImage.displayName = "MediaImage";
54
+ export {
55
+ MediaImage
56
+ };
@@ -0,0 +1,92 @@
1
+ // src/components/media-image/media-image.meta.ts
2
+ var mediaImageMeta = {
3
+ name: "MediaImage",
4
+ summary: "An image that fills its box and falls back to GradientArt seeded by the item when it has no source or the source fails \u2014 Avatar's image-load tracking, for covers, thumbnails and product shots instead of faces.",
5
+ status: "beta",
6
+ keywords: [
7
+ "image",
8
+ "img",
9
+ "image fallback",
10
+ "broken image",
11
+ "cover art",
12
+ "album art",
13
+ "thumbnail",
14
+ "placeholder image",
15
+ "onError",
16
+ "missing image"
17
+ ],
18
+ usage: {
19
+ description: "Use MediaImage wherever content imagery may be missing or broken: a cover in a grid, a thumbnail in a row, a product shot. It fills the box it is given \u2014 an AspectBox for a cover, a sized and rounded box for a thumbnail \u2014 shows a quiet muted surface while the image loads, fades the image in once decoded, and paints GradientArt seeded by the item when there is no image to show, so a grid of missing covers still reads as distinct things. For a person use Avatar; for a whole tile with title and actions use MediaTile, which composes this.",
20
+ bestPractices: [
21
+ {
22
+ guidance: "do",
23
+ description: 'Give the box the shape: `<AspectBox ratio={1} className="rounded-md"><MediaImage \u2026 /></AspectBox>`, or `size-14 rounded-md` on MediaImage itself for a thumbnail. It clips to whatever radius the box has.'
24
+ },
25
+ {
26
+ guidance: "do",
27
+ description: "Pass `seed` (the title or an id) when `alt` is empty, so the fallback art is the item's own and stays the same in every list it appears in."
28
+ },
29
+ {
30
+ guidance: "do",
31
+ description: "Leave `alt` empty when a visible title sits next to the image \u2014 a tile, a row \u2014 and describe it when the image stands alone. A set `alt` also names the fallback, so the description survives a broken URL."
32
+ },
33
+ {
34
+ guidance: "dont",
35
+ description: "Do not hand-write `<img onError={() => setBroken(true)}>`. An image that fails before hydration never fires the handler on a prerendered page; MediaImage preloads off the DOM and catches it."
36
+ },
37
+ {
38
+ guidance: "dont",
39
+ description: 'Do not use it for profile pictures. A person is a circle with initials \u2014 Avatar, whose `variant="art"` is the same fallback with the person\'s initials over it.'
40
+ }
41
+ ]
42
+ },
43
+ related: { components: ["MediaTile", "Avatar", "GradientArt", "AspectBox"] },
44
+ props: [
45
+ { name: "src", type: "string", description: "Image URL. Omitted, empty or failing to load \u21D2 the fallback shows." },
46
+ {
47
+ name: "alt",
48
+ type: "string",
49
+ default: '""',
50
+ description: "Alt text. Empty is decorative \u2014 right beside a visible title. When set and no image shows, it names the fallback instead."
51
+ },
52
+ { name: "seed", type: "string | number", description: "Seeds the fallback art. Defaults to `alt`; pass the title or an id when `alt` is empty." },
53
+ { name: "fallback", type: "ReactNode", description: "Replaces the GradientArt fallback \u2014 a glyph or monogram. Fills the frame under the same clipping." },
54
+ {
55
+ name: "fit",
56
+ type: '"cover" | "contain"',
57
+ default: '"cover"',
58
+ description: "`cover` crops to fill (artwork, photos); `contain` letterboxes on the muted surface (a logo, a product that must not be cropped)."
59
+ },
60
+ { name: "srcSet", type: "string", description: "Responsive sources, passed to the `<img>`." },
61
+ { name: "sizes", type: "string", description: "The `sizes` attribute for `srcSet`." },
62
+ { name: "loading", type: '"lazy" | "eager"', default: '"lazy"', description: "Native lazy loading. Use `eager` for the first row of a grid above the fold." },
63
+ { name: "className", type: "string", description: "Sizing and rounding when MediaImage is the box itself (`size-14 rounded-md`). Inside an AspectBox it already fills." }
64
+ ],
65
+ variants: { fit: ["cover", "contain"] },
66
+ tokensUsed: ["muted", "art-1", "art-2", "art-3", "art-4", "art-5", "art-6", "art-ground"],
67
+ motion: [
68
+ {
69
+ slot: "arrival",
70
+ recipe: "motion-fade",
71
+ part: "image",
72
+ why: "The image fades in over the muted surface once it has decoded, so a slow cover settles in instead of popping row by row as the grid loads."
73
+ },
74
+ { slot: "response", recipe: "none", part: "root", why: "Imagery, not a control. The tile or row around it answers the pointer." },
75
+ { slot: "transition", recipe: "none", part: "root", why: "Its only state change is loading \u2192 loaded or failed, which the arrival covers." },
76
+ { slot: "activity", recipe: "none", part: "root", why: "A loading image rests on a static muted surface; a shimmer per cover across a long grid would be noise." }
77
+ ],
78
+ a11y: [
79
+ "`alt` defaults to empty (decorative), because the usual neighbour is a visible title that already names the item; describe the image when it stands alone.",
80
+ 'When no image is on screen and `alt` is set, the frame takes `role="img"` with that label, so a broken URL does not erase the description. The fallback art itself is always aria-hidden.',
81
+ "The `<img>` mounts only once it has loaded, so assistive technology never meets a broken-image icon."
82
+ ],
83
+ examples: [
84
+ { label: "Cover with fallback", code: '<AspectBox ratio={1} className="rounded-md">\n <MediaImage src={album.cover} seed={album.title} />\n</AspectBox>' },
85
+ { label: "No image yet", code: '<AspectBox ratio={1} className="rounded-md">\n <MediaImage seed="Low tide, high noon" />\n</AspectBox>' },
86
+ { label: "Row thumbnail", code: '<MediaImage src={track.art} seed={track.title} className="size-12 shrink-0 rounded-sm" />' },
87
+ { label: "Logo, never cropped", code: '<AspectBox ratio={16 / 9} className="rounded-lg">\n <MediaImage src={brand.logo} alt={brand.name} fit="contain" />\n</AspectBox>' }
88
+ ]
89
+ };
90
+ export {
91
+ mediaImageMeta
92
+ };
@@ -0,0 +1,7 @@
1
+ // src/components/media-tile/index.ts
2
+ import { MediaTile } from "./media-tile.js";
3
+ import { mediaTileMeta } from "./media-tile.meta.js";
4
+ export {
5
+ MediaTile,
6
+ mediaTileMeta
7
+ };