@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,80 @@
1
+ // src/components/fieldset/fieldset.tsx
2
+ import { Fieldset as Base } from "@base-ui/react/fieldset";
3
+ import { cn } from "../../lib/cn.js";
4
+ import { jsx } from "react/jsx-runtime";
5
+ function Fieldset({ className, ...props }) {
6
+ return /* @__PURE__ */ jsx(
7
+ Base.Root,
8
+ {
9
+ className: cn(
10
+ // min-w-0: a native <fieldset> defaults to min-inline-size: min-content
11
+ // and would refuse to shrink below its widest control. overflow-hidden
12
+ // keeps the footer's wash inside the rounded corners.
13
+ // Publishes its surface like Card, so wells, stepper discs and
14
+ // interactive rows inside derive from the card, not the page.
15
+ "min-w-0 overflow-hidden rounded-lg border border-border bg-card text-card-foreground shadow-sm [--sable-surface-bg:var(--card)]",
16
+ // No opacity of its own: a disabled fieldset disables every control
17
+ // in it, and each already dims to 50% — dimming here as well stacked
18
+ // to ~30%, against 50% everywhere else in the system.
19
+ className
20
+ ),
21
+ ...props
22
+ }
23
+ );
24
+ }
25
+ Fieldset.displayName = "Fieldset";
26
+ function FieldsetLegend({ className, ...props }) {
27
+ return /* @__PURE__ */ jsx(
28
+ Base.Legend,
29
+ {
30
+ className: cn("px-6 pt-6 text-title-lg text-foreground", className),
31
+ ...props
32
+ }
33
+ );
34
+ }
35
+ FieldsetLegend.displayName = "FieldsetLegend";
36
+ function FieldsetDescription({
37
+ className,
38
+ ...props
39
+ }) {
40
+ return /* @__PURE__ */ jsx(
41
+ "p",
42
+ {
43
+ "data-slot": "fieldset-description",
44
+ className: cn("px-6 text-body-sm text-muted-foreground", className),
45
+ ...props
46
+ }
47
+ );
48
+ }
49
+ FieldsetDescription.displayName = "FieldsetDescription";
50
+ function FieldsetContent({
51
+ className,
52
+ ...props
53
+ }) {
54
+ return /* @__PURE__ */ jsx("div", { className: cn("space-y-4 px-6 py-4 last:pb-6", className), ...props });
55
+ }
56
+ FieldsetContent.displayName = "FieldsetContent";
57
+ function FieldsetFooter({
58
+ className,
59
+ ...props
60
+ }) {
61
+ return /* @__PURE__ */ jsx(
62
+ "div",
63
+ {
64
+ className: cn(
65
+ "flex justify-end gap-2 border-t border-border bg-muted/30 px-6 py-4",
66
+ "[[data-slot=fieldset-description]+&]:mt-6",
67
+ className
68
+ ),
69
+ ...props
70
+ }
71
+ );
72
+ }
73
+ FieldsetFooter.displayName = "FieldsetFooter";
74
+ export {
75
+ Fieldset,
76
+ FieldsetContent,
77
+ FieldsetDescription,
78
+ FieldsetFooter,
79
+ FieldsetLegend
80
+ };
@@ -0,0 +1,160 @@
1
+ // src/components/fieldset/fieldset.meta.ts
2
+ var fieldsetMeta = {
3
+ name: "Fieldset",
4
+ summary: "Form section panel (Card-like bordered surface) over Base UI Fieldset, with Legend/Description/Content/Footer parts.",
5
+ status: "stable",
6
+ keywords: [
7
+ "fieldset",
8
+ "form group",
9
+ "legend",
10
+ "fields"
11
+ ],
12
+ usage: {
13
+ description: "Use Fieldset to group related controls under a shared label or explanation.",
14
+ bestPractices: [
15
+ {
16
+ guidance: "do",
17
+ description: "Use it for grouped form sections such as contact details, preferences, or permissions."
18
+ },
19
+ {
20
+ guidance: "do",
21
+ description: "Keep the legend meaningful so assistive tech and agents understand the group purpose."
22
+ },
23
+ {
24
+ guidance: "dont",
25
+ description: "Do not use Fieldset as a generic spacing wrapper outside forms."
26
+ },
27
+ {
28
+ guidance: "dont",
29
+ description: "Do not use a Legend that is really a heading. A legend names the group's question for assistive technology; using it as a section title puts a question mark where the outline should be."
30
+ }
31
+ ],
32
+ anatomy: [
33
+ {
34
+ name: "Fieldset",
35
+ required: true,
36
+ description: "The bordered group: a native <fieldset> whose disabled state reaches every control inside it."
37
+ },
38
+ {
39
+ name: "Legend",
40
+ required: true,
41
+ description: "FieldsetLegend: the question the group's controls answer, announced before each of them."
42
+ },
43
+ {
44
+ name: "Description",
45
+ required: false,
46
+ description: "FieldsetDescription: muted copy under the legend."
47
+ },
48
+ {
49
+ name: "Content",
50
+ required: true,
51
+ description: "FieldsetContent: the stacked body, one Field per control."
52
+ },
53
+ {
54
+ name: "Footer",
55
+ required: false,
56
+ description: "FieldsetFooter: the group's actions on a muted wash."
57
+ }
58
+ ]
59
+ },
60
+ related: {
61
+ components: [
62
+ "Form",
63
+ "Label"
64
+ ]
65
+ },
66
+ props: [
67
+ {
68
+ name: "disabled",
69
+ type: "boolean",
70
+ description: "Disables the whole group. Renders <fieldset disabled> (native control disabling) and surfaces data-[disabled] for dimming."
71
+ },
72
+ {
73
+ name: "render",
74
+ type: "ReactElement | function",
75
+ description: "Base UI render prop to replace or compose the underlying element."
76
+ },
77
+ {
78
+ name: "className",
79
+ type: "string",
80
+ description: "Merged onto each part via cn() for one-off overrides."
81
+ }
82
+ ],
83
+ subcomponents: [
84
+ {
85
+ name: "FieldsetLegend",
86
+ type: "ComponentPropsWithRef<typeof Fieldset.Legend>",
87
+ description: "The group's name \u2014 the question its controls answer. Base UI renders it as a <div> wired to the <fieldset> through aria-labelledby, so a screen reader announces it before each control in the group. This is the whole reason to reach for Fieldset."
88
+ },
89
+ {
90
+ name: "FieldsetDescription",
91
+ type: 'ComponentPropsWithRef<"p">',
92
+ description: "Muted supporting copy under the legend."
93
+ },
94
+ {
95
+ name: "FieldsetContent",
96
+ type: 'ComponentPropsWithRef<"div">',
97
+ description: "The stacked body holding one Field per control."
98
+ },
99
+ {
100
+ name: "FieldsetFooter",
101
+ type: 'ComponentPropsWithRef<"div">',
102
+ description: "Optional right-aligned action bar on a muted wash."
103
+ }
104
+ ],
105
+ tokensUsed: [
106
+ "card",
107
+ "card-foreground",
108
+ "border",
109
+ "foreground",
110
+ "muted-foreground",
111
+ "muted"
112
+ ],
113
+ a11y: [
114
+ "Base.Root renders a native <fieldset>; Base.Legend renders an auto-associated label, so screen readers announce the group name.",
115
+ "disabled propagates as native <fieldset disabled>, disabling all contained controls.",
116
+ "Wrap each control inside FieldsetContent in a Field, which wires its own label, description and error to the control."
117
+ ],
118
+ examples: [
119
+ {
120
+ label: "A grouped question",
121
+ code: `<Fieldset>
122
+ <FieldsetLegend>Notify me about</FieldsetLegend>
123
+ <FieldsetDescription>Pick what reaches your inbox.</FieldsetDescription>
124
+ <FieldsetContent>
125
+ <Field label="Mentions" orientation="horizontal"><Checkbox defaultChecked /></Field>
126
+ <Field label="Replies" orientation="horizontal"><Checkbox /></Field>
127
+ <Field label="Direct messages" orientation="horizontal"><Checkbox /></Field>
128
+ </FieldsetContent>
129
+ <FieldsetFooter>
130
+ <Button>Save preferences</Button>
131
+ </FieldsetFooter>
132
+ </Fieldset>`
133
+ },
134
+ {
135
+ label: "Why a fieldset, and when it is wrong",
136
+ code: `// Fieldset groups inputs that are ONE question with multiple parts, and gives
137
+ // the group a single accessible name \u2014 which is the part you cannot do with a
138
+ // div and a heading.
139
+
140
+ <Fieldset>
141
+ <FieldsetLegend>Digest frequency</FieldsetLegend>
142
+ <FieldsetContent>
143
+ <RadioGroup defaultValue="weekly">
144
+ <Field label="Daily" orientation="horizontal"><Radio value="daily" /></Field>
145
+ <Field label="Weekly" orientation="horizontal"><Radio value="weekly" /></Field>
146
+ </RadioGroup>
147
+ </FieldsetContent>
148
+ </Fieldset>
149
+
150
+ // \u2713 Required for radio groups: without a fieldset the options have no shared
151
+ // name, so a screen reader announces "Weekly, radio" with no question.
152
+ // \u2717 Not for visual grouping of unrelated fields. Use PanelSection on a panel or
153
+ // a Card section on a page; a legend that is really a heading lies to
154
+ // assistive technology about the form's structure.`
155
+ }
156
+ ]
157
+ };
158
+ export {
159
+ fieldsetMeta
160
+ };
@@ -0,0 +1,17 @@
1
+ // src/components/fieldset/index.ts
2
+ import {
3
+ Fieldset,
4
+ FieldsetLegend,
5
+ FieldsetDescription,
6
+ FieldsetContent,
7
+ FieldsetFooter
8
+ } from "./fieldset.js";
9
+ import { fieldsetMeta } from "./fieldset.meta.js";
10
+ export {
11
+ Fieldset,
12
+ FieldsetContent,
13
+ FieldsetDescription,
14
+ FieldsetFooter,
15
+ FieldsetLegend,
16
+ fieldsetMeta
17
+ };
@@ -0,0 +1,193 @@
1
+ // src/components/file-dropzone/file-dropzone.tsx
2
+ import {
3
+ useId,
4
+ useRef,
5
+ useState
6
+ } from "react";
7
+ import { Icon } from "../../icon/index.js";
8
+ import { cn } from "../../lib/cn.js";
9
+ import { useTypeTier } from "../../lib/density.js";
10
+ import { fileDropzoneVariants } from "./file-dropzone.variants.js";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ function matchesAccept(file, accept) {
13
+ if (!accept) return true;
14
+ const name = file.name.toLowerCase();
15
+ const type = file.type.toLowerCase();
16
+ return accept.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean).some((rule) => {
17
+ if (rule.startsWith(".")) return name.endsWith(rule);
18
+ if (rule.endsWith("/*")) return type.startsWith(rule.slice(0, -1));
19
+ return type === rule;
20
+ });
21
+ }
22
+ function formatFileSize(bytes) {
23
+ const units = ["B", "KB", "MB", "GB"];
24
+ let value = bytes;
25
+ let unit = 0;
26
+ while (value >= 1024 && unit < units.length - 1) {
27
+ value /= 1024;
28
+ unit++;
29
+ }
30
+ const rounded = value >= 10 || unit === 0 ? Math.round(value) : Math.round(value * 10) / 10;
31
+ return `${rounded} ${units[unit]}`;
32
+ }
33
+ function hasFiles(event) {
34
+ return Array.from(event.dataTransfer?.types ?? []).includes("Files");
35
+ }
36
+ function FileDropzone({
37
+ accept,
38
+ maxSize,
39
+ multiple = false,
40
+ maxFiles,
41
+ disabled = false,
42
+ required,
43
+ onFilesAccepted,
44
+ onFilesRejected,
45
+ label,
46
+ description,
47
+ acceptLabel,
48
+ formatError,
49
+ icon = "arrow-up",
50
+ size = "md",
51
+ id,
52
+ className,
53
+ "aria-describedby": ariaDescribedBy,
54
+ "aria-invalid": ariaInvalid,
55
+ ...props
56
+ }) {
57
+ const generatedId = useId();
58
+ const buttonId = id ?? generatedId;
59
+ const errId = `${buttonId}-errors`;
60
+ const inputRef = useRef(null);
61
+ const depth = useRef(0);
62
+ const [dragging, setDragging] = useState(false);
63
+ const [errors, setErrors] = useState([]);
64
+ const tier = useTypeTier();
65
+ const messageFor = (r) => {
66
+ if (formatError) return formatError(r);
67
+ const name = `\u201C${r.file.name}\u201D`;
68
+ switch (r.code) {
69
+ case "file-invalid-type":
70
+ return acceptLabel ? `${name} isn't a supported type. Use ${acceptLabel} instead.` : `${name} isn't a supported type. Choose a different file.`;
71
+ case "file-too-large":
72
+ return `${name} is larger than ${formatFileSize(maxSize ?? 0)}. Choose a smaller file.`;
73
+ case "too-many-files":
74
+ return multiple ? `${name} wasn't added. Add up to ${maxFiles} files at a time.` : `${name} wasn't added. Add one file at a time.`;
75
+ }
76
+ };
77
+ const take = (files) => {
78
+ if (disabled || files.length === 0) return;
79
+ const limit = multiple ? maxFiles ?? Number.POSITIVE_INFINITY : 1;
80
+ const accepted = [];
81
+ const rejected = [];
82
+ for (const file of files) {
83
+ const code = !matchesAccept(file, accept) ? "file-invalid-type" : maxSize != null && file.size > maxSize ? "file-too-large" : accepted.length >= limit ? "too-many-files" : null;
84
+ if (code) rejected.push({ file, code, message: messageFor({ file, code }) });
85
+ else accepted.push(file);
86
+ }
87
+ setErrors(rejected.map((r) => r.message));
88
+ if (accepted.length) onFilesAccepted?.(accepted);
89
+ if (rejected.length) onFilesRejected?.(rejected);
90
+ };
91
+ const endDrag = () => {
92
+ depth.current = 0;
93
+ setDragging(false);
94
+ };
95
+ const invalid = errors.length > 0 || ariaInvalid === true || ariaInvalid === "true";
96
+ const describedBy = [ariaDescribedBy, errors.length ? errId : null].filter(Boolean).join(" ") || void 0;
97
+ return /* @__PURE__ */ jsxs(
98
+ "div",
99
+ {
100
+ className: cn("flex w-full flex-col", className),
101
+ onDragEnter: (e) => {
102
+ if (!hasFiles(e)) return;
103
+ e.preventDefault();
104
+ depth.current++;
105
+ if (!disabled) setDragging(true);
106
+ },
107
+ onDragOver: (e) => {
108
+ if (!hasFiles(e)) return;
109
+ e.preventDefault();
110
+ e.dataTransfer.dropEffect = disabled ? "none" : "copy";
111
+ },
112
+ onDragLeave: (e) => {
113
+ if (!hasFiles(e)) return;
114
+ depth.current = Math.max(0, depth.current - 1);
115
+ if (depth.current === 0) setDragging(false);
116
+ },
117
+ onDrop: (e) => {
118
+ e.preventDefault();
119
+ endDrag();
120
+ take(Array.from(e.dataTransfer?.files ?? []));
121
+ },
122
+ ...props,
123
+ children: [
124
+ /* @__PURE__ */ jsxs(
125
+ "button",
126
+ {
127
+ type: "button",
128
+ id: buttonId,
129
+ disabled,
130
+ "data-dragging": dragging ? "" : void 0,
131
+ "data-invalid": invalid ? "" : void 0,
132
+ "aria-invalid": invalid || void 0,
133
+ "aria-describedby": describedBy,
134
+ onClick: () => inputRef.current?.click(),
135
+ className: fileDropzoneVariants({ size }),
136
+ children: [
137
+ /* @__PURE__ */ jsx(
138
+ "span",
139
+ {
140
+ "aria-hidden": "true",
141
+ className: cn(
142
+ "flex size-(--control-md) shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground motion-interactive",
143
+ "group-data-[dragging]:-translate-y-0.5 group-data-[dragging]:bg-primary group-data-[dragging]:text-primary-foreground"
144
+ ),
145
+ children: /* @__PURE__ */ jsx(Icon, { name: icon, className: "text-lg" })
146
+ }
147
+ ),
148
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
149
+ /* @__PURE__ */ jsx("span", { className: tier.control, children: label ?? /* @__PURE__ */ jsxs(Fragment, { children: [
150
+ multiple ? "Drop files here or " : "Drop a file here or ",
151
+ /* @__PURE__ */ jsx("span", { className: "text-primary underline underline-offset-2", children: "browse" })
152
+ ] }) }),
153
+ description ? /* @__PURE__ */ jsx("span", { className: cn("text-muted-foreground", tier.supporting), children: description }) : null
154
+ ] })
155
+ ]
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsx(
159
+ "input",
160
+ {
161
+ ref: inputRef,
162
+ type: "file",
163
+ accept,
164
+ multiple,
165
+ disabled,
166
+ required,
167
+ tabIndex: -1,
168
+ "aria-hidden": "true",
169
+ className: "sr-only",
170
+ onChange: (e) => {
171
+ take(Array.from(e.currentTarget.files ?? []));
172
+ e.currentTarget.value = "";
173
+ }
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsx(
177
+ "div",
178
+ {
179
+ id: errId,
180
+ role: "status",
181
+ className: cn("text-destructive not-empty:pt-2", tier.supporting),
182
+ children: errors.length === 1 ? /* @__PURE__ */ jsx("p", { children: errors[0] }) : errors.length > 1 ? /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5", children: errors.map((message, i) => /* @__PURE__ */ jsx("li", { children: message }, `${i}-${message}`)) }) : null
183
+ }
184
+ )
185
+ ]
186
+ }
187
+ );
188
+ }
189
+ FileDropzone.displayName = "FileDropzone";
190
+ export {
191
+ FileDropzone,
192
+ formatFileSize
193
+ };
@@ -0,0 +1,210 @@
1
+ // src/components/file-dropzone/file-dropzone.meta.ts
2
+ var fileDropzoneMeta = {
3
+ name: "FileDropzone",
4
+ summary: "Drag-and-drop target and file picker in one keyboard-operable button. Checks accept, maxSize and maxFiles on every selection, announces each rejection with how to fix it, and hands accepted files to you to list as Attachments.",
5
+ status: "stable",
6
+ keywords: [
7
+ "file upload",
8
+ "dropzone",
9
+ "drag and drop",
10
+ "file picker",
11
+ "upload",
12
+ "attach file",
13
+ "file input",
14
+ "import"
15
+ ],
16
+ usage: {
17
+ description: "Use FileDropzone where adding files is the main job of a section \u2014 an upload step, an import screen, a document request. It gives the drag gesture a visible target and the same action a button for everyone who does not drag. It holds no list: render accepted files as Attachments beneath it, where progress, retry and remove belong.",
18
+ bestPractices: [
19
+ {
20
+ guidance: "do",
21
+ description: 'State the constraints in `description` ("PNG or PDF, up to 10 MB") and give `acceptLabel` the same words, so a rejection repeats the rule the user already read.'
22
+ },
23
+ {
24
+ guidance: "do",
25
+ description: 'Pair it with a list of Attachment rows that you own. Once files are added, switch to `size="sm"` so the target stays available without pushing the list below the fold.'
26
+ },
27
+ {
28
+ guidance: "do",
29
+ description: 'Cap the total by passing `maxFiles={limit - files.length}`; the dropzone only sees one selection at a time. When none remain, set `disabled` and say why in `description` ("Remove one to add another").'
30
+ },
31
+ {
32
+ guidance: "dont",
33
+ description: "Do not use it for an incidental attach action inside a composer or a toolbar. A paperclip Button that opens the picker is the right weight there; ChatComposer already has one."
34
+ },
35
+ {
36
+ guidance: "dont",
37
+ description: "Do not rely on `accept` alone to protect the server. The dropzone's checks are for the user's benefit; validate type and size again where the file is received."
38
+ },
39
+ {
40
+ guidance: "dont",
41
+ description: 'Do not silently drop rejected files. The zone announces each one, but if you also discard files later (a server-side limit), say so on the Attachment with `status="error"` and a fix.'
42
+ }
43
+ ],
44
+ anatomy: [
45
+ {
46
+ name: "Zone",
47
+ required: true,
48
+ description: "A full-width button with a dashed border. Click, Enter or Space opens the picker; it is also the drop target."
49
+ },
50
+ {
51
+ name: "Icon",
52
+ required: false,
53
+ description: "A decorative mark that lifts while a file is dragged over the zone."
54
+ },
55
+ {
56
+ name: "Label and description",
57
+ required: true,
58
+ description: "The call to action and the constraints. Together they form the button's accessible name."
59
+ },
60
+ {
61
+ name: "Status",
62
+ required: true,
63
+ description: "A role=status region, present from the first render, that lists each rejected file and how to fix it."
64
+ }
65
+ ]
66
+ },
67
+ related: {
68
+ components: ["Attachment", "Input", "Button", "Progress"]
69
+ },
70
+ props: [
71
+ {
72
+ name: "accept",
73
+ type: "string",
74
+ description: "Native accept syntax \u2014 `.pdf`, `application/pdf`, `image/*`, comma-separated. Enforced on drop and on pick."
75
+ },
76
+ {
77
+ name: "maxSize",
78
+ type: "number",
79
+ description: "Largest accepted file, in bytes."
80
+ },
81
+ {
82
+ name: "multiple",
83
+ type: "boolean",
84
+ default: "false",
85
+ description: "Accept more than one file per selection."
86
+ },
87
+ {
88
+ name: "maxFiles",
89
+ type: "number",
90
+ description: "Most files accepted from one selection when `multiple`. Pass the remaining capacity to cap a total."
91
+ },
92
+ {
93
+ name: "onFilesAccepted",
94
+ type: "(files: File[]) => void",
95
+ description: "Files that passed every check, in selection order."
96
+ },
97
+ {
98
+ name: "onFilesRejected",
99
+ type: "(rejections: FileRejection[]) => void",
100
+ description: "Files that failed, each with `code` (file-invalid-type, file-too-large, too-many-files) and the announced `message`."
101
+ },
102
+ {
103
+ name: "label",
104
+ type: "ReactNode",
105
+ default: '"Drop a file here or browse"',
106
+ description: "The visible call to action. Pluralised automatically when `multiple`."
107
+ },
108
+ {
109
+ name: "description",
110
+ type: "ReactNode",
111
+ description: "The constraints in words, shown under the label."
112
+ },
113
+ {
114
+ name: "acceptLabel",
115
+ type: "string",
116
+ description: 'How the accepted types complete "Use \u2026 instead" in an error ("PNG or PDF", "an image or PDF"). Without it a type error can only say "Choose a different file".'
117
+ },
118
+ {
119
+ name: "formatError",
120
+ type: "(rejection) => string",
121
+ description: "Replace the rejection copy, e.g. to localize it."
122
+ },
123
+ {
124
+ name: "icon",
125
+ type: "string",
126
+ default: '"arrow-up"',
127
+ description: "Semantic icon name."
128
+ },
129
+ {
130
+ name: "size",
131
+ type: '"md" | "sm"',
132
+ default: '"md"',
133
+ description: "`md` is the empty-section target; `sm` is a single-row strip above an existing list."
134
+ },
135
+ {
136
+ name: "disabled / required / id / aria-invalid",
137
+ type: "\u2014",
138
+ description: "Standard form-control props. `id` lands on the button, so `<Field>` labels it; `aria-invalid` draws the destructive border."
139
+ }
140
+ ],
141
+ variants: {
142
+ size: ["md", "sm"]
143
+ },
144
+ tokensUsed: [
145
+ "card",
146
+ "foreground",
147
+ "muted",
148
+ "muted-foreground",
149
+ "border-strong",
150
+ "primary",
151
+ "primary-foreground",
152
+ "accent",
153
+ "accent-foreground",
154
+ "ring",
155
+ "destructive"
156
+ ],
157
+ motion: [
158
+ {
159
+ slot: "arrival",
160
+ recipe: "none",
161
+ part: "Zone",
162
+ why: "The zone is the section's content, present from the start. An entrance would only delay the drop target someone is already dragging toward."
163
+ },
164
+ {
165
+ slot: "response",
166
+ recipe: "motion-interactive",
167
+ part: "Zone",
168
+ why: 'Hover strengthens the border to primary, which confirms the whole dashed area \u2014 not just the word "browse" \u2014 is the click target.'
169
+ },
170
+ {
171
+ slot: "transition",
172
+ recipe: "motion-interactive",
173
+ part: "Icon",
174
+ why: "When a file crosses into the zone the icon fills and lifts and the surface tints. That is the only signal that releasing here will work; without it users drop on the page and the browser opens the file instead."
175
+ },
176
+ {
177
+ slot: "activity",
178
+ recipe: "none",
179
+ part: "Zone",
180
+ why: "The zone hands files off immediately and never uploads. Transfer progress belongs on each Attachment, where it can be per-file and retryable."
181
+ }
182
+ ],
183
+ a11y: [
184
+ "The zone is a native button: Enter or Space opens the system picker, so dragging is never the only way in.",
185
+ "Rejections render into a role=status region that exists from the first render, and the button's aria-describedby points at it while it has content, so the reason is still read when focus returns.",
186
+ 'Every error names the file and says how to fix it ("Choose a smaller file"), rather than only what failed.',
187
+ "The underlying file input is visually hidden and removed from the tab order; the button is the single focus stop."
188
+ ],
189
+ examples: [
190
+ {
191
+ label: "Images and PDFs",
192
+ code: '<FileDropzone accept="image/*,.pdf" acceptLabel="an image or PDF" maxSize={10 * 1024 * 1024} multiple description="Images or PDFs, up to 10 MB each" onFilesAccepted={(files) => console.log(files)} />'
193
+ },
194
+ {
195
+ label: "With an Attachment list",
196
+ code: `<div className="flex flex-col gap-3">
197
+ <FileDropzone size="sm" multiple description="Up to 5 files" onFilesAccepted={(files) => console.log(files)} />
198
+ <Attachment name="contract.pdf" meta="2.4 MB \xB7 PDF" />
199
+ <Attachment name="site-photo.jpg" meta="Uploading\u2026" status="uploading" progress={42} />
200
+ </div>`
201
+ },
202
+ {
203
+ label: "In a field",
204
+ code: '<Field label="Proof of address" description="A bill or statement from the last 3 months."><FileDropzone accept=".pdf" acceptLabel="a PDF" maxSize={5 * 1024 * 1024} description="PDF, up to 5 MB" /></Field>'
205
+ }
206
+ ]
207
+ };
208
+ export {
209
+ fileDropzoneMeta
210
+ };
@@ -0,0 +1,26 @@
1
+ // src/components/file-dropzone/file-dropzone.variants.ts
2
+ import { cva } from "class-variance-authority";
3
+ var fileDropzoneVariants = cva(
4
+ [
5
+ "group flex w-full flex-col items-center justify-center gap-2 rounded-md border border-dashed border-border-strong bg-card text-center text-foreground motion-interactive",
6
+ "hover:border-primary hover:bg-muted",
7
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
8
+ "data-[dragging]:border-primary data-[dragging]:bg-accent data-[dragging]:text-accent-foreground",
9
+ "data-[invalid]:border-destructive",
10
+ "disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:border-border-strong disabled:hover:bg-card"
11
+ ],
12
+ {
13
+ variants: {
14
+ size: {
15
+ md: "px-6 py-8",
16
+ sm: "flex-row justify-start gap-3 px-4 py-3 text-start"
17
+ }
18
+ },
19
+ defaultVariants: {
20
+ size: "md"
21
+ }
22
+ }
23
+ );
24
+ export {
25
+ fileDropzoneVariants
26
+ };