@uisatin/ui 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +10 -1
  3. package/{chunk-P4O6TGDR.js → chunk-3VVO5MY5.js} +28 -26
  4. package/chunk-47DDBME3.js +87 -0
  5. package/{chunk-SHDFUXYV.js → chunk-5663JVE5.js} +16 -18
  6. package/chunk-67CBFB6Y.js +99 -0
  7. package/chunk-6DWLTGRQ.js +130 -0
  8. package/chunk-6GNMUJQ4.js +45 -0
  9. package/chunk-6JTSZAGO.js +177 -0
  10. package/chunk-6RLSRMB5.js +14 -0
  11. package/chunk-6Y6CY2DP.js +55 -0
  12. package/{chunk-O7F3CIDV.js → chunk-7NV53EL5.js} +10 -12
  13. package/{chunk-BNZVTLHV.js → chunk-7SVMERPH.js} +25 -21
  14. package/chunk-A52HUWVM.js +24 -0
  15. package/chunk-AKEZCWNW.js +29 -0
  16. package/{chunk-SH6NG6VN.js → chunk-APRVUOD6.js} +6 -8
  17. package/{chunk-QUF2IPOZ.js → chunk-C435UD7V.js} +14 -15
  18. package/{chunk-B2K45IUR.js → chunk-C6WRJ7DG.js} +5 -7
  19. package/{chunk-PF3YBUKT.js → chunk-CQFAMWZI.js} +16 -15
  20. package/chunk-DAKVTPYZ.js +86 -0
  21. package/{chunk-VAGIAREV.js → chunk-DMZW4LGU.js} +29 -26
  22. package/chunk-EBZHGRM5.js +46 -0
  23. package/chunk-EHEXE2UV.js +44 -0
  24. package/{chunk-72OCFAPT.js → chunk-EQAFDIPE.js} +26 -23
  25. package/{chunk-LLHTVIM3.js → chunk-EXKSKYG3.js} +7 -9
  26. package/chunk-FB6DG3LR.js +35 -0
  27. package/chunk-GH2DEOGO.js +67 -0
  28. package/{chunk-YG7JOOLJ.js → chunk-GKDMCY2S.js} +5 -7
  29. package/chunk-GTFUAA6H.js +42 -0
  30. package/{chunk-TX3H3QMA.js → chunk-HI6QIG55.js} +71 -70
  31. package/{chunk-6QMSWITQ.js → chunk-HZV7EXGU.js} +24 -26
  32. package/{chunk-A5XEM3GF.js → chunk-IKJIR6VL.js} +34 -36
  33. package/{chunk-DO3TBNSC.js → chunk-INJWE2LD.js} +15 -17
  34. package/chunk-J5UQPROI.js +56 -0
  35. package/{chunk-6YXUBP27.js → chunk-JCR5TWTF.js} +72 -67
  36. package/chunk-JKOBDLP3.js +25 -0
  37. package/chunk-JR3VVDV6.js +37 -0
  38. package/chunk-JYGCZWET.js +112 -0
  39. package/{chunk-UGRSWP6U.js → chunk-K5G5OEV5.js} +10 -12
  40. package/{chunk-B6V4VSGH.js → chunk-KDU7AT2T.js} +14 -15
  41. package/chunk-KITXKIYW.js +104 -0
  42. package/{chunk-NN6PKJWS.js → chunk-KQNA22D3.js} +7 -9
  43. package/{chunk-YPNKBE5X.js → chunk-L5PPN42A.js} +14 -9
  44. package/chunk-LAOE6Y57.js +95 -0
  45. package/chunk-LI5VYDLN.js +195 -0
  46. package/{chunk-7TXHCRAG.js → chunk-LKSFTNPF.js} +8 -10
  47. package/chunk-LLW3X4ZJ.js +39 -0
  48. package/{chunk-RTJ76X5U.js → chunk-LWRB4DED.js} +2 -4
  49. package/{chunk-NSRTTYQ4.js → chunk-M7RILZVW.js} +42 -35
  50. package/{chunk-LW3TRU5W.js → chunk-MOGWOUCN.js} +28 -16
  51. package/chunk-NCIRJ5V2.js +108 -0
  52. package/chunk-NQL6SIIB.js +168 -0
  53. package/chunk-NTSU44FY.js +81 -0
  54. package/{chunk-3DINAQLL.js → chunk-P36KBUYD.js} +33 -29
  55. package/chunk-P6RHT2VM.js +147 -0
  56. package/{chunk-CL2II6BX.js → chunk-PD2KD5OR.js} +11 -13
  57. package/{chunk-XL75JRUA.js → chunk-PP46SY7M.js} +42 -22
  58. package/{chunk-L6NCCSIP.js → chunk-PTK4QAOQ.js} +36 -29
  59. package/{chunk-HL42K2NH.js → chunk-Q7KVC5B4.js} +17 -17
  60. package/{chunk-H4NU7NPO.js → chunk-R3DTMBDT.js} +62 -61
  61. package/{chunk-KNUWZNFV.js → chunk-R4KPFBMK.js} +4 -6
  62. package/chunk-R5TQ3HNB.js +71 -0
  63. package/chunk-RFSPJECL.js +84 -0
  64. package/chunk-RPL6FRVX.js +88 -0
  65. package/{chunk-AN2RNJLR.js → chunk-STYOBAC7.js} +16 -16
  66. package/{chunk-X3PQANZO.js → chunk-SVUWR3HD.js} +47 -46
  67. package/chunk-T7P3OEBP.js +128 -0
  68. package/{chunk-QS4N4MNP.js → chunk-TB3ZRV3Y.js} +18 -20
  69. package/{chunk-MYEZXZZC.js → chunk-TOY6YPTG.js} +23 -25
  70. package/{chunk-XILQ7GXE.js → chunk-U6X6ODDJ.js} +11 -13
  71. package/{chunk-XZNHT6MO.js → chunk-UAJ6M34K.js} +115 -61
  72. package/chunk-W2EH6RY5.js +42 -0
  73. package/{chunk-FDKIX4DC.js → chunk-W2QQQWNE.js} +7 -9
  74. package/{chunk-LZMKSFCF.js → chunk-WALANB3V.js} +10 -12
  75. package/chunk-WCUR44O6.js +88 -0
  76. package/{chunk-BNTPPZCK.js → chunk-WJYJMX5S.js} +37 -39
  77. package/chunk-WZSLDYUU.js +131 -0
  78. package/{chunk-J3NSDRVH.js → chunk-XETMIETJ.js} +0 -2
  79. package/chunk-XU6JJDMZ.js +117 -0
  80. package/{chunk-BKZBWPUH.js → chunk-XWPH7C2W.js} +9 -11
  81. package/{chunk-GICKPMJU.js → chunk-YXWXSRXG.js} +31 -31
  82. package/{chunk-2HKBZFIK.js → chunk-YY236ZSJ.js} +31 -31
  83. package/{chunk-YX5VNRJX.js → chunk-YYFAZQ25.js} +0 -2
  84. package/{chunk-Y5AYU7PK.js → chunk-ZHFIWDGF.js} +0 -2
  85. package/components/accordion.js +2 -4
  86. package/components/action-button.d.ts +37 -0
  87. package/components/action-button.js +5 -0
  88. package/components/agent-loading.d.ts +2 -0
  89. package/components/agent-loading.js +2 -4
  90. package/components/agent-picker.js +5 -5
  91. package/components/agent-suggestion.js +5 -6
  92. package/components/alert.d.ts +37 -0
  93. package/components/alert.js +5 -0
  94. package/components/announcement-bar.js +7 -7
  95. package/components/attachment.js +5 -5
  96. package/components/avatar.js +4 -6
  97. package/components/badge.js +2 -4
  98. package/components/banner-mesh.js +1 -3
  99. package/components/banner.js +6 -6
  100. package/components/bar-chart.js +10 -11
  101. package/components/breadcrumb.js +5 -6
  102. package/components/button-group.d.ts +26 -0
  103. package/components/button-group.js +5 -0
  104. package/components/button.d.ts +13 -1
  105. package/components/button.js +4 -4
  106. package/components/card.js +5 -5
  107. package/components/channel-chart.js +10 -11
  108. package/components/chart.js +9 -10
  109. package/components/checkbox.js +2 -4
  110. package/components/chip.js +2 -4
  111. package/components/citations.d.ts +6 -4
  112. package/components/citations.js +4 -5
  113. package/components/code-block.js +5 -5
  114. package/components/combobox.d.ts +12 -3
  115. package/components/combobox.js +10 -10
  116. package/components/command-menu.d.ts +6 -2
  117. package/components/command-menu.js +5 -6
  118. package/components/context-menu.d.ts +12 -5
  119. package/components/context-menu.js +5 -6
  120. package/components/cookie-consent.js +5 -5
  121. package/components/date-picker.d.ts +26 -14
  122. package/components/date-picker.js +9 -9
  123. package/components/decision-card.js +7 -7
  124. package/components/dialog.d.ts +6 -8
  125. package/components/dialog.js +6 -5
  126. package/components/donut-chart.js +10 -11
  127. package/components/dot.js +2 -4
  128. package/components/dropdown.d.ts +6 -1
  129. package/components/dropdown.js +4 -5
  130. package/components/empty-state.js +2 -4
  131. package/components/field-group.d.ts +27 -0
  132. package/components/field-group.js +3 -0
  133. package/components/file-upload.js +7 -7
  134. package/components/floating.js +1 -3
  135. package/components/form-field.d.ts +38 -1
  136. package/components/form-field.js +2 -4
  137. package/components/form.d.ts +47 -0
  138. package/components/form.js +3 -0
  139. package/components/hover-card.d.ts +5 -2
  140. package/components/hover-card.js +2 -4
  141. package/components/input-group.d.ts +21 -0
  142. package/components/input-group.js +6 -0
  143. package/components/input-otp.d.ts +4 -2
  144. package/components/input-otp.js +7 -8
  145. package/components/input.d.ts +5 -1
  146. package/components/input.js +3 -5
  147. package/components/kbd.js +2 -4
  148. package/components/labels.d.ts +86 -0
  149. package/components/labels.js +1 -0
  150. package/components/line-chart.js +11 -12
  151. package/components/link.d.ts +20 -0
  152. package/components/link.js +3 -0
  153. package/components/list.d.ts +46 -0
  154. package/components/list.js +2 -0
  155. package/components/message-actions.js +5 -5
  156. package/components/message.js +8 -8
  157. package/components/number-input.d.ts +4 -2
  158. package/components/number-input.js +7 -8
  159. package/components/pagination.js +6 -6
  160. package/components/password-input.d.ts +16 -0
  161. package/components/password-input.js +7 -0
  162. package/components/popover.d.ts +11 -5
  163. package/components/popover.js +3 -4
  164. package/components/progress.js +2 -4
  165. package/components/prompt-bar.js +6 -6
  166. package/components/radio.js +2 -4
  167. package/components/search-bar.js +3 -5
  168. package/components/segmented-control.d.ts +4 -2
  169. package/components/segmented-control.js +3 -5
  170. package/components/select.d.ts +11 -2
  171. package/components/select.js +6 -7
  172. package/components/selectable-card.d.ts +37 -0
  173. package/components/selectable-card.js +2 -0
  174. package/components/selectable-checkbox.d.ts +14 -0
  175. package/components/selectable-checkbox.js +4 -0
  176. package/components/selectable-radio.d.ts +16 -0
  177. package/components/selectable-radio.js +3 -0
  178. package/components/separator.d.ts +18 -0
  179. package/components/separator.js +2 -0
  180. package/components/sheet.d.ts +4 -2
  181. package/components/sheet.js +7 -6
  182. package/components/sidebar.js +2 -4
  183. package/components/skeleton.js +2 -4
  184. package/components/slider.d.ts +6 -2
  185. package/components/slider.js +7 -8
  186. package/components/sliding-indicator.js +1 -3
  187. package/components/spinner.d.ts +18 -0
  188. package/components/spinner.js +3 -0
  189. package/components/split-button.d.ts +24 -0
  190. package/components/split-button.js +8 -0
  191. package/components/streaming-text.js +2 -4
  192. package/components/switch.js +2 -4
  193. package/components/table.d.ts +16 -5
  194. package/components/table.js +4 -5
  195. package/components/tabs.d.ts +4 -2
  196. package/components/tabs.js +3 -5
  197. package/components/textarea.js +3 -5
  198. package/components/thinking.js +3 -5
  199. package/components/toast.js +5 -5
  200. package/components/toggle.js +2 -4
  201. package/components/tooltip.d.ts +5 -2
  202. package/components/tooltip.js +3 -5
  203. package/index.d.ts +17 -2
  204. package/index.js +82 -231
  205. package/lib/utils.d.ts +8 -1
  206. package/lib/utils.js +1 -3
  207. package/package.json +11 -1
  208. package/styles.css +1 -1
  209. package/theme/create-theme.d.ts +6 -2
  210. package/theme/index.js +1 -0
  211. package/chunk-2HKBZFIK.js.map +0 -1
  212. package/chunk-3DINAQLL.js.map +0 -1
  213. package/chunk-3ERGAHKA.js +0 -179
  214. package/chunk-3ERGAHKA.js.map +0 -1
  215. package/chunk-6C7CGJX2.js +0 -86
  216. package/chunk-6C7CGJX2.js.map +0 -1
  217. package/chunk-6QMSWITQ.js.map +0 -1
  218. package/chunk-6YXUBP27.js.map +0 -1
  219. package/chunk-72OCFAPT.js.map +0 -1
  220. package/chunk-7TXHCRAG.js.map +0 -1
  221. package/chunk-A5XEM3GF.js.map +0 -1
  222. package/chunk-AN2RNJLR.js.map +0 -1
  223. package/chunk-B2K45IUR.js.map +0 -1
  224. package/chunk-B6V4VSGH.js.map +0 -1
  225. package/chunk-BKZBWPUH.js.map +0 -1
  226. package/chunk-BNTPPZCK.js.map +0 -1
  227. package/chunk-BNZVTLHV.js.map +0 -1
  228. package/chunk-CL2II6BX.js.map +0 -1
  229. package/chunk-D7RZNTFC.js +0 -95
  230. package/chunk-D7RZNTFC.js.map +0 -1
  231. package/chunk-DETGJAIC.js +0 -147
  232. package/chunk-DETGJAIC.js.map +0 -1
  233. package/chunk-DO3TBNSC.js.map +0 -1
  234. package/chunk-ESC5JCVQ.js +0 -90
  235. package/chunk-ESC5JCVQ.js.map +0 -1
  236. package/chunk-FDKIX4DC.js.map +0 -1
  237. package/chunk-GICKPMJU.js.map +0 -1
  238. package/chunk-GQA24FYG.js +0 -57
  239. package/chunk-GQA24FYG.js.map +0 -1
  240. package/chunk-H4NU7NPO.js.map +0 -1
  241. package/chunk-H63FYCMY.js +0 -11
  242. package/chunk-H63FYCMY.js.map +0 -1
  243. package/chunk-HL42K2NH.js.map +0 -1
  244. package/chunk-HNQUX43Z.js +0 -109
  245. package/chunk-HNQUX43Z.js.map +0 -1
  246. package/chunk-HRKPV66B.js +0 -32
  247. package/chunk-HRKPV66B.js.map +0 -1
  248. package/chunk-J3NSDRVH.js.map +0 -1
  249. package/chunk-JPNWHWAQ.js +0 -151
  250. package/chunk-JPNWHWAQ.js.map +0 -1
  251. package/chunk-KNUWZNFV.js.map +0 -1
  252. package/chunk-L6NCCSIP.js.map +0 -1
  253. package/chunk-LLHTVIM3.js.map +0 -1
  254. package/chunk-LW3TRU5W.js.map +0 -1
  255. package/chunk-LZMKSFCF.js.map +0 -1
  256. package/chunk-MR3JDI7E.js +0 -122
  257. package/chunk-MR3JDI7E.js.map +0 -1
  258. package/chunk-MYEZXZZC.js.map +0 -1
  259. package/chunk-NN6PKJWS.js.map +0 -1
  260. package/chunk-NSRTTYQ4.js.map +0 -1
  261. package/chunk-O7F3CIDV.js.map +0 -1
  262. package/chunk-P4O6TGDR.js.map +0 -1
  263. package/chunk-PF3YBUKT.js.map +0 -1
  264. package/chunk-PVOLDO4G.js +0 -47
  265. package/chunk-PVOLDO4G.js.map +0 -1
  266. package/chunk-QS4N4MNP.js.map +0 -1
  267. package/chunk-QUF2IPOZ.js.map +0 -1
  268. package/chunk-RTJ76X5U.js.map +0 -1
  269. package/chunk-SH6NG6VN.js.map +0 -1
  270. package/chunk-SHDFUXYV.js.map +0 -1
  271. package/chunk-TKO44NDI.js +0 -84
  272. package/chunk-TKO44NDI.js.map +0 -1
  273. package/chunk-TX3H3QMA.js.map +0 -1
  274. package/chunk-UBNHSZSE.js +0 -88
  275. package/chunk-UBNHSZSE.js.map +0 -1
  276. package/chunk-UC3ZJWOD.js +0 -73
  277. package/chunk-UC3ZJWOD.js.map +0 -1
  278. package/chunk-UGRSWP6U.js.map +0 -1
  279. package/chunk-VAGIAREV.js.map +0 -1
  280. package/chunk-WTMZT3IT.js +0 -105
  281. package/chunk-WTMZT3IT.js.map +0 -1
  282. package/chunk-WX6BP5ZP.js +0 -39
  283. package/chunk-WX6BP5ZP.js.map +0 -1
  284. package/chunk-X3PQANZO.js.map +0 -1
  285. package/chunk-XILQ7GXE.js.map +0 -1
  286. package/chunk-XL75JRUA.js.map +0 -1
  287. package/chunk-XZNHT6MO.js.map +0 -1
  288. package/chunk-Y5AYU7PK.js.map +0 -1
  289. package/chunk-YG7JOOLJ.js.map +0 -1
  290. package/chunk-YPJYW624.js +0 -195
  291. package/chunk-YPJYW624.js.map +0 -1
  292. package/chunk-YPNKBE5X.js.map +0 -1
  293. package/chunk-YX5VNRJX.js.map +0 -1
  294. package/components/accordion.js.map +0 -1
  295. package/components/agent-loading.js.map +0 -1
  296. package/components/agent-picker.js.map +0 -1
  297. package/components/agent-suggestion.js.map +0 -1
  298. package/components/announcement-bar.js.map +0 -1
  299. package/components/attachment.js.map +0 -1
  300. package/components/avatar.js.map +0 -1
  301. package/components/badge.js.map +0 -1
  302. package/components/banner-mesh.js.map +0 -1
  303. package/components/banner.js.map +0 -1
  304. package/components/bar-chart.js.map +0 -1
  305. package/components/breadcrumb.js.map +0 -1
  306. package/components/button.js.map +0 -1
  307. package/components/card.js.map +0 -1
  308. package/components/channel-chart.js.map +0 -1
  309. package/components/chart.js.map +0 -1
  310. package/components/checkbox.js.map +0 -1
  311. package/components/chip.js.map +0 -1
  312. package/components/citations.js.map +0 -1
  313. package/components/code-block.js.map +0 -1
  314. package/components/combobox.js.map +0 -1
  315. package/components/command-menu.js.map +0 -1
  316. package/components/context-menu.js.map +0 -1
  317. package/components/cookie-consent.js.map +0 -1
  318. package/components/date-picker.js.map +0 -1
  319. package/components/decision-card.js.map +0 -1
  320. package/components/dialog.js.map +0 -1
  321. package/components/donut-chart.js.map +0 -1
  322. package/components/dot.js.map +0 -1
  323. package/components/dropdown.js.map +0 -1
  324. package/components/empty-state.js.map +0 -1
  325. package/components/file-upload.js.map +0 -1
  326. package/components/floating.js.map +0 -1
  327. package/components/form-field.js.map +0 -1
  328. package/components/hover-card.js.map +0 -1
  329. package/components/input-otp.js.map +0 -1
  330. package/components/input.js.map +0 -1
  331. package/components/kbd.js.map +0 -1
  332. package/components/line-chart.js.map +0 -1
  333. package/components/message-actions.js.map +0 -1
  334. package/components/message.js.map +0 -1
  335. package/components/number-input.js.map +0 -1
  336. package/components/pagination.js.map +0 -1
  337. package/components/popover.js.map +0 -1
  338. package/components/progress.js.map +0 -1
  339. package/components/prompt-bar.js.map +0 -1
  340. package/components/radio.js.map +0 -1
  341. package/components/search-bar.js.map +0 -1
  342. package/components/segmented-control.js.map +0 -1
  343. package/components/select.js.map +0 -1
  344. package/components/sheet.js.map +0 -1
  345. package/components/sidebar.js.map +0 -1
  346. package/components/skeleton.js.map +0 -1
  347. package/components/slider.js.map +0 -1
  348. package/components/sliding-indicator.js.map +0 -1
  349. package/components/streaming-text.js.map +0 -1
  350. package/components/switch.js.map +0 -1
  351. package/components/table.js.map +0 -1
  352. package/components/tabs.js.map +0 -1
  353. package/components/textarea.js.map +0 -1
  354. package/components/thinking.js.map +0 -1
  355. package/components/toast.js.map +0 -1
  356. package/components/toggle.js.map +0 -1
  357. package/components/tooltip.js.map +0 -1
  358. package/index.js.map +0 -1
  359. package/lib/utils.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @uisatin/ui
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 51f930e: New components built from the ones Satin already has:
8
+
9
+ - Buttons: `ButtonGroup` (attached or spaced, with `ButtonGroupSeparator`), `SplitButton`, `ActionButton` (arrow, spinner, checkmark in one slot), and `loading` on `Button`.
10
+ - Forms: `Form` (one layout, errors by `name`, focus on the first invalid field, `onSubmitValues`), `FormSection`, `FormActions`, `FieldGroup`, `InputGroup` with `InputGroupAddon`, `PasswordInput`, `leadingText` / `trailingText` on `Input`, and `name` on `FormField`.
11
+ - Choices: `SelectableRadio` and `SelectableCheckbox`, in `sm` and `md`.
12
+ - Feedback and content: `Alert`, `Spinner`, `Separator`, `Link`, `List` with `Item`.
13
+
14
+ Fixes: `cn` now knows Satin's theme names (`text-body`, `rounded-pill`, `h-control-height`…), so `text-body` is no longer dropped next to a text colour (Banner descriptions, StreamingText and table cells take the theme's body size again) and app classes replace them as they should. Checkbox and Radio texts dim inside a disabled fieldset.
15
+
16
+ ## 0.3.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 0d40736: Satin now sits next to an app's own Tailwind or shadcn/ui theme without touching it. The stylesheet's classes carry Satin's prefix (`sa:flex`), its theme variables are `--sa-*` (`--sa-text-sm`, `--sa-color-blue-600`, `--sa-radius`, `--sa-chart-1`…), and Tailwind's reset and Satin's base rules apply only to Satin's elements, so the app's `text-sm`, `--spacing`, `--radius`, list styles and headings stay the app's in either import order. Tailwind classes passed in `className` still replace the Satin classes they conflict with.
21
+
22
+ Breaking for custom CSS that read Satin's primitive variables: use `--sa-color-*` and `--sa-radius-*` instead of `--color-*` and `--radius-*` (semantic tokens like `--bg-card` and `--action-primary-bg` are unchanged). `themeCss()` writes the new names. The shadcn registry ships the same prefixed source. The empty source maps are gone from the package.
23
+
24
+ - 9a4b332: Every component now takes ordinary HTML attributes and a `ref` (`id`, `data-*`, `aria-*`, `style`, handlers): fields pass them to the control a label points at (Select's trigger, NumberInput's input), overlays to their panel (Dialog, Sheet, Popover, menus, Tooltip's bubble). Each component's docs comment says where they go. Tabs' extra props are now typed.
25
+
26
+ New `SatinLabels` (`@uisatin/ui/labels`): the words components say on their own (Close, Increase, Select all rows, Pick a date…) are English by default and can be translated or reworded for an app or part of it. A component's own prop still wins.
27
+
28
+ Table: a column's `key` must be a field of the row unless the column renders its own `cell`, so a typo is a type error; rows no longer need an index signature. Internal helpers still exported from the root (`CloseIcon`, `menuItemClass`, `FieldChrome`…) are marked `@internal`.
29
+
3
30
  ## 0.2.0
4
31
 
5
32
  ### Minor Changes
package/README.md CHANGED
@@ -10,7 +10,7 @@ Satin's React components: shadcn-based, built on Radix, themed with Satin tokens
10
10
 
11
11
  **Satin Free.** This package is the free, open-source edition of Satin, under the MIT license. Satin Pro, with more components, patterns and templates, will ship separately as its own licensed package; nothing here changes when it does.
12
12
 
13
- You don't need Tailwind. Satin ships one precompiled stylesheet with the tokens and every class the components use.
13
+ You don't need Tailwind. Satin ships one precompiled stylesheet with the tokens and every class the components use. If your app has its own Tailwind (v3 or v4) or a shadcn/ui theme, the two don't touch: Satin's classes are prefixed (`sa:flex`), its variables are `--sa-*`, and its reset only applies to Satin's elements, so your `text-sm`, `--spacing` or `--radius` stay yours in either import order.
14
14
 
15
15
  ## Install
16
16
 
@@ -43,6 +43,15 @@ export function Save() {
43
43
 
44
44
  **Dark mode:** add the `dark` class to `<html>` or any parent element.
45
45
 
46
+ **Customizing:**
47
+
48
+ - Props first: `variant`, `size`, `tone`, `shape` cover what the design system allows.
49
+ - `className` takes your own classes and lands on the component's root. With Tailwind in your app, a utility there replaces the Satin class it conflicts with (`<Button className="px-6">` drops Satin's padding for yours). Without Tailwind, use your own CSS classes; a Tailwind class name alone does nothing, because Satin's stylesheet only contains its own prefixed classes.
50
+ - Theme: brand colour and corners with `themeCss({ brand, radius })` or the customizer at https://uisatin.dev/theming. Semantic tokens (`--bg-card`, `--text-muted`, `--action-primary-bg`…) can be set in your CSS too.
51
+ - Words: the labels components say on their own (Close, Increase, Select all rows…) are English by default. Wrap the app in `<SatinLabels labels={{ close: 'Zamknij' }}>` (from `@uisatin/ui/labels`) to translate or reword any of them.
52
+ - HTML attributes and `ref`: every component passes `id`, `data-*`, `aria-*`, handlers and `ref` to its main element (the control for fields, the panel for overlays); each component's docs comment says which.
53
+ - Satin's CSS sits in cascade layers (`theme`, `base`, `components`, `utilities`). Your unlayered rules win over it, so a global `p { margin: … }` also reaches a paragraph inside a Satin Card; scope those rules or put them in `@layer base`.
54
+
46
55
  **Font:** the tokens ask for Geist and Geist Mono; load them (for example with `@fontsource-variable/geist`) or the system font is used.
47
56
 
48
57
  ## Copy the source instead (shadcn registry)
@@ -1,6 +1,7 @@
1
- import { menuItemClass, MenuItemContent } from './chunk-3DINAQLL.js';
2
- import { Kbd, KbdHint, KbdArrowUp, KbdArrowDown, KbdReturn } from './chunk-BKZBWPUH.js';
3
- import { cn } from './chunk-H63FYCMY.js';
1
+ import { menuItemClass, MenuItemContent } from './chunk-P36KBUYD.js';
2
+ import { Kbd, KbdHint, KbdArrowUp, KbdArrowDown, KbdReturn } from './chunk-XWPH7C2W.js';
3
+ import { useSatinLabels } from './chunk-NTSU44FY.js';
4
+ import { cn } from './chunk-EHEXE2UV.js';
4
5
  import * as React from 'react';
5
6
  import { Dialog } from 'radix-ui';
6
7
  import { Search } from 'iconoir-react';
@@ -17,14 +18,16 @@ function CommandMenu({
17
18
  defaultOpen = false,
18
19
  onOpenChange,
19
20
  hotkey = true,
20
- placeholder = "Type a command or search\u2026",
21
+ placeholder,
21
22
  emptyText = (q) => `No results for \u201C${q}\u201D`,
22
23
  hints = true,
23
24
  modal = true,
24
25
  container,
25
26
  onOpenAutoFocus,
26
- className
27
+ className,
28
+ ...props
27
29
  }) {
30
+ const labels = useSatinLabels();
28
31
  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
29
32
  const open = openProp ?? uncontrolledOpen;
30
33
  const setOpen = React.useCallback(
@@ -69,24 +72,25 @@ function CommandMenu({
69
72
  const position = container ? "absolute" : "fixed";
70
73
  let index = -1;
71
74
  return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: setOpen, modal, children: /* @__PURE__ */ jsxs(Dialog.Portal, { container, children: [
72
- /* @__PURE__ */ jsx(Dialog.Overlay, { className: cn(position, "inset-0 z-50 bg-black-a40") }),
73
- /* @__PURE__ */ jsx("div", { className: cn(position, "pointer-events-none inset-0 z-50 flex items-center justify-center p-4"), children: /* @__PURE__ */ jsxs(
75
+ /* @__PURE__ */ jsx(Dialog.Overlay, { className: cn(position, "sa:inset-0 sa:z-50 sa:bg-black-a40") }),
76
+ /* @__PURE__ */ jsx("div", { className: cn(position, "sa:pointer-events-none sa:inset-0 sa:z-50 sa:flex sa:items-center sa:justify-center sa:p-4"), children: /* @__PURE__ */ jsxs(
74
77
  Dialog.Content,
75
78
  {
76
- "data-slot": "command-menu",
77
79
  "aria-describedby": void 0,
80
+ ...props,
81
+ "data-slot": "command-menu",
78
82
  onOpenAutoFocus,
79
83
  className: cn(
80
- "pointer-events-auto flex h-fit max-h-[min(480px,76vh)] w-[520px] max-w-full flex-col overflow-hidden",
81
- "rounded-2xl border border-border-subtle bg-bg-popover",
82
- "[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]",
83
- "outline-none data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]",
84
+ "sa:pointer-events-auto sa:flex sa:h-fit sa:max-h-[min(480px,76vh)] sa:w-[520px] sa:max-w-full sa:flex-col sa:overflow-hidden",
85
+ "sa:rounded-2xl sa:border sa:border-border-subtle sa:bg-bg-popover",
86
+ "sa:[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]",
87
+ "sa:outline-none sa:data-[state=open]:animate-[satin-enter_var(--sa-duration-base)_var(--sa-ease-out)]",
84
88
  className
85
89
  ),
86
90
  children: [
87
- /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: "Command menu" }),
88
- /* @__PURE__ */ jsxs("label", { className: "flex h-12 shrink-0 items-center gap-2 border-b border-border-subtle px-4 text-text-muted", children: [
89
- /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-4 shrink-0 [stroke-width:1.875]" }),
91
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "sa:sr-only", children: labels.commandMenu }),
92
+ /* @__PURE__ */ jsxs("label", { className: "sa:flex sa:h-12 sa:shrink-0 sa:items-center sa:gap-2 sa:border-b sa:border-border-subtle sa:px-4 sa:text-text-muted", children: [
93
+ /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "sa:size-4 sa:shrink-0 sa:[stroke-width:1.875]" }),
90
94
  /* @__PURE__ */ jsx(
91
95
  "input",
92
96
  {
@@ -95,9 +99,9 @@ function CommandMenu({
95
99
  "aria-controls": listId,
96
100
  "aria-autocomplete": "list",
97
101
  "aria-activedescendant": flat[active] ? optionId(active) : void 0,
98
- "aria-label": "Search commands",
102
+ "aria-label": labels.searchCommands,
99
103
  value: query,
100
- placeholder,
104
+ placeholder: placeholder ?? labels.commandPlaceholder,
101
105
  onChange: (e) => {
102
106
  setQuery(e.target.value);
103
107
  setActive(0);
@@ -112,13 +116,13 @@ function CommandMenu({
112
116
  run(flat[active]);
113
117
  }
114
118
  },
115
- className: "min-w-0 flex-1 bg-transparent text-base leading-[21px] text-text-default outline-none placeholder:text-text-muted focus-visible:ring-0"
119
+ className: "sa:min-w-0 sa:flex-1 sa:bg-transparent sa:text-base sa:leading-[21px] sa:text-text-default sa:outline-none sa:placeholder:text-text-muted sa:focus-visible:ring-0"
116
120
  }
117
121
  ),
118
122
  /* @__PURE__ */ jsx(Kbd, { size: "md", "aria-hidden": true, children: "Esc" })
119
123
  ] }),
120
- /* @__PURE__ */ jsx("div", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "flex min-h-0 flex-col gap-2 overflow-y-auto p-2", children: flat.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-8 text-center text-sm text-text-muted", children: emptyText(query) }) : shown.map((g, gi) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": `${listId}-g${gi}`, className: "flex flex-col", children: [
121
- /* @__PURE__ */ jsx("div", { id: `${listId}-g${gi}`, className: "flex h-6 items-center px-2 text-xs leading-3 font-medium tracking-normal text-text-muted", children: g.label }),
124
+ /* @__PURE__ */ jsx("div", { ref: listRef, id: listId, role: "listbox", "aria-label": labels.commands, className: "sa:flex sa:min-h-0 sa:flex-col sa:gap-2 sa:overflow-y-auto sa:p-2", children: flat.length === 0 ? /* @__PURE__ */ jsx("p", { className: "sa:px-2 sa:py-8 sa:text-center sa:text-sm sa:text-text-muted", children: emptyText(query) }) : shown.map((g, gi) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": `${listId}-g${gi}`, className: "sa:flex sa:flex-col", children: [
125
+ /* @__PURE__ */ jsx("div", { id: `${listId}-g${gi}`, className: "sa:flex sa:h-6 sa:items-center sa:px-2 sa:text-xs sa:leading-3 sa:font-medium sa:tracking-normal sa:text-text-muted", children: g.label }),
122
126
  g.items.map((item) => {
123
127
  index += 1;
124
128
  const i = index;
@@ -150,10 +154,10 @@ function CommandMenu({
150
154
  );
151
155
  })
152
156
  ] }, gi)) }),
153
- hints && /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "flex h-10 shrink-0 items-center gap-4 border-t border-border-subtle px-4", children: [
154
- /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdArrowUp, {}, "up"), /* @__PURE__ */ jsx(KbdArrowDown, {}, "down")], label: "Navigate" }),
155
- /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdReturn, {}, "return")], label: "Open" }),
156
- /* @__PURE__ */ jsx(KbdHint, { className: "ml-auto", keys: ["Esc"], label: "Close" })
157
+ hints && /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "sa:flex sa:h-10 sa:shrink-0 sa:items-center sa:gap-4 sa:border-t sa:border-border-subtle sa:px-4", children: [
158
+ /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdArrowUp, {}, "up"), /* @__PURE__ */ jsx(KbdArrowDown, {}, "down")], label: labels.navigate }),
159
+ /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdReturn, {}, "return")], label: labels.openItem }),
160
+ /* @__PURE__ */ jsx(KbdHint, { className: "sa:ml-auto", keys: ["Esc"], label: labels.close })
157
161
  ] })
158
162
  ]
159
163
  }
@@ -162,5 +166,3 @@ function CommandMenu({
162
166
  }
163
167
 
164
168
  export { CommandMenu };
165
- //# sourceMappingURL=chunk-P4O6TGDR.js.map
166
- //# sourceMappingURL=chunk-P4O6TGDR.js.map
@@ -0,0 +1,87 @@
1
+ import { HoverCard } from './chunk-W2EH6RY5.js';
2
+ import { useSatinLabels } from './chunk-NTSU44FY.js';
3
+ import { cn } from './chunk-EHEXE2UV.js';
4
+ import * as React from 'react';
5
+ import { jsx, jsxs } from 'react/jsx-runtime';
6
+
7
+ function SourceIcon({ source }) {
8
+ if (source.icon) return /* @__PURE__ */ jsx("span", { className: "sa:grid sa:size-4 sa:shrink-0 sa:place-items-center sa:overflow-clip sa:rounded-xs sa:[&>*]:size-4", children: source.icon });
9
+ return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "sa:grid sa:size-4 sa:shrink-0 sa:place-items-center sa:rounded-xs sa:bg-bg-muted sa:text-[10px] sa:leading-none sa:font-semibold sa:text-text-muted", children: source.title.charAt(0).toUpperCase() });
10
+ }
11
+ function Citation({ index, source, className, "aria-label": ariaLabel, ...props }) {
12
+ const labels = useSatinLabels();
13
+ const chip = /* @__PURE__ */ jsx(
14
+ "a",
15
+ {
16
+ ...props,
17
+ "data-slot": "citation",
18
+ href: source.href,
19
+ target: source.href ? "_blank" : void 0,
20
+ rel: source.href ? "noreferrer" : void 0,
21
+ "aria-label": ariaLabel ?? `${labels.source} ${index}: ${source.title}`,
22
+ className: cn(
23
+ "sa:mx-0.5 sa:inline-grid sa:h-4 sa:min-w-4 sa:translate-y-[-1px] sa:place-items-center sa:rounded-sm sa:bg-bg-muted sa:px-1 sa:align-middle sa:text-xs sa:leading-none sa:font-medium sa:text-text-default sa:no-underline sa:tabular-nums sa:outline-none",
24
+ "sa:transition-[background-color,box-shadow] sa:duration-(--sa-duration-fast) sa:ease-(--sa-ease-out)",
25
+ "sa:hover:bg-bg-hover sa:hover:[box-shadow:inset_0_0_0_1px_var(--border-strong)] sa:focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
26
+ className
27
+ ),
28
+ children: index
29
+ }
30
+ );
31
+ return /* @__PURE__ */ jsxs(HoverCard, { trigger: chip, side: "top", align: "center", className: "sa:w-[300px] sa:gap-2 sa:p-3", children: [
32
+ /* @__PURE__ */ jsxs("span", { className: "sa:flex sa:items-center sa:gap-2 sa:text-xs sa:text-text-muted", children: [
33
+ /* @__PURE__ */ jsx(SourceIcon, { source }),
34
+ /* @__PURE__ */ jsx("span", { className: "sa:truncate", children: source.origin })
35
+ ] }),
36
+ /* @__PURE__ */ jsx("span", { className: "sa:text-sm sa:font-medium sa:text-text-default", children: source.title }),
37
+ source.quote && /* @__PURE__ */ jsxs("span", { className: "sa:text-body sa:text-text-muted", children: [
38
+ "\u201C",
39
+ source.quote,
40
+ "\u201D"
41
+ ] })
42
+ ] });
43
+ }
44
+ function Sources({ sources, defaultOpen = false, className, ...props }) {
45
+ const [open, setOpen] = React.useState(defaultOpen);
46
+ const listId = React.useId();
47
+ return /* @__PURE__ */ jsxs("div", { ...props, "data-slot": "sources", className: cn("sa:flex sa:flex-col sa:gap-2", className), children: [
48
+ /* @__PURE__ */ jsxs(
49
+ "button",
50
+ {
51
+ type: "button",
52
+ "aria-expanded": open,
53
+ "aria-controls": listId,
54
+ onClick: () => setOpen(!open),
55
+ className: cn(
56
+ "sa:inline-flex sa:h-8 sa:w-fit sa:items-center sa:gap-2 sa:rounded-pill sa:border sa:border-border-default sa:py-1 sa:pr-3 sa:pl-1.5 sa:text-sm sa:font-medium sa:text-text-default sa:outline-none",
57
+ "sa:transition-[border-color,background-color] sa:duration-(--sa-duration-fast) sa:ease-(--sa-ease-out)",
58
+ "sa:hover:border-border-strong sa:focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
59
+ open && "sa:bg-bg-hover"
60
+ ),
61
+ children: [
62
+ /* @__PURE__ */ jsx("span", { className: "sa:flex sa:items-center sa:gap-0.5", children: sources.slice(0, 3).map((s, i) => /* @__PURE__ */ jsx(SourceIcon, { source: s }, i)) }),
63
+ sources.length,
64
+ " ",
65
+ sources.length === 1 ? "source" : "sources"
66
+ ]
67
+ }
68
+ ),
69
+ /* @__PURE__ */ jsx("div", { id: listId, "data-state": open ? "open" : "closed", className: "satin-expand", children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("ol", { className: "sa:flex sa:flex-col sa:gap-0.5", children: sources.map((s, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
70
+ "a",
71
+ {
72
+ href: s.href,
73
+ target: s.href ? "_blank" : void 0,
74
+ rel: s.href ? "noreferrer" : void 0,
75
+ className: "sa:flex sa:items-center sa:gap-3 sa:rounded-lg sa:p-2 sa:text-sm sa:no-underline sa:outline-none sa:transition-colors sa:duration-(--sa-duration-fast) sa:ease-(--sa-ease-out) sa:hover:bg-bg-hover sa:focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
76
+ children: [
77
+ /* @__PURE__ */ jsx("span", { className: "sa:grid sa:h-4 sa:min-w-4 sa:place-items-center sa:rounded-sm sa:bg-bg-muted sa:px-1 sa:text-xs sa:leading-none sa:font-medium sa:text-text-default sa:tabular-nums", children: i + 1 }),
78
+ /* @__PURE__ */ jsx(SourceIcon, { source: s }),
79
+ /* @__PURE__ */ jsx("span", { className: "sa:min-w-0 sa:flex-1 sa:truncate sa:text-text-default", children: s.title }),
80
+ s.origin && /* @__PURE__ */ jsx("span", { className: "sa:shrink-0 sa:text-text-muted", children: s.origin })
81
+ ]
82
+ }
83
+ ) }, i)) }) }) })
84
+ ] });
85
+ }
86
+
87
+ export { Citation, Sources };
@@ -1,6 +1,6 @@
1
- import { niceMax } from './chunk-DO3TBNSC.js';
2
- import { ChartCard, defaultFormat, ChartTooltip } from './chunk-YPJYW624.js';
3
- import { cn } from './chunk-H63FYCMY.js';
1
+ import { niceMax } from './chunk-INJWE2LD.js';
2
+ import { ChartCard, defaultFormat, ChartTooltip } from './chunk-LI5VYDLN.js';
3
+ import { cn } from './chunk-EHEXE2UV.js';
4
4
  import * as React from 'react';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
6
 
@@ -71,13 +71,13 @@ function LineCard({
71
71
  setHovered(Math.max(0, Math.min(n - 1, Math.round(f * (n - 1)))));
72
72
  };
73
73
  const fmt = (v) => `${formatValue(v)}${unit ? ` ${unit}` : ""}`;
74
- return /* @__PURE__ */ jsx(ChartCard, { total: total ?? defaultFormat(sum), ...props, children: /* @__PURE__ */ jsxs("div", { className: "relative pt-2 pl-8", children: [
74
+ return /* @__PURE__ */ jsx(ChartCard, { total: total ?? defaultFormat(sum), ...props, children: /* @__PURE__ */ jsxs("div", { className: "sa:relative sa:pt-2 sa:pl-8", children: [
75
75
  ticks.map((t, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
76
76
  i < 4 && /* @__PURE__ */ jsx(
77
77
  "span",
78
78
  {
79
79
  "aria-hidden": true,
80
- className: "absolute right-0 left-8 h-px border-t border-dashed border-border-subtle",
80
+ className: "sa:absolute sa:right-0 sa:left-8 sa:h-px sa:border-t sa:border-dashed sa:border-border-subtle",
81
81
  style: { top: 8 + TRACK / 4 * i }
82
82
  }
83
83
  ),
@@ -85,7 +85,7 @@ function LineCard({
85
85
  "span",
86
86
  {
87
87
  "aria-hidden": true,
88
- className: cn("absolute left-6 w-6 -translate-x-full text-right text-xs leading-[18px] text-text-muted", fade && "satin-bar-fade"),
88
+ className: cn("sa:absolute sa:left-6 sa:w-6 sa:-translate-x-full sa:text-right sa:text-xs sa:leading-[18px] sa:text-text-muted", fade && "satin-bar-fade"),
89
89
  style: { top: 8 + TRACK / 4 * i - 9 },
90
90
  children: formatValue(t)
91
91
  },
@@ -98,7 +98,7 @@ function LineCard({
98
98
  role: "group",
99
99
  "aria-label": `${props.title}, ${n} points`,
100
100
  tabIndex: 0,
101
- className: "relative rounded-md outline-none focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
101
+ className: "sa:relative sa:rounded-md sa:outline-none sa:focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
102
102
  style: { height: TRACK },
103
103
  onPointerMove: pick,
104
104
  onPointerLeave: () => setHovered(null),
@@ -116,12 +116,12 @@ function LineCard({
116
116
  "aria-hidden": true,
117
117
  viewBox: `0 0 100 ${TRACK}`,
118
118
  preserveAspectRatio: "none",
119
- className: cn("absolute inset-0 size-full overflow-visible", fade && "satin-bar-fade"),
119
+ className: cn("sa:absolute sa:inset-0 sa:size-full sa:overflow-visible", fade && "satin-bar-fade"),
120
120
  children: [
121
121
  area && /* @__PURE__ */ jsxs(Fragment, { children: [
122
122
  /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", x2: "0", y1: "0", y2: "1", children: [
123
- /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "var(--chart-3)", stopOpacity: "0.28" }),
124
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "var(--chart-3)", stopOpacity: "0" })
123
+ /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "var(--sa-chart-3)", stopOpacity: "0.28" }),
124
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "var(--sa-chart-3)", stopOpacity: "0" })
125
125
  ] }) }),
126
126
  /* @__PURE__ */ jsx("path", { d: `${line} L 100 ${TRACK} L 0 ${TRACK} Z`, fill: `url(#${gradientId})` })
127
127
  ] }),
@@ -142,7 +142,7 @@ function LineCard({
142
142
  {
143
143
  d: line,
144
144
  fill: "none",
145
- stroke: "var(--chart-3)",
145
+ stroke: "var(--sa-chart-3)",
146
146
  strokeWidth: 2,
147
147
  strokeLinecap: "round",
148
148
  strokeLinejoin: "round",
@@ -159,23 +159,23 @@ function LineCard({
159
159
  {
160
160
  ref: setAnchor,
161
161
  "aria-hidden": true,
162
- className: "pointer-events-none absolute size-2 -translate-1/2 rounded-full border-2 border-chart-3 bg-bg-card",
162
+ className: "sa:pointer-events-none sa:absolute sa:size-2 sa:-translate-1/2 sa:rounded-full sa:border-2 sa:border-chart-3 sa:bg-bg-card",
163
163
  style: { left: `${x(active)}%`, top: y(data[active].value) }
164
164
  }
165
165
  ),
166
166
  /* @__PURE__ */ jsx(ChartTooltip, { anchor, sideOffset: 6, label: data[active].tooltipLabel ?? data[active].label, value: fmt(data[active].value) }),
167
- /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: `${data[active].tooltipLabel ?? data[active].label}: ${fmt(data[active].value)}` })
167
+ /* @__PURE__ */ jsx("span", { className: "sa:sr-only", "aria-live": "polite", children: `${data[active].tooltipLabel ?? data[active].label}: ${fmt(data[active].value)}` })
168
168
  ] })
169
169
  ]
170
170
  }
171
171
  ),
172
- /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "relative mt-1.5 h-5", children: data.map(
172
+ /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "sa:relative sa:mt-1.5 sa:h-5", children: data.map(
173
173
  (d, i) => showLabel(i) ? /* @__PURE__ */ jsx(
174
174
  "span",
175
175
  {
176
176
  className: cn(
177
- "absolute -translate-x-1/2 text-sm leading-(--text-sm--line-height) whitespace-nowrap",
178
- i === active ? "font-medium text-text-default" : "text-text-muted",
177
+ "sa:absolute sa:-translate-x-1/2 sa:text-sm sa:leading-(--sa-text-sm--line-height) sa:whitespace-nowrap",
178
+ i === active ? "sa:font-medium sa:text-text-default" : "sa:text-text-muted",
179
179
  fade && "satin-bar-fade"
180
180
  ),
181
181
  style: { left: `${x(i)}%` },
@@ -191,5 +191,3 @@ function AreaCard(props) {
191
191
  }
192
192
 
193
193
  export { AreaCard, LineCard };
194
- //# sourceMappingURL=chunk-SHDFUXYV.js.map
195
- //# sourceMappingURL=chunk-SHDFUXYV.js.map
@@ -0,0 +1,99 @@
1
+ import { cn } from './chunk-EHEXE2UV.js';
2
+ import * as React from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var ListContext = React.createContext(null);
6
+ function Item({
7
+ title,
8
+ description,
9
+ icon,
10
+ media,
11
+ meta,
12
+ actions,
13
+ href,
14
+ target,
15
+ onClick,
16
+ selected = false,
17
+ disabled = false,
18
+ size: ownSize,
19
+ variant = "plain",
20
+ className,
21
+ children,
22
+ ...props
23
+ }) {
24
+ const list = React.useContext(ListContext);
25
+ const size = ownSize ?? list?.size ?? "md";
26
+ const sm = size === "sm";
27
+ const interactive = (href !== void 0 || onClick !== void 0) && !disabled;
28
+ const Root = list ? "li" : "div";
29
+ const flush = list?.variant === "divided" || list?.variant === "card";
30
+ const target_ = "sa:outline-none sa:after:absolute sa:after:inset-0";
31
+ const titleText = /* @__PURE__ */ jsx("span", { className: "sa:block sa:truncate", children: title });
32
+ const titleNode = href !== void 0 && !disabled ? /* @__PURE__ */ jsx("a", { href, target, rel: target === "_blank" ? "noopener noreferrer" : void 0, "data-slot": "item-target", "aria-current": selected ? "page" : void 0, className: cn(target_, "sa:no-underline sa:text-inherit"), children: titleText }) : onClick && !disabled ? /* @__PURE__ */ jsx("button", { type: "button", "data-slot": "item-target", "aria-pressed": selected || void 0, onClick, className: cn(target_, "sa:block sa:w-full sa:cursor-pointer sa:text-left"), children: titleText }) : titleText;
33
+ return /* @__PURE__ */ jsxs(
34
+ Root,
35
+ {
36
+ "data-slot": "item",
37
+ "data-size": size,
38
+ "data-selected": selected || void 0,
39
+ "data-disabled": disabled || void 0,
40
+ className: cn(
41
+ "sa:relative sa:flex sa:min-w-0 sa:items-center",
42
+ sm ? "sa:min-h-10 sa:gap-2.5 sa:px-2 sa:py-1.5" : "sa:min-h-14 sa:gap-3 sa:px-3 sa:py-2.5",
43
+ flush ? list?.variant === "card" ? sm ? "sa:px-3" : "sa:px-4" : "sa:px-0" : "sa:rounded-lg",
44
+ variant === "sa:outline" && !list && "sa:border sa:border-border-default sa:bg-bg-card sa:[box-shadow:0_1px_2px_0_var(--effect-shadow-xs)]",
45
+ "sa:transition-colors sa:duration-(--sa-duration-fast) sa:ease-(--sa-ease-out)",
46
+ interactive && "sa:hover:bg-bg-hover",
47
+ interactive && flush && list?.variant === "divided" && "sa:hover:bg-transparent sa:[&:hover_[data-slot=item-title]]:underline",
48
+ selected && "sa:bg-bg-selected sa:hover:bg-bg-selected",
49
+ // The focus ring of the stretched link, drawn on the row.
50
+ "sa:has-[[data-slot=item-target]:focus-visible]:[box-shadow:inset_0_0_0_2px_var(--action-focus-ring)]",
51
+ disabled && "sa:opacity-50",
52
+ className
53
+ ),
54
+ ...props,
55
+ children: [
56
+ media ? /* @__PURE__ */ jsx("span", { className: "sa:flex sa:shrink-0 sa:items-center", children: media }) : icon ? /* @__PURE__ */ jsx(
57
+ "span",
58
+ {
59
+ "aria-hidden": true,
60
+ className: cn(
61
+ "sa:grid sa:shrink-0 sa:place-items-center sa:rounded-lg sa:bg-bg-muted sa:text-text-muted sa:[&_svg]:size-icon-size sa:[&_svg]:[stroke-width:1.875]",
62
+ sm ? "sa:size-7" : "sa:size-8"
63
+ ),
64
+ children: icon
65
+ }
66
+ ) : null,
67
+ /* @__PURE__ */ jsxs("div", { className: "sa:min-w-0 sa:flex-1", children: [
68
+ /* @__PURE__ */ jsx("div", { "data-slot": "item-title", className: "sa:text-sm sa:leading-5 sa:font-medium sa:text-text-default sa:underline-offset-[3px]", children: titleNode }),
69
+ description && /* @__PURE__ */ jsx("p", { className: "sa:truncate sa:text-sm sa:leading-5 sa:text-text-muted", children: description }),
70
+ children && /* @__PURE__ */ jsx("div", { className: "sa:mt-1.5", children })
71
+ ] }),
72
+ meta && /* @__PURE__ */ jsx("div", { className: "sa:shrink-0 sa:text-sm sa:text-text-muted sa:tabular-nums", children: meta }),
73
+ actions && // Above the stretched target, so they stay their own controls.
74
+ /* @__PURE__ */ jsx("div", { className: "sa:relative sa:z-10 sa:flex sa:shrink-0 sa:items-center sa:gap-1", children: actions })
75
+ ]
76
+ }
77
+ );
78
+ }
79
+ function List({ variant = "plain", size = "md", className, ...props }) {
80
+ const context = React.useMemo(() => ({ variant, size }), [variant, size]);
81
+ return /* @__PURE__ */ jsx(ListContext.Provider, { value: context, children: /* @__PURE__ */ jsx(
82
+ "ul",
83
+ {
84
+ role: "list",
85
+ "data-slot": "list",
86
+ "data-variant": variant,
87
+ className: cn(
88
+ "sa:m-0 sa:flex sa:w-full sa:list-none sa:flex-col sa:p-0",
89
+ variant === "plain" && "sa:gap-0.5",
90
+ variant !== "plain" && "sa:divide-y sa:divide-border-default",
91
+ variant === "card" && "sa:overflow-hidden sa:rounded-xl sa:border sa:border-border-default sa:bg-bg-card sa:[box-shadow:0_1px_2px_0_var(--effect-shadow-xs)]",
92
+ className
93
+ ),
94
+ ...props
95
+ }
96
+ ) });
97
+ }
98
+
99
+ export { Item, List };
@@ -0,0 +1,130 @@
1
+ import { Spinner } from './chunk-AKEZCWNW.js';
2
+ import { cn } from './chunk-EHEXE2UV.js';
3
+ import * as React from 'react';
4
+ import { Slot } from 'radix-ui';
5
+ import { cva } from 'class-variance-authority';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+
8
+ var buttonVariants = cva(
9
+ [
10
+ "sa:inline-flex sa:shrink-0 sa:items-center sa:justify-center sa:overflow-clip sa:font-medium sa:whitespace-nowrap sa:select-none",
11
+ "sa:transition-[background-color,border-color,color,box-shadow,transform] sa:duration-(--sa-duration-fast) sa:ease-(--sa-ease-out)",
12
+ // A menu or popover trigger snaps back to full size the moment it opens (no scale, no
13
+ // transform transition), so the menu measures the button's real edge and never jumps.
14
+ "sa:not-aria-expanded:active:scale-[0.97] sa:aria-expanded:[transition-property:background-color,border-color,color,box-shadow]",
15
+ "sa:disabled:pointer-events-none sa:disabled:opacity-50",
16
+ "sa:focus-visible:outline-none sa:[&_svg]:pointer-events-none sa:[&_svg]:shrink-0",
17
+ // Figma icons are 1.25px at 16 and 1.09px at 14; on Iconoir's 24 grid both are 1.875.
18
+ "sa:[&_svg]:[stroke-width:1.875]"
19
+ ],
20
+ {
21
+ variants: {
22
+ variant: {
23
+ primary: [
24
+ "sa:border sa:border-action-primary-border sa:bg-action-primary-bg sa:text-action-primary-fg",
25
+ "sa:[box-shadow:0_0_0_1px_var(--action-primary-bg),0_3px_6px_0_var(--action-primary-shadow)]",
26
+ "sa:satin-hover:bg-action-primary-bg-hover sa:satin-hover:[box-shadow:0_0_0_1px_var(--action-primary-bg-hover),0_3px_6px_0_var(--action-primary-shadow)]",
27
+ "sa:satin-focus:[box-shadow:0_0_0_1px_var(--action-primary-bg),0_3px_6px_0_var(--action-primary-shadow),0_0_0_2px_var(--action-focus-ring)]",
28
+ "sa:satin-pressed:bg-action-primary-bg-pressed sa:satin-pressed:[box-shadow:0_0_0_1px_var(--action-primary-bg-pressed)]",
29
+ "sa:[&[aria-haspopup][aria-expanded=true]:focus-visible]:[box-shadow:0_0_0_1px_var(--action-primary-bg-pressed),0_0_0_2px_var(--action-focus-ring)]"
30
+ ],
31
+ destructive: [
32
+ "sa:border sa:border-action-destructive-border sa:bg-action-destructive-bg sa:text-text-on-solid",
33
+ "sa:[box-shadow:0_0_0_1px_var(--action-destructive-bg),0_3px_6px_0_var(--action-primary-shadow)]",
34
+ "sa:satin-hover:bg-action-destructive-bg-hover sa:satin-hover:[box-shadow:0_0_0_1px_var(--action-destructive-bg-hover),0_3px_6px_0_var(--action-primary-shadow)]",
35
+ "sa:satin-focus:[box-shadow:0_0_0_1px_var(--action-destructive-bg),0_3px_6px_0_var(--action-primary-shadow),0_0_0_2px_var(--action-focus-ring)]",
36
+ "sa:satin-pressed:bg-action-destructive-bg-pressed sa:satin-pressed:[box-shadow:0_0_0_1px_var(--action-destructive-bg-pressed)]",
37
+ "sa:[&[aria-haspopup][aria-expanded=true]:focus-visible]:[box-shadow:0_0_0_1px_var(--action-destructive-bg-pressed),0_0_0_2px_var(--action-focus-ring)]"
38
+ ],
39
+ inverse: [
40
+ "sa:border sa:border-action-inverse-border sa:bg-action-inverse-bg sa:text-text-on-inverse",
41
+ "sa:[box-shadow:0_0_0_1px_var(--action-inverse-bg),0_3px_6px_0_var(--action-primary-shadow)]",
42
+ "sa:satin-hover:bg-action-inverse-bg-hover sa:satin-hover:[box-shadow:0_0_0_1px_var(--action-inverse-bg-hover),0_3px_6px_0_var(--action-primary-shadow)]",
43
+ "sa:satin-focus:[box-shadow:0_0_0_1px_var(--action-inverse-bg),0_3px_6px_0_var(--action-primary-shadow),0_0_0_2px_var(--action-focus-ring)]",
44
+ "sa:satin-pressed:bg-action-inverse-bg-pressed sa:satin-pressed:[box-shadow:0_0_0_1px_var(--action-inverse-bg-pressed)]",
45
+ "sa:[&[aria-haspopup][aria-expanded=true]:focus-visible]:[box-shadow:0_0_0_1px_var(--action-inverse-bg-pressed),0_0_0_2px_var(--action-focus-ring)]"
46
+ ],
47
+ // The outline is a 1px ring outside the box, like the filled variants' ring, so all of
48
+ // them read the same height; the border underneath takes the fill.
49
+ secondary: [
50
+ "sa:border sa:border-transparent sa:bg-bg-popover sa:text-text-default sa:[&_svg]:text-text-muted",
51
+ "sa:[box-shadow:0_0_0_1px_var(--border-default),0_1px_2px_1px_var(--effect-shadow-xs)]",
52
+ "sa:disabled:[box-shadow:0_0_0_1px_var(--border-strong)]",
53
+ "sa:satin-hover:bg-action-secondary-bg-hover sa:satin-hover:[box-shadow:0_0_0_1px_var(--border-strong),0_1px_2px_1px_var(--effect-shadow-xs)]",
54
+ "sa:satin-focus:bg-bg-popover sa:satin-focus:[box-shadow:0_0_0_1px_var(--border-strong),0_0_0_2px_var(--action-focus-ring)]",
55
+ "sa:satin-pressed:bg-action-secondary-bg-pressed sa:satin-pressed:[box-shadow:0_0_0_1px_var(--border-strong)]",
56
+ "sa:[&[aria-haspopup][aria-expanded=true]:focus-visible]:[box-shadow:0_0_0_1px_var(--border-strong),0_0_0_2px_var(--action-focus-ring)]"
57
+ ],
58
+ tertiary: [
59
+ "sa:bg-transparent sa:text-text-default sa:[&_svg]:text-text-muted",
60
+ "sa:satin-hover:bg-bg-hover",
61
+ "sa:satin-focus:bg-bg-hover sa:satin-focus:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
62
+ "sa:satin-pressed:bg-border-input",
63
+ "sa:[&[aria-haspopup][aria-expanded=true]:focus-visible]:[box-shadow:0_0_0_2px_var(--action-focus-ring)]"
64
+ ]
65
+ },
66
+ size: {
67
+ xs: "sa:h-control-height-xs sa:gap-1 sa:px-2 sa:text-sm sa:[&_svg]:size-icon-size-sm",
68
+ md: "sa:h-control-height sa:gap-1.5 sa:px-2.5 sa:text-sm sa:[&_svg]:size-icon-size",
69
+ lg: "sa:h-control-height-lg sa:gap-1.5 sa:px-3 sa:text-sm sa:[&_svg]:size-icon-size",
70
+ xl: "sa:h-control-height-xl sa:gap-2 sa:px-3 sa:text-base sa:[&_svg]:size-icon-size"
71
+ },
72
+ shape: {
73
+ default: "",
74
+ rounded: "sa:rounded-pill"
75
+ },
76
+ iconOnly: {
77
+ true: "sa:px-0",
78
+ false: ""
79
+ }
80
+ },
81
+ compoundVariants: [
82
+ // Default shape: the radius grows with the size (8 / 10 / 10 / 12).
83
+ { shape: "default", size: "xs", className: "sa:rounded-md" },
84
+ { shape: "default", size: "md", className: "sa:rounded-lg" },
85
+ { shape: "default", size: "lg", className: "sa:rounded-lg" },
86
+ { shape: "default", size: "xl", className: "sa:rounded-xl" },
87
+ { iconOnly: true, size: "xs", className: "sa:w-control-height-xs" },
88
+ { iconOnly: true, size: "md", className: "sa:w-control-height" },
89
+ { iconOnly: true, size: "lg", className: "sa:w-control-height-lg" },
90
+ { iconOnly: true, size: "xl", className: "sa:w-control-height-xl" }
91
+ ],
92
+ defaultVariants: { variant: "primary", size: "md", shape: "default", iconOnly: false }
93
+ }
94
+ );
95
+ var ButtonDefaultsContext = React.createContext(null);
96
+ function Button({ className, variant, size, shape, iconOnly, asChild = false, loading = false, type, onClick, children, "aria-disabled": ariaDisabled, ...props }) {
97
+ const Comp = asChild ? Slot.Root : "button";
98
+ const group = React.useContext(ButtonDefaultsContext);
99
+ const resolved = variant ?? group?.variant ?? "primary";
100
+ return /* @__PURE__ */ jsx(
101
+ Comp,
102
+ {
103
+ "data-slot": "button",
104
+ "data-variant": resolved,
105
+ type: asChild ? void 0 : type ?? "button",
106
+ "aria-busy": loading || void 0,
107
+ "aria-disabled": loading || ariaDisabled || void 0,
108
+ "data-loading": loading || void 0,
109
+ className: cn(
110
+ buttonVariants({ variant: resolved, size: size ?? group?.size, shape: shape ?? group?.shape, iconOnly }),
111
+ loading && "sa:relative sa:cursor-progress",
112
+ className
113
+ ),
114
+ onClick: (event) => {
115
+ if (loading) {
116
+ event.preventDefault();
117
+ return;
118
+ }
119
+ onClick?.(event);
120
+ },
121
+ ...props,
122
+ children: loading && !asChild ? /* @__PURE__ */ jsxs(Fragment, { children: [
123
+ /* @__PURE__ */ jsx("span", { className: "sa:invisible sa:contents", children }),
124
+ /* @__PURE__ */ jsx("span", { className: "sa:absolute sa:inset-0 sa:grid sa:place-items-center", children: /* @__PURE__ */ jsx(Spinner, { size: (size ?? group?.size) === "xs" ? "sm" : "md", label: null }) })
125
+ ] }) : children
126
+ }
127
+ );
128
+ }
129
+
130
+ export { Button, ButtonDefaultsContext, buttonVariants };