@uisatin/ui 0.0.0-stage → 0.1.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 (329) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -2
  3. package/chunk-2HKBZFIK.js +339 -0
  4. package/chunk-2HKBZFIK.js.map +1 -0
  5. package/chunk-2YEWSJD7.js +95 -0
  6. package/chunk-2YEWSJD7.js.map +1 -0
  7. package/chunk-3DINAQLL.js +153 -0
  8. package/chunk-3DINAQLL.js.map +1 -0
  9. package/chunk-3ERGAHKA.js +179 -0
  10. package/chunk-3ERGAHKA.js.map +1 -0
  11. package/chunk-6C7CGJX2.js +86 -0
  12. package/chunk-6C7CGJX2.js.map +1 -0
  13. package/chunk-6YXUBP27.js +474 -0
  14. package/chunk-6YXUBP27.js.map +1 -0
  15. package/chunk-72OCFAPT.js +175 -0
  16. package/chunk-72OCFAPT.js.map +1 -0
  17. package/chunk-7TXHCRAG.js +51 -0
  18. package/chunk-7TXHCRAG.js.map +1 -0
  19. package/chunk-A5XEM3GF.js +260 -0
  20. package/chunk-A5XEM3GF.js.map +1 -0
  21. package/chunk-AN2RNJLR.js +79 -0
  22. package/chunk-AN2RNJLR.js.map +1 -0
  23. package/chunk-B2K45IUR.js +36 -0
  24. package/chunk-B2K45IUR.js.map +1 -0
  25. package/chunk-B6V4VSGH.js +82 -0
  26. package/chunk-B6V4VSGH.js.map +1 -0
  27. package/chunk-BKZBWPUH.js +59 -0
  28. package/chunk-BKZBWPUH.js.map +1 -0
  29. package/chunk-BNTPPZCK.js +220 -0
  30. package/chunk-BNTPPZCK.js.map +1 -0
  31. package/chunk-BNZVTLHV.js +98 -0
  32. package/chunk-BNZVTLHV.js.map +1 -0
  33. package/chunk-CL2II6BX.js +89 -0
  34. package/chunk-CL2II6BX.js.map +1 -0
  35. package/chunk-DETGJAIC.js +147 -0
  36. package/chunk-DETGJAIC.js.map +1 -0
  37. package/chunk-DO3TBNSC.js +130 -0
  38. package/chunk-DO3TBNSC.js.map +1 -0
  39. package/chunk-ESC5JCVQ.js +90 -0
  40. package/chunk-ESC5JCVQ.js.map +1 -0
  41. package/chunk-FDKIX4DC.js +55 -0
  42. package/chunk-FDKIX4DC.js.map +1 -0
  43. package/chunk-GICKPMJU.js +239 -0
  44. package/chunk-GICKPMJU.js.map +1 -0
  45. package/chunk-GQA24FYG.js +57 -0
  46. package/chunk-GQA24FYG.js.map +1 -0
  47. package/chunk-H4NU7NPO.js +264 -0
  48. package/chunk-H4NU7NPO.js.map +1 -0
  49. package/chunk-H63FYCMY.js +11 -0
  50. package/chunk-H63FYCMY.js.map +1 -0
  51. package/chunk-HL42K2NH.js +76 -0
  52. package/chunk-HL42K2NH.js.map +1 -0
  53. package/chunk-HNQUX43Z.js +109 -0
  54. package/chunk-HNQUX43Z.js.map +1 -0
  55. package/chunk-HRKPV66B.js +32 -0
  56. package/chunk-HRKPV66B.js.map +1 -0
  57. package/chunk-J3NSDRVH.js +83 -0
  58. package/chunk-J3NSDRVH.js.map +1 -0
  59. package/chunk-JPNWHWAQ.js +151 -0
  60. package/chunk-JPNWHWAQ.js.map +1 -0
  61. package/chunk-KNUWZNFV.js +240 -0
  62. package/chunk-KNUWZNFV.js.map +1 -0
  63. package/chunk-L6NCCSIP.js +213 -0
  64. package/chunk-L6NCCSIP.js.map +1 -0
  65. package/chunk-LLHTVIM3.js +50 -0
  66. package/chunk-LLHTVIM3.js.map +1 -0
  67. package/chunk-LW3TRU5W.js +131 -0
  68. package/chunk-LW3TRU5W.js.map +1 -0
  69. package/chunk-LZMKSFCF.js +79 -0
  70. package/chunk-LZMKSFCF.js.map +1 -0
  71. package/chunk-MR3JDI7E.js +122 -0
  72. package/chunk-MR3JDI7E.js.map +1 -0
  73. package/chunk-NN6PKJWS.js +44 -0
  74. package/chunk-NN6PKJWS.js.map +1 -0
  75. package/chunk-NSRTTYQ4.js +252 -0
  76. package/chunk-NSRTTYQ4.js.map +1 -0
  77. package/chunk-O7F3CIDV.js +45 -0
  78. package/chunk-O7F3CIDV.js.map +1 -0
  79. package/chunk-P4O6TGDR.js +166 -0
  80. package/chunk-P4O6TGDR.js.map +1 -0
  81. package/chunk-PF3YBUKT.js +81 -0
  82. package/chunk-PF3YBUKT.js.map +1 -0
  83. package/chunk-PVOLDO4G.js +47 -0
  84. package/chunk-PVOLDO4G.js.map +1 -0
  85. package/chunk-QS4N4MNP.js +215 -0
  86. package/chunk-QS4N4MNP.js.map +1 -0
  87. package/chunk-QUF2IPOZ.js +98 -0
  88. package/chunk-QUF2IPOZ.js.map +1 -0
  89. package/chunk-RTJ76X5U.js +126 -0
  90. package/chunk-RTJ76X5U.js.map +1 -0
  91. package/chunk-SH6NG6VN.js +40 -0
  92. package/chunk-SH6NG6VN.js.map +1 -0
  93. package/chunk-SHDFUXYV.js +195 -0
  94. package/chunk-SHDFUXYV.js.map +1 -0
  95. package/chunk-TKO44NDI.js +84 -0
  96. package/chunk-TKO44NDI.js.map +1 -0
  97. package/chunk-TOMSU4S4.js +149 -0
  98. package/chunk-TOMSU4S4.js.map +1 -0
  99. package/chunk-TVLGZGYN.js +59 -0
  100. package/chunk-TVLGZGYN.js.map +1 -0
  101. package/chunk-TX3H3QMA.js +520 -0
  102. package/chunk-TX3H3QMA.js.map +1 -0
  103. package/chunk-UBNHSZSE.js +88 -0
  104. package/chunk-UBNHSZSE.js.map +1 -0
  105. package/chunk-UC3ZJWOD.js +73 -0
  106. package/chunk-UC3ZJWOD.js.map +1 -0
  107. package/chunk-UGRSWP6U.js +69 -0
  108. package/chunk-UGRSWP6U.js.map +1 -0
  109. package/chunk-VAGIAREV.js +214 -0
  110. package/chunk-VAGIAREV.js.map +1 -0
  111. package/chunk-WTMZT3IT.js +105 -0
  112. package/chunk-WTMZT3IT.js.map +1 -0
  113. package/chunk-WX6BP5ZP.js +39 -0
  114. package/chunk-WX6BP5ZP.js.map +1 -0
  115. package/chunk-X3PQANZO.js +255 -0
  116. package/chunk-X3PQANZO.js.map +1 -0
  117. package/chunk-XILQ7GXE.js +66 -0
  118. package/chunk-XILQ7GXE.js.map +1 -0
  119. package/chunk-XL75JRUA.js +130 -0
  120. package/chunk-XL75JRUA.js.map +1 -0
  121. package/chunk-XZNHT6MO.js +348 -0
  122. package/chunk-XZNHT6MO.js.map +1 -0
  123. package/chunk-Y5AYU7PK.js +44 -0
  124. package/chunk-Y5AYU7PK.js.map +1 -0
  125. package/chunk-YG7JOOLJ.js +28 -0
  126. package/chunk-YG7JOOLJ.js.map +1 -0
  127. package/chunk-YPJYW624.js +195 -0
  128. package/chunk-YPJYW624.js.map +1 -0
  129. package/chunk-YPNKBE5X.js +104 -0
  130. package/chunk-YPNKBE5X.js.map +1 -0
  131. package/components/accordion.d.ts +27 -0
  132. package/components/accordion.js +4 -0
  133. package/components/accordion.js.map +1 -0
  134. package/components/agent-loading.d.ts +65 -0
  135. package/components/agent-loading.js +4 -0
  136. package/components/agent-loading.js.map +1 -0
  137. package/components/agent-picker.d.ts +82 -0
  138. package/components/agent-picker.js +5 -0
  139. package/components/agent-picker.js.map +1 -0
  140. package/components/agent-suggestion.d.ts +69 -0
  141. package/components/agent-suggestion.js +6 -0
  142. package/components/agent-suggestion.js.map +1 -0
  143. package/components/announcement-bar.d.ts +39 -0
  144. package/components/announcement-bar.js +6 -0
  145. package/components/announcement-bar.js.map +1 -0
  146. package/components/attachment.d.ts +73 -0
  147. package/components/attachment.js +5 -0
  148. package/components/attachment.js.map +1 -0
  149. package/components/avatar.d.ts +34 -0
  150. package/components/avatar.js +6 -0
  151. package/components/avatar.js.map +1 -0
  152. package/components/badge.d.ts +19 -0
  153. package/components/badge.js +4 -0
  154. package/components/badge.js.map +1 -0
  155. package/components/banner.d.ts +54 -0
  156. package/components/banner.js +5 -0
  157. package/components/banner.js.map +1 -0
  158. package/components/bar-chart.d.ts +32 -0
  159. package/components/bar-chart.js +11 -0
  160. package/components/bar-chart.js.map +1 -0
  161. package/components/breadcrumb.d.ts +32 -0
  162. package/components/breadcrumb.js +6 -0
  163. package/components/breadcrumb.js.map +1 -0
  164. package/components/button.d.ts +32 -0
  165. package/components/button.js +4 -0
  166. package/components/button.js.map +1 -0
  167. package/components/card.d.ts +28 -0
  168. package/components/card.js +5 -0
  169. package/components/card.js.map +1 -0
  170. package/components/channel-chart.d.ts +14 -0
  171. package/components/channel-chart.js +11 -0
  172. package/components/channel-chart.js.map +1 -0
  173. package/components/chart.d.ts +88 -0
  174. package/components/chart.js +10 -0
  175. package/components/chart.js.map +1 -0
  176. package/components/checkbox.d.ts +17 -0
  177. package/components/checkbox.js +4 -0
  178. package/components/checkbox.js.map +1 -0
  179. package/components/chip.d.ts +54 -0
  180. package/components/chip.js +4 -0
  181. package/components/chip.js.map +1 -0
  182. package/components/citations.d.ts +37 -0
  183. package/components/citations.js +5 -0
  184. package/components/citations.js.map +1 -0
  185. package/components/code-block.d.ts +13 -0
  186. package/components/code-block.js +5 -0
  187. package/components/code-block.js.map +1 -0
  188. package/components/combobox.d.ts +58 -0
  189. package/components/combobox.js +10 -0
  190. package/components/combobox.js.map +1 -0
  191. package/components/command-menu.d.ts +54 -0
  192. package/components/command-menu.js +6 -0
  193. package/components/command-menu.js.map +1 -0
  194. package/components/context-menu.d.ts +46 -0
  195. package/components/context-menu.js +6 -0
  196. package/components/context-menu.js.map +1 -0
  197. package/components/cookie-consent.d.ts +26 -0
  198. package/components/cookie-consent.js +5 -0
  199. package/components/cookie-consent.js.map +1 -0
  200. package/components/date-picker.d.ts +112 -0
  201. package/components/date-picker.js +9 -0
  202. package/components/date-picker.js.map +1 -0
  203. package/components/decision-card.d.ts +65 -0
  204. package/components/decision-card.js +7 -0
  205. package/components/decision-card.js.map +1 -0
  206. package/components/dialog.d.ts +68 -0
  207. package/components/dialog.js +5 -0
  208. package/components/dialog.js.map +1 -0
  209. package/components/donut-chart.d.ts +20 -0
  210. package/components/donut-chart.js +11 -0
  211. package/components/donut-chart.js.map +1 -0
  212. package/components/dot.d.ts +21 -0
  213. package/components/dot.js +4 -0
  214. package/components/dot.js.map +1 -0
  215. package/components/dropdown.d.ts +74 -0
  216. package/components/dropdown.js +5 -0
  217. package/components/dropdown.js.map +1 -0
  218. package/components/empty-state.d.ts +25 -0
  219. package/components/empty-state.js +4 -0
  220. package/components/empty-state.js.map +1 -0
  221. package/components/file-upload.d.ts +78 -0
  222. package/components/file-upload.js +7 -0
  223. package/components/file-upload.js.map +1 -0
  224. package/components/floating.d.ts +30 -0
  225. package/components/floating.js +3 -0
  226. package/components/floating.js.map +1 -0
  227. package/components/form-field.d.ts +35 -0
  228. package/components/form-field.js +4 -0
  229. package/components/form-field.js.map +1 -0
  230. package/components/hover-card.d.ts +30 -0
  231. package/components/hover-card.js +4 -0
  232. package/components/hover-card.js.map +1 -0
  233. package/components/input-otp.d.ts +49 -0
  234. package/components/input-otp.js +8 -0
  235. package/components/input-otp.js.map +1 -0
  236. package/components/input.d.ts +28 -0
  237. package/components/input.js +5 -0
  238. package/components/input.js.map +1 -0
  239. package/components/kbd.d.ts +37 -0
  240. package/components/kbd.js +4 -0
  241. package/components/kbd.js.map +1 -0
  242. package/components/line-chart.d.ts +29 -0
  243. package/components/line-chart.js +12 -0
  244. package/components/line-chart.js.map +1 -0
  245. package/components/message-actions.d.ts +24 -0
  246. package/components/message-actions.js +5 -0
  247. package/components/message-actions.js.map +1 -0
  248. package/components/message.d.ts +40 -0
  249. package/components/message.js +8 -0
  250. package/components/message.js.map +1 -0
  251. package/components/number-input.d.ts +33 -0
  252. package/components/number-input.js +8 -0
  253. package/components/number-input.js.map +1 -0
  254. package/components/pagination.d.ts +45 -0
  255. package/components/pagination.js +6 -0
  256. package/components/pagination.js.map +1 -0
  257. package/components/popover.d.ts +44 -0
  258. package/components/popover.js +4 -0
  259. package/components/popover.js.map +1 -0
  260. package/components/progress.d.ts +24 -0
  261. package/components/progress.js +4 -0
  262. package/components/progress.js.map +1 -0
  263. package/components/prompt-bar.d.ts +63 -0
  264. package/components/prompt-bar.js +6 -0
  265. package/components/prompt-bar.js.map +1 -0
  266. package/components/radio.d.ts +27 -0
  267. package/components/radio.js +4 -0
  268. package/components/radio.js.map +1 -0
  269. package/components/search-bar.d.ts +20 -0
  270. package/components/search-bar.js +5 -0
  271. package/components/search-bar.js.map +1 -0
  272. package/components/segmented-control.d.ts +32 -0
  273. package/components/segmented-control.js +5 -0
  274. package/components/segmented-control.js.map +1 -0
  275. package/components/select.d.ts +97 -0
  276. package/components/select.js +7 -0
  277. package/components/select.js.map +1 -0
  278. package/components/sheet.d.ts +37 -0
  279. package/components/sheet.js +6 -0
  280. package/components/sheet.js.map +1 -0
  281. package/components/sidebar.d.ts +52 -0
  282. package/components/sidebar.js +4 -0
  283. package/components/sidebar.js.map +1 -0
  284. package/components/skeleton.d.ts +18 -0
  285. package/components/skeleton.js +4 -0
  286. package/components/skeleton.js.map +1 -0
  287. package/components/slider.d.ts +57 -0
  288. package/components/slider.js +8 -0
  289. package/components/slider.js.map +1 -0
  290. package/components/sliding-indicator.d.ts +23 -0
  291. package/components/sliding-indicator.js +3 -0
  292. package/components/sliding-indicator.js.map +1 -0
  293. package/components/streaming-text.d.ts +33 -0
  294. package/components/streaming-text.js +4 -0
  295. package/components/streaming-text.js.map +1 -0
  296. package/components/switch.d.ts +15 -0
  297. package/components/switch.js +4 -0
  298. package/components/switch.js.map +1 -0
  299. package/components/table.d.ts +57 -0
  300. package/components/table.js +5 -0
  301. package/components/table.js.map +1 -0
  302. package/components/tabs.d.ts +45 -0
  303. package/components/tabs.js +5 -0
  304. package/components/tabs.js.map +1 -0
  305. package/components/textarea.d.ts +30 -0
  306. package/components/textarea.js +5 -0
  307. package/components/textarea.js.map +1 -0
  308. package/components/thinking.d.ts +64 -0
  309. package/components/thinking.js +5 -0
  310. package/components/thinking.js.map +1 -0
  311. package/components/toast.d.ts +71 -0
  312. package/components/toast.js +5 -0
  313. package/components/toast.js.map +1 -0
  314. package/components/toggle.d.ts +30 -0
  315. package/components/toggle.js +4 -0
  316. package/components/toggle.js.map +1 -0
  317. package/components/tooltip.d.ts +35 -0
  318. package/components/tooltip.js +5 -0
  319. package/components/tooltip.js.map +1 -0
  320. package/index.d.ts +64 -0
  321. package/index.js +230 -0
  322. package/index.js.map +1 -0
  323. package/lib/utils.d.ts +3 -0
  324. package/lib/utils.js +3 -0
  325. package/lib/utils.js.map +1 -0
  326. package/package.json +54 -4
  327. package/styles.css +2 -0
  328. package/theme/create-theme.d.ts +44 -0
  329. package/theme/index.d.ts +1 -0
@@ -0,0 +1,98 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import * as React from 'react';
3
+ import { Popover as Popover$1 } from 'radix-ui';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ var panelClass = cn(
7
+ "relative flex w-[320px] max-w-[calc(100vw-16px)] flex-col overflow-clip pb-2.5",
8
+ "rounded-xl border border-border-default bg-bg-popover",
9
+ "[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]"
10
+ );
11
+ var closeClass = cn(
12
+ "absolute top-2.5 right-2.5 grid size-4 place-items-center rounded-sm text-text-subtle",
13
+ "transition-colors duration-(--duration-fast) ease-(--ease-out)",
14
+ "satin-hover:text-text-default focus-visible:outline-none satin-focus:[box-shadow:0_0_0_2px_var(--action-focus-ring)]"
15
+ );
16
+ var closeIcon = /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx(
17
+ "path",
18
+ {
19
+ d: "M4.50551 11.4951L8.0006 8M8.0006 8L11.4957 4.50491M8.0006 8L4.50551 4.50491M8.0006 8L11.4957 11.4951",
20
+ stroke: "currentColor",
21
+ strokeWidth: "1.25",
22
+ strokeLinecap: "round",
23
+ strokeLinejoin: "round"
24
+ }
25
+ ) });
26
+ function PanelBody({ titleId, title, description, body, closeButton }) {
27
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
28
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-0.5 px-2.5 pt-2.5 text-sm", children: [
29
+ /* @__PURE__ */ jsx("p", { id: titleId, className: cn("leading-[18px] font-medium text-text-default", closeButton && "pr-6"), children: title }),
30
+ description ? /* @__PURE__ */ jsx("p", { className: "text-text-muted", children: description }) : null
31
+ ] }),
32
+ body ? /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4 px-2.5 pt-4", children: body }) : null
33
+ ] });
34
+ }
35
+ function Popover({
36
+ title,
37
+ description,
38
+ children,
39
+ body,
40
+ open,
41
+ defaultOpen,
42
+ onOpenChange,
43
+ side = "bottom",
44
+ align = "start",
45
+ sideOffset = 8,
46
+ closeButton = true,
47
+ container,
48
+ onOpenAutoFocus,
49
+ onInteractOutside,
50
+ className
51
+ }) {
52
+ const titleId = React.useId();
53
+ return /* @__PURE__ */ jsxs(Popover$1.Root, { open, defaultOpen, onOpenChange, children: [
54
+ children && /* @__PURE__ */ jsx(Popover$1.Trigger, { asChild: true, children }),
55
+ /* @__PURE__ */ jsx(Popover$1.Portal, { container, children: /* @__PURE__ */ jsxs(
56
+ Popover$1.Content,
57
+ {
58
+ "data-slot": "popover",
59
+ "aria-labelledby": titleId,
60
+ side,
61
+ align,
62
+ sideOffset,
63
+ collisionPadding: 8,
64
+ onOpenAutoFocus,
65
+ onInteractOutside,
66
+ className: cn(
67
+ panelClass,
68
+ "pointer-events-auto z-50 origin-(--radix-popover-content-transform-origin) focus-visible:outline-none",
69
+ "data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]",
70
+ className
71
+ ),
72
+ children: [
73
+ /* @__PURE__ */ jsx(PanelBody, { titleId, title, description, body, closeButton }),
74
+ closeButton && /* @__PURE__ */ jsx(Popover$1.Close, { "aria-label": "Close", className: closeClass, children: closeIcon })
75
+ ]
76
+ }
77
+ ) })
78
+ ] });
79
+ }
80
+ function PopoverPanel({
81
+ title,
82
+ description,
83
+ body,
84
+ closeButton = true,
85
+ onClose,
86
+ className
87
+ }) {
88
+ const titleId = React.useId();
89
+ return /* @__PURE__ */ jsxs("div", { role: "dialog", "aria-labelledby": titleId, "data-slot": "popover", className: cn(panelClass, className), children: [
90
+ /* @__PURE__ */ jsx(PanelBody, { titleId, title, description, body, closeButton }),
91
+ closeButton && /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Close", onClick: onClose, className: closeClass, children: closeIcon })
92
+ ] });
93
+ }
94
+ var PopoverClose = Popover$1.Close;
95
+
96
+ export { Popover, PopoverClose, PopoverPanel };
97
+ //# sourceMappingURL=chunk-BNZVTLHV.js.map
98
+ //# sourceMappingURL=chunk-BNZVTLHV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/popover.tsx"],"names":["PopoverPrimitive"],"mappings":"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","file":"chunk-BNZVTLHV.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Popover as PopoverPrimitive } from 'radix-ui'\nimport { cn } from '../lib/utils'\n\n/**\n * Popover, 1:1 with the uiKit `Popover` component (613:18781): a 320px popover surface,\n * radius-xl, border/default, the shadcn `lg` shadow, 10px padding all round. A 13px medium\n * title (18px line) over a 13px muted description, 2px apart; a 16px close glyph in text/subtle\n * 10px from the top-right corner; an optional body slot 16px below the header. It opens 8px below its trigger, aligned to the trigger's start.\n *\n * Built on the Radix Popover. `children` is the trigger (rendered with `asChild`, so pass a\n * Button); `body` fills the body slot. Pass `container` to portal it into the docs stage.\n */\nexport interface PopoverProps {\n title: React.ReactNode\n description?: React.ReactNode\n /** The trigger. Rendered with `asChild`. */\n children?: React.ReactNode\n /** Figma's body slot: actions or a small form. Keep it to one task. */\n body?: React.ReactNode\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n side?: 'top' | 'right' | 'bottom' | 'left'\n align?: 'start' | 'center' | 'end'\n sideOffset?: number\n /** Show the close glyph in the corner. */\n closeButton?: boolean\n /** Portal target. Defaults to `document.body`. */\n container?: HTMLElement | null\n /** Called when focus moves into the popover on open; `preventDefault()` keeps it where it was. */\n onOpenAutoFocus?: (event: Event) => void\n /** A press or focus outside the popover; `preventDefault()` keeps it open. */\n onInteractOutside?: (event: Event) => void\n className?: string\n}\n\nconst panelClass = cn(\n 'relative flex w-[320px] max-w-[calc(100vw-16px)] flex-col overflow-clip pb-2.5',\n 'rounded-xl border border-border-default bg-bg-popover',\n '[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]',\n)\nconst closeClass = cn(\n 'absolute top-2.5 right-2.5 grid size-4 place-items-center rounded-sm text-text-subtle',\n 'transition-colors duration-(--duration-fast) ease-(--ease-out)',\n 'satin-hover:text-text-default focus-visible:outline-none satin-focus:[box-shadow:0_0_0_2px_var(--action-focus-ring)]',\n)\nconst closeIcon = (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden>\n <path\n d=\"M4.50551 11.4951L8.0006 8M8.0006 8L11.4957 4.50491M8.0006 8L4.50551 4.50491M8.0006 8L11.4957 11.4951\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n)\n\n/** Title, description and body: what both the floating Popover and PopoverPanel show. */\nfunction PanelBody({ titleId, title, description, body, closeButton }: { titleId: string } & Pick<PopoverProps, 'title' | 'description' | 'body' | 'closeButton'>) {\n return (\n <>\n <div className=\"flex flex-col gap-0.5 px-2.5 pt-2.5 text-sm\">\n <p id={titleId} className={cn('leading-[18px] font-medium text-text-default', closeButton && 'pr-6')}>{title}</p>\n {description ? <p className=\"text-text-muted\">{description}</p> : null}\n </div>\n {body ? <div className=\"flex flex-col gap-4 px-2.5 pt-4\">{body}</div> : null}\n </>\n )\n}\n\nexport function Popover({\n title,\n description,\n children,\n body,\n open,\n defaultOpen,\n onOpenChange,\n side = 'bottom',\n align = 'start',\n sideOffset = 8,\n closeButton = true,\n container,\n onOpenAutoFocus,\n onInteractOutside,\n className,\n}: PopoverProps) {\n const titleId = React.useId()\n return (\n <PopoverPrimitive.Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n {children && <PopoverPrimitive.Trigger asChild>{children}</PopoverPrimitive.Trigger>}\n <PopoverPrimitive.Portal container={container}>\n <PopoverPrimitive.Content\n data-slot=\"popover\"\n aria-labelledby={titleId}\n side={side}\n align={align}\n sideOffset={sideOffset}\n collisionPadding={8}\n onOpenAutoFocus={onOpenAutoFocus}\n onInteractOutside={onInteractOutside}\n className={cn(\n panelClass,\n 'pointer-events-auto z-50 origin-(--radix-popover-content-transform-origin) focus-visible:outline-none',\n 'data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]',\n className,\n )}\n >\n {/* Radix Popover has no Title part; the content is labelled by the heading. */}\n <PanelBody titleId={titleId} title={title} description={description} body={body} closeButton={closeButton} />\n {closeButton && (\n <PopoverPrimitive.Close aria-label=\"Close\" className={closeClass}>\n {closeIcon}\n </PopoverPrimitive.Close>\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Portal>\n </PopoverPrimitive.Root>\n )\n}\n\n/**\n * The popover's panel on its own, in place: no trigger, no positioning. For docs, previews\n * and layers you anchor yourself. The close button calls `onClose`.\n */\nexport function PopoverPanel({\n title,\n description,\n body,\n closeButton = true,\n onClose,\n className,\n}: Pick<PopoverProps, 'title' | 'description' | 'body' | 'closeButton' | 'className'> & { onClose?: () => void }) {\n const titleId = React.useId()\n return (\n <div role=\"dialog\" aria-labelledby={titleId} data-slot=\"popover\" className={cn(panelClass, className)}>\n <PanelBody titleId={titleId} title={title} description={description} body={body} closeButton={closeButton} />\n {closeButton && (\n <button type=\"button\" aria-label=\"Close\" onClick={onClose} className={closeClass}>\n {closeIcon}\n </button>\n )}\n </div>\n )\n}\n\n/** Wrap a body button in this to make it close the popover: `<PopoverClose asChild><Button…/></PopoverClose>`. */\nexport const PopoverClose = PopoverPrimitive.Close\n"]}
@@ -0,0 +1,89 @@
1
+ import { ChartCard, defaultFormat, ChartLegendPill } from './chunk-YPJYW624.js';
2
+ import * as React from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var SIZE = 184;
6
+ var STROKE = 20;
7
+ var R = (SIZE - STROKE) / 2;
8
+ var C = 2 * Math.PI * R;
9
+ var GAP = 2;
10
+ var seriesColor = (i) => `var(--chart-${i % 5 + 1})`;
11
+ function DonutCard({ data, formatValue = defaultFormat, highlight, centerLabel = "Total", ...props }) {
12
+ const [hovered, setHovered] = React.useState(null);
13
+ const active = (hovered != null && hovered < data.length ? hovered : null) ?? highlight ?? null;
14
+ const sum = data.reduce((s, d) => s + Math.max(0, d.value), 0) || 1;
15
+ const share = (v) => Math.round(v / sum * 100);
16
+ let offset = 0;
17
+ const arcs = data.map((d, i) => {
18
+ const len = Math.max(0, d.value) / sum * C;
19
+ const arc = { i, start: offset, len: Math.max(0, len - GAP) };
20
+ offset += len;
21
+ return arc;
22
+ });
23
+ return /* @__PURE__ */ jsx(ChartCard, { ...props, children: /* @__PURE__ */ jsxs(
24
+ "div",
25
+ {
26
+ className: "flex flex-col items-center gap-4 @min-[560px]:flex-row @min-[560px]:gap-8",
27
+ onPointerLeave: () => setHovered(null),
28
+ children: [
29
+ /* @__PURE__ */ jsxs("div", { className: "relative shrink-0 py-2", style: { width: SIZE }, children: [
30
+ /* @__PURE__ */ jsx("svg", { width: SIZE, height: SIZE, viewBox: `0 0 ${SIZE} ${SIZE}`, "aria-hidden": true, className: "block -rotate-90", children: arcs.map(({ i, start, len }) => /* @__PURE__ */ jsx(
31
+ "circle",
32
+ {
33
+ cx: SIZE / 2,
34
+ cy: SIZE / 2,
35
+ r: R,
36
+ fill: "none",
37
+ stroke: seriesColor(i),
38
+ strokeWidth: STROKE,
39
+ strokeDasharray: `${len} ${C - len}`,
40
+ strokeDashoffset: -start,
41
+ onPointerEnter: () => setHovered(i),
42
+ className: "transition-opacity duration-(--duration-fast) ease-(--ease-out)",
43
+ style: { opacity: active !== null && active !== i ? 0.15 : 1 }
44
+ },
45
+ data[i].label
46
+ )) }),
47
+ /* @__PURE__ */ jsxs("div", { "aria-live": "polite", className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center", children: [
48
+ /* @__PURE__ */ jsx("span", { className: "text-xl leading-(--text-xl--line-height) font-semibold text-text-default tabular-nums", children: formatValue(active != null ? data[active].value : sum) }),
49
+ /* @__PURE__ */ jsx("span", { className: "text-sm leading-(--text-sm--line-height) text-text-muted", children: active != null ? `${data[active].label} \xB7 ${share(data[active].value)}%` : centerLabel })
50
+ ] })
51
+ ] }),
52
+ /* @__PURE__ */ jsx(
53
+ "ul",
54
+ {
55
+ className: "grid w-full grid-cols-2 gap-x-4 gap-y-2 px-2 @min-[560px]:flex @min-[560px]:flex-1 @min-[560px]:flex-col @min-[560px]:gap-1 @min-[560px]:px-0",
56
+ "aria-label": props.title,
57
+ children: data.map((d, i) => /* @__PURE__ */ jsx(
58
+ "li",
59
+ {
60
+ tabIndex: 0,
61
+ onPointerEnter: () => setHovered(i),
62
+ onFocus: () => setHovered(i),
63
+ onBlur: () => setHovered(null),
64
+ "aria-label": `${d.label}: ${formatValue(d.value)}, ${share(d.value)}%`,
65
+ className: "min-w-0 rounded-pill outline-none focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
66
+ children: /* @__PURE__ */ jsx(
67
+ ChartLegendPill,
68
+ {
69
+ variant: "plain",
70
+ className: "flex w-full",
71
+ color: seriesColor(i),
72
+ label: d.label,
73
+ active: active === i,
74
+ dimmed: active !== null && active !== i
75
+ }
76
+ )
77
+ },
78
+ d.label
79
+ ))
80
+ }
81
+ )
82
+ ]
83
+ }
84
+ ) });
85
+ }
86
+
87
+ export { DonutCard };
88
+ //# sourceMappingURL=chunk-CL2II6BX.js.map
89
+ //# sourceMappingURL=chunk-CL2II6BX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/donut-chart.tsx"],"names":[],"mappings":"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","file":"chunk-CL2II6BX.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { ChartCard, ChartLegendPill, defaultFormat, type ChartCardBaseProps } from './chart'\n\n/**\n * Donut chart, 1:1 with the uiKit `chart/donutCard` (4067:7096), in the shared ChartCard\n * (chart.tsx).\n *\n * A 184px ring (20px thick) of chart/1–5 segments starting at 12 o'clock, a 2px gap between\n * them, with the sum in the middle (text/xl semibold) over `centerLabel` in text/muted. The sum\n * lives in the ring, so the card's summary shows only the range. Under the ring a legend of\n * plain pills (swatch and label, the value is in the ring on hover) in two columns, 16 × 8 apart.\n * From 560px the legend moves to the right of the ring as one column.\n *\n * Hover a segment or its pill (or set `highlight`): the other segments fade to 15%, the other\n * pills' content to 45% (the hovered one fills bg/hover), and the middle shows the hovered value over \"Label · 20%\".\n */\nexport interface DonutCardProps extends Omit<ChartCardBaseProps, 'total' | 'change'> {\n /** Under the sum in the middle. */\n centerLabel?: string\n}\n\nconst SIZE = 184\nconst STROKE = 20\nconst R = (SIZE - STROKE) / 2\nconst C = 2 * Math.PI * R\nconst GAP = 2\n\nconst seriesColor = (i: number) => `var(--chart-${(i % 5) + 1})`\n\nexport function DonutCard({ data, formatValue = defaultFormat, highlight, centerLabel = 'Total', ...props }: DonutCardProps) {\n const [hovered, setHovered] = React.useState<number | null>(null)\n const active = (hovered != null && hovered < data.length ? hovered : null) ?? highlight ?? null\n const sum = data.reduce((s, d) => s + Math.max(0, d.value), 0) || 1\n const share = (v: number) => Math.round((v / sum) * 100)\n\n let offset = 0\n const arcs = data.map((d, i) => {\n const len = (Math.max(0, d.value) / sum) * C\n const arc = { i, start: offset, len: Math.max(0, len - GAP) }\n offset += len\n return arc\n })\n\n return (\n <ChartCard {...props}>\n <div\n className=\"flex flex-col items-center gap-4 @min-[560px]:flex-row @min-[560px]:gap-8\"\n onPointerLeave={() => setHovered(null)}\n >\n <div className=\"relative shrink-0 py-2\" style={{ width: SIZE }}>\n <svg width={SIZE} height={SIZE} viewBox={`0 0 ${SIZE} ${SIZE}`} aria-hidden className=\"block -rotate-90\">\n {arcs.map(({ i, start, len }) => (\n <circle\n key={data[i].label}\n cx={SIZE / 2}\n cy={SIZE / 2}\n r={R}\n fill=\"none\"\n stroke={seriesColor(i)}\n strokeWidth={STROKE}\n strokeDasharray={`${len} ${C - len}`}\n strokeDashoffset={-start}\n onPointerEnter={() => setHovered(i)}\n className=\"transition-opacity duration-(--duration-fast) ease-(--ease-out)\"\n style={{ opacity: active !== null && active !== i ? 0.15 : 1 }}\n />\n ))}\n </svg>\n <div aria-live=\"polite\" className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-xl leading-(--text-xl--line-height) font-semibold text-text-default tabular-nums\">\n {formatValue(active != null ? data[active].value : sum)}\n </span>\n <span className=\"text-sm leading-(--text-sm--line-height) text-text-muted\">\n {active != null ? `${data[active].label} · ${share(data[active].value)}%` : centerLabel}\n </span>\n </div>\n </div>\n <ul\n className=\"grid w-full grid-cols-2 gap-x-4 gap-y-2 px-2 @min-[560px]:flex @min-[560px]:flex-1 @min-[560px]:flex-col @min-[560px]:gap-1 @min-[560px]:px-0\"\n aria-label={props.title}\n >\n {data.map((d, i) => (\n <li\n key={d.label}\n tabIndex={0}\n onPointerEnter={() => setHovered(i)}\n onFocus={() => setHovered(i)}\n onBlur={() => setHovered(null)}\n aria-label={`${d.label}: ${formatValue(d.value)}, ${share(d.value)}%`}\n className=\"min-w-0 rounded-pill outline-none focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]\"\n >\n <ChartLegendPill\n variant=\"plain\"\n className=\"flex w-full\"\n color={seriesColor(i)}\n label={d.label}\n active={active === i}\n dimmed={active !== null && active !== i}\n />\n </li>\n ))}\n </ul>\n </div>\n </ChartCard>\n )\n}\n"]}
@@ -0,0 +1,147 @@
1
+ import { useSlidingIndicator } from './chunk-J3NSDRVH.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import * as React from 'react';
4
+ import { Tabs as Tabs$1 } from 'radix-ui';
5
+ import { cva } from 'class-variance-authority';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var list = cva("relative flex", {
9
+ variants: {
10
+ variant: {
11
+ // The rule is an inset shadow, so the 2px indicator can sit on top of it (as in Figma).
12
+ underline: "items-end gap-8 [box-shadow:inset_0_-1px_0_var(--border-default)]",
13
+ pill: "items-center gap-1"
14
+ }
15
+ }
16
+ });
17
+ var trigger = cva(
18
+ [
19
+ "group/tab relative flex shrink-0 items-center font-medium whitespace-nowrap text-text-muted select-none",
20
+ "transition-[color,background-color,box-shadow] duration-(--duration-fast) ease-(--ease-out)",
21
+ "focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50",
22
+ "satin-hover:text-text-default satin-focus:text-text-default data-[state=active]:text-text-default",
23
+ "[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]"
24
+ ],
25
+ {
26
+ variants: {
27
+ variant: {
28
+ underline: "",
29
+ pill: [
30
+ "rounded-pill",
31
+ "data-[state=inactive]:satin-hover:bg-bg-muted",
32
+ "satin-focus:[box-shadow:0_0_0_1px_var(--border-focus)]"
33
+ ]
34
+ },
35
+ size: {
36
+ md: "text-base",
37
+ sm: "text-sm"
38
+ }
39
+ },
40
+ compoundVariants: [
41
+ { variant: "underline", size: "md", className: "h-control-height-xl" },
42
+ { variant: "underline", size: "sm", className: "h-control-height-lg" },
43
+ { variant: "pill", size: "md", className: "h-control-height-lg px-3" },
44
+ { variant: "pill", size: "sm", className: "h-control-height px-2.5" }
45
+ ]
46
+ }
47
+ );
48
+ function normalize(item) {
49
+ return typeof item === "string" ? { value: item, label: item } : item;
50
+ }
51
+ function Tabs({
52
+ items,
53
+ value,
54
+ defaultValue,
55
+ onValueChange,
56
+ variant = "underline",
57
+ size = "md",
58
+ disabled = false,
59
+ children,
60
+ className,
61
+ ...props
62
+ }) {
63
+ const tabs = items.map(normalize);
64
+ const listRef = React.useRef(null);
65
+ const [current, setCurrent] = React.useState(value ?? defaultValue ?? tabs[0]?.value);
66
+ const selected = value ?? current;
67
+ const indicator = useSlidingIndicator(listRef, '[role="tab"][data-state="active"]', `${selected}|${variant}|${size}|${tabs.length}`);
68
+ return /* @__PURE__ */ jsxs(
69
+ Tabs$1.Root,
70
+ {
71
+ "data-slot": "tabs",
72
+ value,
73
+ defaultValue: defaultValue ?? (value === void 0 ? tabs[0]?.value : void 0),
74
+ onValueChange: (v) => {
75
+ setCurrent(v);
76
+ onValueChange?.(v);
77
+ },
78
+ className: cn("flex flex-col", className),
79
+ children: [
80
+ /* @__PURE__ */ jsxs(Tabs$1.List, { ref: listRef, "aria-label": props["aria-label"], className: list({ variant }), children: [
81
+ /* @__PURE__ */ jsx(
82
+ "span",
83
+ {
84
+ ref: indicator.ref,
85
+ "aria-hidden": true,
86
+ className: cn(
87
+ "pointer-events-none absolute left-0 opacity-0",
88
+ variant === "underline" ? "bottom-0 z-10 h-0.5 rounded-full bg-action-primary-bg" : "top-1/2 z-0 -translate-y-1/2 rounded-pill bg-bg-selected",
89
+ variant === "pill" && (size === "md" ? "h-control-height-lg" : "h-control-height")
90
+ )
91
+ }
92
+ ),
93
+ tabs.map((tab) => /* @__PURE__ */ jsxs(
94
+ Tabs$1.Trigger,
95
+ {
96
+ value: tab.value,
97
+ disabled: disabled || tab.disabled,
98
+ ...children == null && { "aria-controls": void 0 },
99
+ className: cn(
100
+ trigger({ variant, size }),
101
+ variant === "pill" && "z-10",
102
+ // Before the indicator is placed (server render), the selected tab paints its own.
103
+ !indicator.ready && variant === "pill" && "data-[state=active]:bg-bg-selected"
104
+ ),
105
+ children: [
106
+ /* @__PURE__ */ jsxs(
107
+ "span",
108
+ {
109
+ className: cn(
110
+ "flex items-center gap-1.5 rounded-sm",
111
+ variant === "underline" && "group-focus-visible/tab:[box-shadow:inset_0_0_0_1.5px_var(--border-focus)] group-data-[force=focus]/tab:[box-shadow:inset_0_0_0_1.5px_var(--border-focus)]"
112
+ ),
113
+ children: [
114
+ tab.icon,
115
+ tab.label
116
+ ]
117
+ }
118
+ ),
119
+ variant === "underline" && /* @__PURE__ */ jsx(
120
+ "span",
121
+ {
122
+ "aria-hidden": true,
123
+ className: cn(
124
+ "absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-transparent",
125
+ "transition-colors duration-(--duration-fast) ease-(--ease-out)",
126
+ "group-data-[state=inactive]/tab:group-hover/tab:bg-border-strong group-data-[state=inactive]/tab:group-data-[force=hover]/tab:bg-border-strong",
127
+ !indicator.ready && "group-data-[state=active]/tab:bg-action-primary-bg"
128
+ )
129
+ }
130
+ )
131
+ ]
132
+ },
133
+ tab.value
134
+ ))
135
+ ] }),
136
+ children
137
+ ]
138
+ }
139
+ );
140
+ }
141
+ function TabsContent({ className, ...props }) {
142
+ return /* @__PURE__ */ jsx(Tabs$1.Content, { "data-slot": "tabs-content", className: cn("rounded-md focus-visible:shadow-border-focus focus-visible:outline-none", className), ...props });
143
+ }
144
+
145
+ export { Tabs, TabsContent };
146
+ //# sourceMappingURL=chunk-DETGJAIC.js.map
147
+ //# sourceMappingURL=chunk-DETGJAIC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/tabs.tsx"],"names":["TabsPrimitive"],"mappings":"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","file":"chunk-DETGJAIC.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Tabs as TabsPrimitive } from 'radix-ui'\nimport { cva } from 'class-variance-authority'\nimport { cn } from '../lib/utils'\nimport { useSlidingIndicator } from './sliding-indicator'\n\n/**\n * Tabs, 1:1 with the uiKit `Tabs` (3635:18677) and `tabs/item` (3635:18591) sets.\n *\n * Underline: tabs 32px apart on a 1px border/default rule; md is 36px high with a 14px label,\n * sm 32px with 13px. The selected tab has a 2px action/primary indicator sitting on the rule;\n * hover shows it in border/strong. Focus draws a 1.5px border/focus ring around the label.\n *\n * Pill: tabs 4px apart, radius-full; md 32px high with 12px sides, sm 28px with 10px. Hover\n * fills bg/muted, selected bg/selected, focus a 1px border/focus ring.\n *\n * The selected tab's indicator (the underline's 2px bar, the pill's bg/selected) is one element\n * that slides from tab to tab under the labels, as in the Segmented control and Pagination\n * (sliding-indicator.tsx): 300 ms, the leading edge first.\n *\n * Labels are text/muted, text/default on hover, focus and selected; disabled is 50%. Optional\n * 16px leading icon, 6px from the label. Built on the Radix Tabs (arrow keys move between tabs).\n * States answer to `data-force=\"hover\" | \"focus\"` for state sheets.\n */\nexport type TabItem =\n | string\n | {\n value: string\n label: React.ReactNode\n /** 16px leading icon. */\n icon?: React.ReactNode\n disabled?: boolean\n }\n\nexport interface TabsProps {\n items: TabItem[]\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n variant?: 'underline' | 'pill'\n size?: 'md' | 'sm'\n /** Disable every tab. */\n disabled?: boolean\n /** Accessible name for the tab list. */\n 'aria-label'?: string\n /** `TabsContent` panels, one per item value. */\n children?: React.ReactNode\n className?: string\n}\n\nconst list = cva('relative flex', {\n variants: {\n variant: {\n // The rule is an inset shadow, so the 2px indicator can sit on top of it (as in Figma).\n underline: 'items-end gap-8 [box-shadow:inset_0_-1px_0_var(--border-default)]',\n pill: 'items-center gap-1',\n },\n },\n})\n\nconst trigger = cva(\n [\n 'group/tab relative flex shrink-0 items-center font-medium whitespace-nowrap text-text-muted select-none',\n 'transition-[color,background-color,box-shadow] duration-(--duration-fast) ease-(--ease-out)',\n 'focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50',\n 'satin-hover:text-text-default satin-focus:text-text-default data-[state=active]:text-text-default',\n '[&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]',\n ],\n {\n variants: {\n variant: {\n underline: '',\n pill: [\n 'rounded-pill',\n 'data-[state=inactive]:satin-hover:bg-bg-muted',\n 'satin-focus:[box-shadow:0_0_0_1px_var(--border-focus)]',\n ],\n },\n size: {\n md: 'text-base',\n sm: 'text-sm',\n },\n },\n compoundVariants: [\n { variant: 'underline', size: 'md', className: 'h-control-height-xl' },\n { variant: 'underline', size: 'sm', className: 'h-control-height-lg' },\n { variant: 'pill', size: 'md', className: 'h-control-height-lg px-3' },\n { variant: 'pill', size: 'sm', className: 'h-control-height px-2.5' },\n ],\n },\n)\n\nfunction normalize(item: TabItem) {\n return typeof item === 'string' ? { value: item, label: item as React.ReactNode } : item\n}\n\nexport function Tabs({\n items,\n value,\n defaultValue,\n onValueChange,\n variant = 'underline',\n size = 'md',\n disabled = false,\n children,\n className,\n ...props\n}: TabsProps) {\n const tabs = items.map(normalize)\n const listRef = React.useRef<HTMLDivElement>(null)\n // Uncontrolled tabs: follow the selection here too, so the indicator knows when to move.\n const [current, setCurrent] = React.useState(value ?? defaultValue ?? tabs[0]?.value)\n const selected = value ?? current\n const indicator = useSlidingIndicator(listRef, '[role=\"tab\"][data-state=\"active\"]', `${selected}|${variant}|${size}|${tabs.length}`)\n\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n value={value}\n defaultValue={defaultValue ?? (value === undefined ? tabs[0]?.value : undefined)}\n onValueChange={(v) => {\n setCurrent(v)\n onValueChange?.(v)\n }}\n className={cn('flex flex-col', className)}\n >\n <TabsPrimitive.List ref={listRef} aria-label={props['aria-label']} className={list({ variant })}>\n <span\n ref={indicator.ref}\n aria-hidden\n className={cn(\n 'pointer-events-none absolute left-0 opacity-0',\n variant === 'underline' ? 'bottom-0 z-10 h-0.5 rounded-full bg-action-primary-bg' : 'top-1/2 z-0 -translate-y-1/2 rounded-pill bg-bg-selected',\n variant === 'pill' && (size === 'md' ? 'h-control-height-lg' : 'h-control-height'),\n )}\n />\n {tabs.map((tab) => (\n <TabsPrimitive.Trigger\n key={tab.value}\n value={tab.value}\n disabled={disabled || tab.disabled}\n // Without TabsContent there is no panel to point at.\n {...(children == null && { 'aria-controls': undefined })}\n className={cn(\n trigger({ variant, size }),\n variant === 'pill' && 'z-10',\n // Before the indicator is placed (server render), the selected tab paints its own.\n !indicator.ready && variant === 'pill' && 'data-[state=active]:bg-bg-selected',\n )}\n >\n <span\n className={cn(\n 'flex items-center gap-1.5 rounded-sm',\n variant === 'underline' &&\n 'group-focus-visible/tab:[box-shadow:inset_0_0_0_1.5px_var(--border-focus)] group-data-[force=focus]/tab:[box-shadow:inset_0_0_0_1.5px_var(--border-focus)]',\n )}\n >\n {tab.icon}\n {tab.label}\n </span>\n {variant === 'underline' && (\n <span\n aria-hidden\n className={cn(\n 'absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-transparent',\n 'transition-colors duration-(--duration-fast) ease-(--ease-out)',\n 'group-data-[state=inactive]/tab:group-hover/tab:bg-border-strong group-data-[state=inactive]/tab:group-data-[force=hover]/tab:bg-border-strong',\n !indicator.ready && 'group-data-[state=active]/tab:bg-action-primary-bg',\n )}\n />\n )}\n </TabsPrimitive.Trigger>\n ))}\n </TabsPrimitive.List>\n {children}\n </TabsPrimitive.Root>\n )\n}\n\n/** The panel for one tab value. */\nexport function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return <TabsPrimitive.Content data-slot=\"tabs-content\" className={cn('rounded-md focus-visible:shadow-border-focus focus-visible:outline-none', className)} {...props} />\n}\n"]}
@@ -0,0 +1,130 @@
1
+ import { ChartCard, defaultFormat, ChartTooltip, ChartLegendRow } from './chunk-YPJYW624.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import * as React from 'react';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function niceMax(max) {
7
+ if (max <= 0) return 4;
8
+ const raw = max / 4;
9
+ const pow = 10 ** Math.floor(Math.log10(raw));
10
+ const step = [1, 1.5, 2, 2.5, 3, 5, 7.5, 10].map((m) => m * pow).find((s) => s >= raw) ?? 10 * pow;
11
+ return step * 4;
12
+ }
13
+ var TRACK = 180;
14
+ function BarCard({
15
+ data,
16
+ formatValue = defaultFormat,
17
+ highlight,
18
+ legend,
19
+ unit,
20
+ reducedMotion,
21
+ total,
22
+ ...props
23
+ }) {
24
+ const [hovered, setHovered] = React.useState(null);
25
+ const [anchor, setAnchor] = React.useState(null);
26
+ const active = (hovered != null && hovered < data.length ? hovered : null) ?? highlight ?? null;
27
+ const signature = data.map((d) => `${d.label}:${d.value}`).join("|");
28
+ const [redraw, setRedraw] = React.useState({ signature, n: 0 });
29
+ if (redraw.signature !== signature) setRedraw({ signature, n: redraw.n + 1 });
30
+ const regrow = redraw.n > 0 && !reducedMotion;
31
+ const max = niceMax(Math.max(0, ...data.map((d) => d.value)));
32
+ const ticks = [4, 3, 2, 1, 0].map((i) => max / 4 * i);
33
+ const sum = data.reduce((n, d) => n + d.value, 0);
34
+ return /* @__PURE__ */ jsxs(ChartCard, { total: total ?? defaultFormat(sum), ...props, children: [
35
+ /* @__PURE__ */ jsx("div", { className: "pt-2", children: /* @__PURE__ */ jsxs("div", { className: "relative flex h-[206px] items-end gap-2 pl-8", onPointerLeave: () => setHovered(null), children: [
36
+ ticks.slice(0, 4).map((_, i) => /* @__PURE__ */ jsx(
37
+ "span",
38
+ {
39
+ "aria-hidden": true,
40
+ className: "absolute right-0 left-8 h-px border-t border-dashed border-border-subtle",
41
+ style: { top: TRACK / 4 * i }
42
+ },
43
+ i
44
+ )),
45
+ ticks.map((t, i) => /* @__PURE__ */ jsx(
46
+ "span",
47
+ {
48
+ "aria-hidden": true,
49
+ className: cn(
50
+ "absolute left-6 w-6 -translate-x-full text-right text-xs leading-[18px] text-text-muted",
51
+ regrow && "satin-bar-fade"
52
+ ),
53
+ style: { top: TRACK / 4 * i - 9 },
54
+ children: formatValue(t)
55
+ },
56
+ `${redraw.n}-${i}`
57
+ )),
58
+ /* @__PURE__ */ jsx("ul", { className: "contents", "aria-label": props.title, children: data.map((d, i) => {
59
+ const isActive = active === i;
60
+ const dimmed = active !== null && !isActive;
61
+ const height = d.value / max * TRACK;
62
+ return /* @__PURE__ */ jsxs(
63
+ "li",
64
+ {
65
+ tabIndex: 0,
66
+ "aria-label": `${d.tooltipLabel ?? d.label}: ${formatValue(d.value)}${unit ? ` ${unit}` : ""}`,
67
+ onPointerEnter: () => setHovered(i),
68
+ onFocus: () => setHovered(i),
69
+ onBlur: () => setHovered(null),
70
+ className: "relative flex min-w-0 flex-1 flex-col items-center gap-1.5 rounded-md focus-visible:outline-none",
71
+ children: [
72
+ /* @__PURE__ */ jsxs("div", { className: "relative flex w-full flex-col items-center justify-end gap-1.5", style: { height: TRACK }, children: [
73
+ isActive && /* @__PURE__ */ jsxs(Fragment, { children: [
74
+ /* @__PURE__ */ jsx(
75
+ ChartTooltip,
76
+ {
77
+ anchor,
78
+ label: d.tooltipLabel ?? d.label,
79
+ value: `${formatValue(d.value)}${unit ? ` ${unit}` : ""}`
80
+ }
81
+ ),
82
+ /* @__PURE__ */ jsx("span", { ref: setAnchor, className: "text-sm leading-(--text-sm--line-height) font-medium text-text-default", children: formatValue(d.value) })
83
+ ] }),
84
+ /* @__PURE__ */ jsx(
85
+ "span",
86
+ {
87
+ "aria-hidden": true,
88
+ className: cn(
89
+ "w-full rounded-md transition-[background-color,outline-color] duration-(--duration-fast) ease-(--ease-out)",
90
+ // Dimmed bars stay a tint of chart/3 on the card, so the brand colour never reaches them.
91
+ dimmed ? "bg-[color-mix(in_oklab,var(--chart-3)_30%,var(--bg-card))]" : "bg-chart-3",
92
+ isActive && "outline outline-offset-2 outline-chart-3",
93
+ regrow && "satin-bar-regrow"
94
+ ),
95
+ style: { height }
96
+ }
97
+ )
98
+ ] }),
99
+ /* @__PURE__ */ jsx(
100
+ "span",
101
+ {
102
+ className: cn(
103
+ "text-sm leading-(--text-sm--line-height) font-medium whitespace-nowrap",
104
+ isActive ? "text-text-default" : "text-text-muted",
105
+ regrow && "satin-bar-fade"
106
+ ),
107
+ children: d.label
108
+ }
109
+ )
110
+ ]
111
+ },
112
+ d.label
113
+ );
114
+ }) }, redraw.n)
115
+ ] }) }),
116
+ legend && /* @__PURE__ */ jsx(
117
+ ChartLegendRow,
118
+ {
119
+ color: "var(--chart-3)",
120
+ label: legend.label,
121
+ value: legend.value ?? formatValue(sum),
122
+ note: legend.note
123
+ }
124
+ )
125
+ ] });
126
+ }
127
+
128
+ export { BarCard, niceMax };
129
+ //# sourceMappingURL=chunk-DO3TBNSC.js.map
130
+ //# sourceMappingURL=chunk-DO3TBNSC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/bar-chart.tsx"],"names":[],"mappings":"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","file":"chunk-DO3TBNSC.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\nimport { ChartCard, ChartLegendRow, ChartTooltip, defaultFormat, type ChartCardBaseProps } from './chart'\n\n/**\n * Bar chart, 1:1 with the uiKit `chart/barCard` (3607:18253) and its `chart/barColumn`\n * (3602:17543), in the shared card frame (chart.tsx).\n *\n * BarCard: a 206px plot, 32px axis gutter, 4 dashed border-subtle gridlines at nice ticks,\n * axis labels regular 12/18 text-muted, columns 8px apart with a 180px track, bars radius-md\n * in chart/3 and day labels medium 13 text-muted 6px below. Hover (or `highlight`) keeps the\n * hovered bar, outlines it 2px out in chart/3, shows its value above and bolds its day; the\n * other bars dim to a 30% tint of chart/3 on bg/card, so they follow the bar, not the brand.\n * The KPI above defaults to the sum, in full (formatValue is for the axis); an optional legend row can sit under the plot.\n *\n * When the data changes (a new period, say) the bars regrow from the baseline in 250 ms on\n * ease-out, revealed by clip-path so their rounded tops stay whole, and the day labels and the\n * axis fade in on the new scale. Not on the first paint; under reduced motion, or with\n * `reducedMotion`, the bars swap at once.\n */\nexport function niceMax(max: number) {\n if (max <= 0) return 4\n const raw = max / 4\n const pow = 10 ** Math.floor(Math.log10(raw))\n const step = [1, 1.5, 2, 2.5, 3, 5, 7.5, 10].map((m) => m * pow).find((s) => s >= raw) ?? 10 * pow\n return step * 4\n}\n\n\nexport interface BarCardProps extends ChartCardBaseProps {\n /** The legend row under the plot. */\n legend?: { label: string; value?: string; note?: string }\n /** Unit after the value in the tooltip (\"covers\"). */\n unit?: string\n /** Swap the bars without motion when the data changes, as under prefers-reduced-motion. */\n reducedMotion?: boolean\n}\n\nconst TRACK = 180\n\nexport function BarCard({\n data,\n formatValue = defaultFormat,\n highlight,\n legend,\n unit,\n reducedMotion,\n total,\n ...props\n}: BarCardProps) {\n const [hovered, setHovered] = React.useState<number | null>(null)\n const [anchor, setAnchor] = React.useState<HTMLElement | null>(null)\n const active = (hovered != null && hovered < data.length ? hovered : null) ?? highlight ?? null\n // Counts real changes to the data (not a new array with the same values), so the bars\n // remount and regrow; zero until the first change.\n const signature = data.map((d) => `${d.label}:${d.value}`).join('|')\n const [redraw, setRedraw] = React.useState({ signature, n: 0 })\n if (redraw.signature !== signature) setRedraw({ signature, n: redraw.n + 1 })\n const regrow = redraw.n > 0 && !reducedMotion\n const max = niceMax(Math.max(0, ...data.map((d) => d.value)))\n const ticks = [4, 3, 2, 1, 0].map((i) => (max / 4) * i)\n const sum = data.reduce((n, d) => n + d.value, 0)\n\n return (\n <ChartCard total={total ?? defaultFormat(sum)} {...props}>\n <div className=\"pt-2\">\n <div className=\"relative flex h-[206px] items-end gap-2 pl-8\" onPointerLeave={() => setHovered(null)}>\n {/* Gridlines at each tick but zero, dashed border-subtle. */}\n {ticks.slice(0, 4).map((_, i) => (\n <span\n key={i}\n aria-hidden\n className=\"absolute right-0 left-8 h-px border-t border-dashed border-border-subtle\"\n style={{ top: (TRACK / 4) * i }}\n />\n ))}\n {ticks.map((t, i) => (\n <span\n key={`${redraw.n}-${i}`}\n aria-hidden\n className={cn(\n 'absolute left-6 w-6 -translate-x-full text-right text-xs leading-[18px] text-text-muted',\n regrow && 'satin-bar-fade',\n )}\n style={{ top: (TRACK / 4) * i - 9 }}\n >\n {formatValue(t)}\n </span>\n ))}\n <ul key={redraw.n} className=\"contents\" aria-label={props.title}>\n {data.map((d, i) => {\n const isActive = active === i\n const dimmed = active !== null && !isActive\n const height = (d.value / max) * TRACK\n return (\n <li\n key={d.label}\n tabIndex={0}\n aria-label={`${d.tooltipLabel ?? d.label}: ${formatValue(d.value)}${unit ? ` ${unit}` : ''}`}\n onPointerEnter={() => setHovered(i)}\n onFocus={() => setHovered(i)}\n onBlur={() => setHovered(null)}\n className=\"relative flex min-w-0 flex-1 flex-col items-center gap-1.5 rounded-md focus-visible:outline-none\"\n >\n <div className=\"relative flex w-full flex-col items-center justify-end gap-1.5\" style={{ height: TRACK }}>\n {isActive && (\n <>\n {/* The tooltip floats 4px above the value. */}\n <ChartTooltip\n anchor={anchor}\n label={d.tooltipLabel ?? d.label}\n value={`${formatValue(d.value)}${unit ? ` ${unit}` : ''}`}\n />\n <span ref={setAnchor} className=\"text-sm leading-(--text-sm--line-height) font-medium text-text-default\">\n {formatValue(d.value)}\n </span>\n </>\n )}\n <span\n aria-hidden\n className={cn(\n 'w-full rounded-md transition-[background-color,outline-color] duration-(--duration-fast) ease-(--ease-out)',\n // Dimmed bars stay a tint of chart/3 on the card, so the brand colour never reaches them.\n dimmed ? 'bg-[color-mix(in_oklab,var(--chart-3)_30%,var(--bg-card))]' : 'bg-chart-3',\n isActive && 'outline outline-offset-2 outline-chart-3',\n regrow && 'satin-bar-regrow',\n )}\n style={{ height }}\n />\n </div>\n <span\n className={cn(\n 'text-sm leading-(--text-sm--line-height) font-medium whitespace-nowrap',\n isActive ? 'text-text-default' : 'text-text-muted',\n regrow && 'satin-bar-fade',\n )}\n >\n {d.label}\n </span>\n </li>\n )\n })}\n </ul>\n </div>\n </div>\n {legend && (\n <ChartLegendRow\n color=\"var(--chart-3)\"\n label={legend.label}\n value={legend.value ?? formatValue(sum)}\n note={legend.note}\n />\n )}\n </ChartCard>\n )\n}\n"]}