@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,168 @@
1
+ "use client";
2
+
3
+ // src/components/panel-group/panel-group.tsx
4
+ import {
5
+ useCallback,
6
+ useId,
7
+ useSyncExternalStore
8
+ } from "react";
9
+ import { cn } from "../../lib/cn.js";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var widthCache = /* @__PURE__ */ new Map();
12
+ var listeners = /* @__PURE__ */ new Set();
13
+ function clampWidth(value, min, max) {
14
+ return Math.min(max, Math.max(min, Math.round(value)));
15
+ }
16
+ function subscribe(listener) {
17
+ listeners.add(listener);
18
+ return () => listeners.delete(listener);
19
+ }
20
+ function readWidth(key, fallback, min, max) {
21
+ const cached = widthCache.get(key);
22
+ if (cached !== void 0) return cached;
23
+ let value = fallback;
24
+ try {
25
+ const stored = Number(window.localStorage.getItem(key));
26
+ if (Number.isFinite(stored) && stored > 0) value = clampWidth(stored, min, max);
27
+ } catch {
28
+ }
29
+ widthCache.set(key, value);
30
+ return value;
31
+ }
32
+ function usePanelWidth(defaultWidth, { storageKey, min = 200, max = 400 } = {}) {
33
+ const instanceId = useId();
34
+ const persist = Boolean(storageKey);
35
+ const key = storageKey ?? `memory:${instanceId}`;
36
+ const width = useSyncExternalStore(
37
+ subscribe,
38
+ () => persist ? readWidth(key, defaultWidth, min, max) : widthCache.get(key) ?? defaultWidth,
39
+ () => defaultWidth
40
+ );
41
+ const setWidth = useCallback(
42
+ (next) => {
43
+ const clamped = clampWidth(next, min, max);
44
+ if (widthCache.get(key) === clamped) return;
45
+ widthCache.set(key, clamped);
46
+ if (persist) {
47
+ try {
48
+ window.localStorage.setItem(key, String(clamped));
49
+ } catch {
50
+ }
51
+ }
52
+ for (const listener of listeners) listener();
53
+ },
54
+ [key, persist, min, max]
55
+ );
56
+ const bounds = { min, max };
57
+ return [width, setWidth, bounds];
58
+ }
59
+ function PanelGroup({ className, children, ...props }) {
60
+ return /* @__PURE__ */ jsx("div", { className: cn("flex min-h-0 min-w-0 flex-1", className), ...props, children });
61
+ }
62
+ PanelGroup.displayName = "PanelGroup";
63
+ function Panel({
64
+ label,
65
+ width,
66
+ scroll = true,
67
+ className,
68
+ children,
69
+ ...props
70
+ }) {
71
+ return /* @__PURE__ */ jsx(
72
+ "aside",
73
+ {
74
+ "aria-label": label,
75
+ style: width !== void 0 ? { width: `${width}px` } : void 0,
76
+ className: cn(
77
+ "flex min-h-0 min-w-0 flex-col bg-panel",
78
+ width === void 0 && "flex-1",
79
+ width !== void 0 && "shrink-0",
80
+ // Thin scrollbar: a panel is chrome, and the platform default is wider
81
+ // than the panel's own padding. Contained overscroll so a panel that
82
+ // runs out of list does not start scrolling the canvas beside it.
83
+ scroll && "overflow-y-auto overscroll-contain scrollbar-quiet",
84
+ className
85
+ ),
86
+ ...props,
87
+ children
88
+ }
89
+ );
90
+ }
91
+ Panel.displayName = "Panel";
92
+ function PanelResizer({
93
+ side,
94
+ width,
95
+ onWidthChange,
96
+ label,
97
+ min = 200,
98
+ max = 400,
99
+ step = 8,
100
+ className
101
+ }) {
102
+ function onPointerDown(e) {
103
+ e.preventDefault();
104
+ const startX = e.clientX;
105
+ const startWidth = width;
106
+ function onMove(ev) {
107
+ const delta = side === "left" ? ev.clientX - startX : startX - ev.clientX;
108
+ onWidthChange(startWidth + delta);
109
+ }
110
+ function onUp() {
111
+ window.removeEventListener("pointermove", onMove);
112
+ window.removeEventListener("pointerup", onUp);
113
+ window.removeEventListener("pointercancel", onUp);
114
+ }
115
+ window.addEventListener("pointermove", onMove);
116
+ window.addEventListener("pointerup", onUp);
117
+ window.addEventListener("pointercancel", onUp);
118
+ }
119
+ function onKeyDown(e) {
120
+ const grow = side === "left" ? "ArrowRight" : "ArrowLeft";
121
+ const shrink = side === "left" ? "ArrowLeft" : "ArrowRight";
122
+ if (e.key === grow) {
123
+ e.preventDefault();
124
+ onWidthChange(width + step);
125
+ } else if (e.key === shrink) {
126
+ e.preventDefault();
127
+ onWidthChange(width - step);
128
+ } else if (e.key === "Home") {
129
+ e.preventDefault();
130
+ onWidthChange(min);
131
+ } else if (e.key === "End") {
132
+ e.preventDefault();
133
+ onWidthChange(max);
134
+ }
135
+ }
136
+ return /* @__PURE__ */ jsx(
137
+ "div",
138
+ {
139
+ role: "separator",
140
+ "aria-orientation": "vertical",
141
+ "aria-label": label,
142
+ "aria-valuenow": width,
143
+ "aria-valuemin": min,
144
+ "aria-valuemax": max,
145
+ tabIndex: 0,
146
+ onPointerDown,
147
+ onKeyDown,
148
+ className: cn(
149
+ "group relative z-10 w-px shrink-0 cursor-col-resize bg-hairline outline-none",
150
+ className
151
+ ),
152
+ children: /* @__PURE__ */ jsx(
153
+ "span",
154
+ {
155
+ "aria-hidden": true,
156
+ className: "absolute inset-y-0 -left-1 -right-1 block motion-interactive group-hover:bg-hairline-strong group-focus-visible:bg-primary/60"
157
+ }
158
+ )
159
+ }
160
+ );
161
+ }
162
+ PanelResizer.displayName = "PanelResizer";
163
+ export {
164
+ Panel,
165
+ PanelGroup,
166
+ PanelResizer,
167
+ usePanelWidth
168
+ };
@@ -0,0 +1,153 @@
1
+ // src/components/panel-group/panel-group.meta.ts
2
+ var panelGroupMeta = {
3
+ name: "PanelGroup",
4
+ summary: "A row of docked chrome panels around a flexible centre, with draggable and keyboard-resizable edges and optional persisted widths.",
5
+ keywords: [
6
+ "panel",
7
+ "panels",
8
+ "resize",
9
+ "resizable",
10
+ "splitter",
11
+ "docked",
12
+ "workspace",
13
+ "tool",
14
+ "chrome",
15
+ "inspector",
16
+ "layout"
17
+ ],
18
+ usage: {
19
+ description: "Use PanelGroup for the body of a tool workspace: fixed-width Panels docked left and/or right, a flexible Panel in the middle for the canvas, and a PanelResizer between them. Panels scroll internally and the group never scrolls. This is the workspace-register counterpart to SplitPane, which only switches between side-by-side and stacked at a breakpoint and cannot be resized.",
20
+ bestPractices: [
21
+ {
22
+ guidance: "do",
23
+ description: "Give every docked Panel a fixed width and leave the centre Panel width-less so it absorbs the remaining space."
24
+ },
25
+ {
26
+ guidance: "do",
27
+ description: "Drive the width with usePanelWidth and pass a storageKey, so a user's layout survives a reload. Spread its bounds onto the PanelResizer rather than repeating min and max by hand."
28
+ },
29
+ {
30
+ guidance: "do",
31
+ description: "Label every Panel \u2014 they are landmarks, and 'Layers' or 'Properties' is what a screen-reader user navigates by."
32
+ },
33
+ {
34
+ guidance: "dont",
35
+ description: "Let the group scroll. Only panels and the canvas scroll; a scrolling group means the shell lost its height constraint."
36
+ },
37
+ {
38
+ guidance: "dont",
39
+ description: "Use it for page content columns \u2014 that's Grid or Columns. PanelGroup is chrome, and it sits outside the content grid."
40
+ },
41
+ {
42
+ guidance: "dont",
43
+ description: "Omit PanelResizer to save effort and then let users live with a fixed panel. If a panel holds a tree or a property grid, its width is a preference."
44
+ }
45
+ ],
46
+ anatomy: [
47
+ {
48
+ name: "PanelGroup",
49
+ required: true,
50
+ description: "The flex row. Sets min-h-0/min-w-0 so children can actually shrink and scroll."
51
+ },
52
+ {
53
+ name: "Panel",
54
+ required: true,
55
+ description: "One column. Fixed-width when `width` is set, flexible otherwise. Scrolls internally."
56
+ },
57
+ {
58
+ name: "PanelResizer",
59
+ required: false,
60
+ description: "The draggable edge between two panels: a 1px hairline with a wider hit area, operable by pointer and keyboard."
61
+ }
62
+ ]
63
+ },
64
+ related: {
65
+ components: ["PanelSection", "ScrubField", "SplitPane", "Sidebar", "AppShell"]
66
+ },
67
+ status: "stable",
68
+ props: [],
69
+ subcomponents: [
70
+ {
71
+ name: "Panel",
72
+ type: "{ label: string; width?: number; scroll?: boolean }",
73
+ description: "A docked or flexible column. `label` names the landmark; omit `width` for the flexible centre. `scroll` defaults to true \u2014 set it false for a header + scrolling body + pinned footer, so the footer doesn't scroll away with the list. When you own the layout, give the header and footer shrink-0 and the middle min-h-0 flex-1 overflow-y-auto. overflow-y-auto only activates if every flex ancestor can shrink: a single missing min-h-0 anywhere up the chain makes the panel grow instead of scroll, and nothing reports it."
74
+ },
75
+ {
76
+ name: "PanelResizer",
77
+ type: "{ side: 'left' | 'right'; width: number; onWidthChange: (n: number) => void; label: string; min?: number; max?: number; step?: number }",
78
+ description: "The draggable edge. `side` says which side the resized panel is on, so the drag delta's sign is right."
79
+ },
80
+ {
81
+ name: "usePanelWidth",
82
+ type: "(defaultWidth: number, options?: { storageKey?: string; min?: number; max?: number }) => readonly [number, (n: number) => void, { min: number; max: number }]",
83
+ description: "Controlled width for a Panel, clamped and optionally persisted to localStorage (only when `storageKey` is passed). Read through useSyncExternalStore, so there is no server/client hydration mismatch and no setState in an effect; do not hand-roll a localStorage read during render or a write from an effect. Without `storageKey` the width is kept in memory per hook instance. The third element is the `{ min, max }` it clamps to: spread it onto the paired PanelResizer so the separator's aria-valuemin/max and Home/End match the real clamp."
84
+ }
85
+ ],
86
+ a11y: [
87
+ "PanelResizer is a role=separator with aria-orientation, aria-valuenow/min/max, and is focusable \u2014 a pointer-only resizer is a keyboard trap.",
88
+ "Arrow keys resize by `step`; Home and End jump to the minimum and maximum.",
89
+ "Each Panel renders an <aside> with an accessible name from `label`, so panels are navigable landmarks."
90
+ ],
91
+ tokensUsed: ["primary", "panel", "hairline", "hairline-strong"],
92
+ examples: [
93
+ {
94
+ label: "Tool body with a resizable left panel",
95
+ code: `function Body() {
96
+ const [leftWidth, setLeftWidth, leftBounds] = usePanelWidth(240, { storageKey: "app:panel:left", min: 180, max: 360 })
97
+ return (
98
+ <PanelGroup>
99
+ <Panel label="Layers" width={leftWidth}>
100
+ <PanelSection title="Layers">
101
+ <PropertyRow label="Background">
102
+ <Switch checked />
103
+ </PropertyRow>
104
+ </PanelSection>
105
+ </Panel>
106
+ <PanelResizer side="left" width={leftWidth} onWidthChange={setLeftWidth} label="Resize layers panel" {...leftBounds} />
107
+ <Panel label="Canvas">
108
+ <div className="grid h-full place-items-center bg-canvas text-ui-body text-muted-foreground">Canvas</div>
109
+ </Panel>
110
+ </PanelGroup>
111
+ )
112
+ }`
113
+ },
114
+ {
115
+ label: "Both edges resizable",
116
+ code: `function Body() {
117
+ const [left, setLeft, leftBounds] = usePanelWidth(240, { storageKey: "app:left" })
118
+ const [right, setRight, rightBounds] = usePanelWidth(256, { storageKey: "app:right" })
119
+ return (
120
+ <PanelGroup>
121
+ <Panel label="Layers" width={left} />
122
+ <PanelResizer side="left" width={left} onWidthChange={setLeft} label="Resize layers panel" {...leftBounds} />
123
+ <Panel label="Canvas" />
124
+ <PanelResizer side="right" width={right} onWidthChange={setRight} label="Resize properties panel" {...rightBounds} />
125
+ <Panel label="Properties" width={right}>
126
+ <PanelSection title="Blending">
127
+ <PropertyPair>
128
+ <ScrubField label="Opacity" icon="grid" suffix="%" value={100} min={0} max={100} />
129
+ <ScrubField label="Blur" value={0} min={0} max={64} suffix="px" />
130
+ </PropertyPair>
131
+ </PanelSection>
132
+ </Panel>
133
+ </PanelGroup>
134
+ )
135
+ }`
136
+ },
137
+ {
138
+ label: "Fixed panel, no resizer",
139
+ code: `<PanelGroup>
140
+ <Panel label="Tools" width={56}>
141
+ <div className="flex flex-col gap-1 p-1">
142
+ <Button size="icon-xs" variant="ghost" aria-label="Toggle grid"><Icon name="grid" /></Button>
143
+ <Button size="icon-xs" variant="ghost" aria-label="Hide"><Icon name="eye" /></Button>
144
+ </div>
145
+ </Panel>
146
+ <Panel label="Canvas" />
147
+ </PanelGroup>`
148
+ }
149
+ ]
150
+ };
151
+ export {
152
+ panelGroupMeta
153
+ };
@@ -0,0 +1,9 @@
1
+ // src/components/panel-section/index.ts
2
+ import { PanelSection, PropertyPair, PropertyRow } from "./panel-section.js";
3
+ import { panelSectionMeta } from "./panel-section.meta.js";
4
+ export {
5
+ PanelSection,
6
+ PropertyPair,
7
+ PropertyRow,
8
+ panelSectionMeta
9
+ };
@@ -0,0 +1,115 @@
1
+ "use client";
2
+
3
+ // src/components/panel-section/panel-section.tsx
4
+ import { cn } from "../../lib/cn.js";
5
+ import { beginScrub } from "../../lib/scrub-gesture.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ function PanelSection({
8
+ title,
9
+ action,
10
+ className,
11
+ children,
12
+ ...props
13
+ }) {
14
+ return (
15
+ // Side padding and the first/last section's top/bottom come from a framing
16
+ // sable-frame-tool, so rows stay concentric with a rounded frame's corners;
17
+ // in a square Workspace column they fall back to the 8px tool inset.
18
+ /* @__PURE__ */ jsxs(
19
+ "section",
20
+ {
21
+ className: cn(
22
+ "flex flex-col border-t border-hairline first:pt-[var(--panel-edge,0px)] last:pb-[var(--panel-edge,0px)]",
23
+ className
24
+ ),
25
+ ...props,
26
+ children: [
27
+ /* @__PURE__ */ jsxs("header", { className: "flex h-7 items-center justify-between gap-2 px-[var(--panel-inset,--spacing(2))]", children: [
28
+ /* @__PURE__ */ jsx("h3", { className: "text-ui-section text-foreground", children: title }),
29
+ action
30
+ ] }),
31
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5 px-[var(--panel-inset,--spacing(2))] pb-2", children })
32
+ ]
33
+ }
34
+ )
35
+ );
36
+ }
37
+ PanelSection.displayName = "PanelSection";
38
+ function PropertyRow({
39
+ label,
40
+ htmlFor,
41
+ hint,
42
+ stacked = false,
43
+ scrub,
44
+ className,
45
+ children,
46
+ ...props
47
+ }) {
48
+ const scrubProps = scrub ? {
49
+ onPointerDown: (e) => beginScrub(e, {
50
+ value: scrub.value,
51
+ step: scrub.step ?? 1,
52
+ clamp: (n) => Math.min(scrub.max ?? Number.POSITIVE_INFINITY, Math.max(scrub.min ?? Number.NEGATIVE_INFINITY, n)),
53
+ onValueChange: scrub.onValueChange,
54
+ onGestureStart: scrub.onGestureStart,
55
+ onGestureEnd: scrub.onGestureEnd,
56
+ disabled: scrub.disabled,
57
+ preventDefaultOnDown: false
58
+ }),
59
+ // The affordance has to be visible before the drag, or nobody finds
60
+ // it; `select-none` so a slow drag does not highlight the word.
61
+ className: scrub.disabled ? void 0 : "cursor-ew-resize select-none",
62
+ title: hint ?? (scrub.disabled ? void 0 : "Drag to change")
63
+ } : null;
64
+ if (stacked) {
65
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 py-0.5", className), ...props, children: [
66
+ /* @__PURE__ */ jsx(
67
+ "label",
68
+ {
69
+ htmlFor,
70
+ title: hint,
71
+ ...scrubProps,
72
+ className: cn("text-ui-md text-muted-foreground", scrubProps?.className),
73
+ children: label
74
+ }
75
+ ),
76
+ children
77
+ ] });
78
+ }
79
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex min-h-6 items-center gap-2 py-0.5", className), ...props, children: [
80
+ /* @__PURE__ */ jsx(
81
+ "label",
82
+ {
83
+ htmlFor,
84
+ title: hint,
85
+ ...scrubProps,
86
+ className: cn(
87
+ "min-w-0 flex-1 truncate text-ui-md text-muted-foreground",
88
+ scrubProps?.className
89
+ ),
90
+ children: label
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-1", children })
94
+ ] });
95
+ }
96
+ PropertyRow.displayName = "PropertyRow";
97
+ function PropertyPair({ labels, className, children, ...props }) {
98
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1 py-0.5", className), ...props, children: [
99
+ labels ? /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: labels.map((text, i) => /* @__PURE__ */ jsx(
100
+ "span",
101
+ {
102
+ className: "truncate text-ui-md text-muted-foreground",
103
+ children: text
104
+ },
105
+ i
106
+ )) }) : null,
107
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children })
108
+ ] });
109
+ }
110
+ PropertyPair.displayName = "PropertyPair";
111
+ export {
112
+ PanelSection,
113
+ PropertyPair,
114
+ PropertyRow
115
+ };
@@ -0,0 +1,156 @@
1
+ // src/components/panel-section/panel-section.meta.ts
2
+ var panelSectionMeta = {
3
+ name: "PanelSection",
4
+ summary: "A flush group of property rows inside a docked panel \u2014 eyebrow header, hairline separator, rows beneath. The workspace register's answer to Card, which does not belong in a panel.",
5
+ keywords: [
6
+ "panel",
7
+ "section",
8
+ "inspector",
9
+ "properties",
10
+ "property grid",
11
+ "workspace",
12
+ "tool",
13
+ "chrome",
14
+ "sidebar"
15
+ ],
16
+ usage: {
17
+ description: "Use PanelSection to group properties inside an inspector or docked panel, with PropertyRow for one label-plus-control line and PropertyPair for two controls side by side. This is the workspace register's grouping primitive: it separates with a hairline and nothing else, because a Card inside a 240px panel spends its border and inset on nothing and pushes every row inward.",
18
+ bestPractices: [
19
+ {
20
+ guidance: "do",
21
+ description: "Group related properties under a short functional title \u2014 Blending, Layout, Fill \u2014 the way a tool inspector names its sections."
22
+ },
23
+ {
24
+ guidance: "do",
25
+ description: "Reach for PropertyPair before giving each property its own full-width row; pairing halves the vertical cost in a narrow panel."
26
+ },
27
+ {
28
+ guidance: "do",
29
+ description: "Put a section-scoped control (a visibility toggle, an add action) in the action slot rather than inventing a second header row."
30
+ },
31
+ {
32
+ guidance: "dont",
33
+ description: "Wrap panel content in Card. Cards are page-register furniture; in a panel they read as a page pasted into chrome."
34
+ },
35
+ {
36
+ guidance: "dont",
37
+ description: "Repeat the panel's own title as the section title. If the header above already names the selection, title the section by what it controls (Parameters, Blending)."
38
+ },
39
+ {
40
+ guidance: "dont",
41
+ description: 'Hand-roll a property line (`<div className="flex justify-between"><span>Opacity</span><Slider /></div>`). Use PropertyRow for every label-plus-control line: when each property type invents its own arrangement, a panel of fifteen properties ends up with fifteen layouts.'
42
+ },
43
+ {
44
+ guidance: "dont",
45
+ description: "Use PropertyRow for page forms \u2014 use Field, which carries label/description/error semantics. PropertyRow is a dense chrome row, not a form control."
46
+ }
47
+ ],
48
+ anatomy: [
49
+ {
50
+ name: "Header",
51
+ required: true,
52
+ description: "The section title in the UI section tier, with an optional trailing action."
53
+ },
54
+ {
55
+ name: "PropertyRow",
56
+ required: false,
57
+ description: "One property: label left, control right. `stacked` moves the control to its own line for full-width controls."
58
+ },
59
+ {
60
+ name: "PropertyPair",
61
+ required: false,
62
+ description: "Two controls side by side, with optional captions above each."
63
+ }
64
+ ]
65
+ },
66
+ related: {
67
+ components: ["Workspace", "PanelGroup", "ScrubField", "StatusBar", "Field", "Card"]
68
+ },
69
+ status: "stable",
70
+ props: [
71
+ {
72
+ name: "title",
73
+ type: "ReactNode",
74
+ description: "Section name, rendered as the header in the UI section tier."
75
+ },
76
+ {
77
+ name: "action",
78
+ type: "ReactNode",
79
+ description: "Optional trailing control in the header \u2014 a visibility toggle, an add action."
80
+ }
81
+ ],
82
+ subcomponents: [
83
+ {
84
+ name: "PropertyRow",
85
+ type: "{ label: ReactNode; htmlFor?: string; hint?: string; stacked?: boolean; scrub?: { value, onValueChange, step?, min?, max?, onGestureStart?, onGestureEnd?, disabled? } }",
86
+ description: "One property line. `hint` becomes the label's hover explanation; `stacked` puts the control on its own line. `scrub` makes the property NAME a drag handle for its value \u2014 the Figma/Framer/Paper convention, and the answer for a numeric row with no honest glyph to put in a ScrubField (a schema-generated `levels` or `seed`, where a `#` would be noise pretending to be meaning). Opt-in and additive: a row without it is unchanged. The label stays a real `<label htmlFor>` \u2014 a 2px jitter threshold keeps a click a click, and the click synthesised after a real drag is swallowed so a scrub does not also select the field's text."
87
+ },
88
+ {
89
+ name: "PropertyPair",
90
+ type: "{ labels?: [ReactNode, ReactNode] }",
91
+ description: "Two controls side by side in a 2-up grid, with optional captions above each."
92
+ }
93
+ ],
94
+ a11y: [
95
+ "PropertyRow renders a real <label>; pass htmlFor with the control's id so clicking the label focuses it.",
96
+ "The section title is an h3, so panels contribute a real heading outline rather than styled divs.",
97
+ "`hint` is exposed as the label's title attribute \u2014 keep the essential meaning in the label itself, since title text is not reliably announced.",
98
+ "A `scrub` label does not replace keyboard editing and must not be the only way to set the value: the drag is a pointer affordance, so the control it names still has to accept typing and arrow keys. It also keeps its `htmlFor` behaviour, which is the reason the gesture arms on a 2px threshold rather than on pointerdown."
99
+ ],
100
+ tokensUsed: ["foreground", "muted-foreground", "hairline"],
101
+ examples: [
102
+ {
103
+ label: "Blending section, 2-up",
104
+ code: `<PanelSection title="Blending">
105
+ <PropertyPair>
106
+ <ScrubField label="Opacity" value={100} min={0} max={100} suffix="%" />
107
+ <Select value="normal">
108
+ <SelectTrigger size="xs" />
109
+ <SelectContent>
110
+ <SelectItem value="normal">Normal</SelectItem>
111
+ <SelectItem value="multiply">Multiply</SelectItem>
112
+ </SelectContent>
113
+ </Select>
114
+ </PropertyPair>
115
+ </PanelSection>`
116
+ },
117
+ {
118
+ label: "Rows with a stacked slider",
119
+ code: `<PanelSection title="Parameters">
120
+ <PropertyRow label="Block size" hint="Block edge length in reference pixels." stacked>
121
+ <Slider value={32} min={4} max={256} />
122
+ </PropertyRow>
123
+ <PropertyRow label="Direction">
124
+ <Select value="both">
125
+ <SelectTrigger size="xs" />
126
+ <SelectContent>
127
+ <SelectItem value="both">Both</SelectItem>
128
+ <SelectItem value="horizontal">Horizontal</SelectItem>
129
+ </SelectContent>
130
+ </Select>
131
+ </PropertyRow>
132
+ <PropertyRow label="Reverse">
133
+ <Switch checked={false} />
134
+ </PropertyRow>
135
+ </PanelSection>`
136
+ },
137
+ {
138
+ label: "Section with a header action",
139
+ code: `<PanelSection
140
+ title="Blending"
141
+ action={
142
+ <Button size="icon-xs" variant="ghost" aria-label="Hide layer">
143
+ <Icon name="eye" />
144
+ </Button>
145
+ }
146
+ >
147
+ <PropertyRow label="Opacity">
148
+ <ScrubField label="Opacity" value={60} min={0} max={100} suffix="%" />
149
+ </PropertyRow>
150
+ </PanelSection>`
151
+ }
152
+ ]
153
+ };
154
+ export {
155
+ panelSectionMeta
156
+ };
@@ -0,0 +1,7 @@
1
+ // src/components/phone/index.ts
2
+ import { Phone } from "./phone.js";
3
+ import { phoneMeta } from "./phone.meta.js";
4
+ export {
5
+ Phone,
6
+ phoneMeta
7
+ };
@@ -0,0 +1,50 @@
1
+ // src/components/phone/phone.tsx
2
+ import { cn } from "../../lib/cn.js";
3
+ import { StatusIcons } from "./status-icons.js";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ function Phone({ statusBar = true, systemChrome = true, className, children, ...props }) {
6
+ return /* @__PURE__ */ jsxs(
7
+ "div",
8
+ {
9
+ className: cn(
10
+ // Hardware is the one surface no preset or mode repaints: a titanium
11
+ // body and band, not a theme's scrim (`overlay` is translucent in some
12
+ // presets, which drew a grey, see-through phone).
13
+ // design-lint-disable-next-line inline-color -- fixed device material, deliberately unthemed
14
+ "@container relative mx-auto w-[280px] [--phone-body:oklch(18%_0.004_265)] [--phone-band:oklch(48%_0.006_265)]",
15
+ className
16
+ ),
17
+ ...props,
18
+ children: [
19
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute -start-[0.6cqi] top-[18%] h-[4.5%] w-[0.8cqi] rounded-s-full bg-(--phone-band)" }),
20
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute -start-[0.6cqi] top-[25.5%] h-[7%] w-[0.8cqi] rounded-s-full bg-(--phone-band)" }),
21
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute -start-[0.6cqi] top-[34%] h-[7%] w-[0.8cqi] rounded-s-full bg-(--phone-band)" }),
22
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute -end-[0.6cqi] top-[27%] h-[10.5%] w-[0.8cqi] rounded-e-full bg-(--phone-band)" }),
23
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute -end-[0.4cqi] top-[55%] h-[6%] w-[0.6cqi] rounded-e-full bg-(--phone-band)" }),
24
+ /* @__PURE__ */ jsx("div", { className: "relative rounded-[18cqi] bg-(--phone-body) p-[3.7cqi] shadow-xl ring-[0.5cqi] ring-(--phone-band) ring-inset", children: /* @__PURE__ */ jsxs("div", { className: "relative aspect-[402/874] overflow-hidden rounded-[14.3cqi] bg-background text-foreground [clip-path:inset(0_round_14.3cqi)]", children: [
25
+ /* @__PURE__ */ jsx("div", { className: cn("h-full overflow-auto overscroll-contain scrollbar-hidden", statusBar && "pt-[14.3cqi]"), children }),
26
+ statusBar ? /* @__PURE__ */ jsxs(
27
+ "div",
28
+ {
29
+ "aria-hidden": true,
30
+ className: "absolute inset-x-0 top-0 grid h-[14.3cqi] grid-cols-[1fr_19cqi_1fr] grid-rows-[8cqi] content-start items-center bg-background px-[4cqi] pt-[2.6cqi]",
31
+ children: [
32
+ /* @__PURE__ */ jsx("span", { className: "justify-self-center text-label-md tabular-nums", children: "9:41" }),
33
+ /* @__PURE__ */ jsx("span", {}),
34
+ /* @__PURE__ */ jsx(StatusIcons, { className: "flex items-center gap-[1.15cqi] justify-self-center [&_svg]:h-[2.8cqi] [&_svg]:w-auto" })
35
+ ]
36
+ }
37
+ ) : null,
38
+ systemChrome ? /* @__PURE__ */ jsxs(Fragment, { children: [
39
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 top-[2.6cqi] mx-auto h-[8cqi] w-[19cqi] rounded-full bg-(--phone-body)" }),
40
+ /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute inset-x-0 bottom-[1.85cqi] mx-auto h-[1.15cqi] min-h-1 w-[35%] rounded-full bg-foreground" })
41
+ ] }) : null
42
+ ] }) })
43
+ ]
44
+ }
45
+ );
46
+ }
47
+ Phone.displayName = "Phone";
48
+ export {
49
+ Phone
50
+ };