@uisatin/ui 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) 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-3DINAQLL.js +153 -0
  6. package/chunk-3DINAQLL.js.map +1 -0
  7. package/chunk-3ERGAHKA.js +179 -0
  8. package/chunk-3ERGAHKA.js.map +1 -0
  9. package/chunk-6C7CGJX2.js +86 -0
  10. package/chunk-6C7CGJX2.js.map +1 -0
  11. package/chunk-6QMSWITQ.js +140 -0
  12. package/chunk-6QMSWITQ.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-D7RZNTFC.js +95 -0
  36. package/chunk-D7RZNTFC.js.map +1 -0
  37. package/chunk-DETGJAIC.js +147 -0
  38. package/chunk-DETGJAIC.js.map +1 -0
  39. package/chunk-DO3TBNSC.js +130 -0
  40. package/chunk-DO3TBNSC.js.map +1 -0
  41. package/chunk-ESC5JCVQ.js +90 -0
  42. package/chunk-ESC5JCVQ.js.map +1 -0
  43. package/chunk-FDKIX4DC.js +55 -0
  44. package/chunk-FDKIX4DC.js.map +1 -0
  45. package/chunk-GICKPMJU.js +239 -0
  46. package/chunk-GICKPMJU.js.map +1 -0
  47. package/chunk-GQA24FYG.js +57 -0
  48. package/chunk-GQA24FYG.js.map +1 -0
  49. package/chunk-H4NU7NPO.js +264 -0
  50. package/chunk-H4NU7NPO.js.map +1 -0
  51. package/chunk-H63FYCMY.js +11 -0
  52. package/chunk-H63FYCMY.js.map +1 -0
  53. package/chunk-HL42K2NH.js +76 -0
  54. package/chunk-HL42K2NH.js.map +1 -0
  55. package/chunk-HNQUX43Z.js +109 -0
  56. package/chunk-HNQUX43Z.js.map +1 -0
  57. package/chunk-HRKPV66B.js +32 -0
  58. package/chunk-HRKPV66B.js.map +1 -0
  59. package/chunk-J3NSDRVH.js +83 -0
  60. package/chunk-J3NSDRVH.js.map +1 -0
  61. package/chunk-JPNWHWAQ.js +151 -0
  62. package/chunk-JPNWHWAQ.js.map +1 -0
  63. package/chunk-KNUWZNFV.js +240 -0
  64. package/chunk-KNUWZNFV.js.map +1 -0
  65. package/chunk-L6NCCSIP.js +213 -0
  66. package/chunk-L6NCCSIP.js.map +1 -0
  67. package/chunk-LLHTVIM3.js +50 -0
  68. package/chunk-LLHTVIM3.js.map +1 -0
  69. package/chunk-LW3TRU5W.js +131 -0
  70. package/chunk-LW3TRU5W.js.map +1 -0
  71. package/chunk-LZMKSFCF.js +79 -0
  72. package/chunk-LZMKSFCF.js.map +1 -0
  73. package/chunk-MR3JDI7E.js +122 -0
  74. package/chunk-MR3JDI7E.js.map +1 -0
  75. package/chunk-NN6PKJWS.js +44 -0
  76. package/chunk-NN6PKJWS.js.map +1 -0
  77. package/chunk-NSRTTYQ4.js +252 -0
  78. package/chunk-NSRTTYQ4.js.map +1 -0
  79. package/chunk-O7F3CIDV.js +45 -0
  80. package/chunk-O7F3CIDV.js.map +1 -0
  81. package/chunk-P4O6TGDR.js +166 -0
  82. package/chunk-P4O6TGDR.js.map +1 -0
  83. package/chunk-PF3YBUKT.js +81 -0
  84. package/chunk-PF3YBUKT.js.map +1 -0
  85. package/chunk-PVOLDO4G.js +47 -0
  86. package/chunk-PVOLDO4G.js.map +1 -0
  87. package/chunk-QS4N4MNP.js +215 -0
  88. package/chunk-QS4N4MNP.js.map +1 -0
  89. package/chunk-QUF2IPOZ.js +98 -0
  90. package/chunk-QUF2IPOZ.js.map +1 -0
  91. package/chunk-RTJ76X5U.js +126 -0
  92. package/chunk-RTJ76X5U.js.map +1 -0
  93. package/chunk-SH6NG6VN.js +40 -0
  94. package/chunk-SH6NG6VN.js.map +1 -0
  95. package/chunk-SHDFUXYV.js +195 -0
  96. package/chunk-SHDFUXYV.js.map +1 -0
  97. package/chunk-TKO44NDI.js +84 -0
  98. package/chunk-TKO44NDI.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/chunk-YX5VNRJX.js +24 -0
  132. package/chunk-YX5VNRJX.js.map +1 -0
  133. package/components/accordion.d.ts +27 -0
  134. package/components/accordion.js +4 -0
  135. package/components/accordion.js.map +1 -0
  136. package/components/agent-loading.d.ts +65 -0
  137. package/components/agent-loading.js +4 -0
  138. package/components/agent-loading.js.map +1 -0
  139. package/components/agent-picker.d.ts +82 -0
  140. package/components/agent-picker.js +5 -0
  141. package/components/agent-picker.js.map +1 -0
  142. package/components/agent-suggestion.d.ts +69 -0
  143. package/components/agent-suggestion.js +6 -0
  144. package/components/agent-suggestion.js.map +1 -0
  145. package/components/announcement-bar.d.ts +39 -0
  146. package/components/announcement-bar.js +7 -0
  147. package/components/announcement-bar.js.map +1 -0
  148. package/components/attachment.d.ts +73 -0
  149. package/components/attachment.js +5 -0
  150. package/components/attachment.js.map +1 -0
  151. package/components/avatar.d.ts +34 -0
  152. package/components/avatar.js +6 -0
  153. package/components/avatar.js.map +1 -0
  154. package/components/badge.d.ts +19 -0
  155. package/components/badge.js +4 -0
  156. package/components/badge.js.map +1 -0
  157. package/components/banner-mesh.d.ts +11 -0
  158. package/components/banner-mesh.js +3 -0
  159. package/components/banner-mesh.js.map +1 -0
  160. package/components/banner.d.ts +50 -0
  161. package/components/banner.js +6 -0
  162. package/components/banner.js.map +1 -0
  163. package/components/bar-chart.d.ts +32 -0
  164. package/components/bar-chart.js +11 -0
  165. package/components/bar-chart.js.map +1 -0
  166. package/components/breadcrumb.d.ts +32 -0
  167. package/components/breadcrumb.js +6 -0
  168. package/components/breadcrumb.js.map +1 -0
  169. package/components/button.d.ts +32 -0
  170. package/components/button.js +4 -0
  171. package/components/button.js.map +1 -0
  172. package/components/card.d.ts +28 -0
  173. package/components/card.js +5 -0
  174. package/components/card.js.map +1 -0
  175. package/components/channel-chart.d.ts +14 -0
  176. package/components/channel-chart.js +11 -0
  177. package/components/channel-chart.js.map +1 -0
  178. package/components/chart.d.ts +88 -0
  179. package/components/chart.js +10 -0
  180. package/components/chart.js.map +1 -0
  181. package/components/checkbox.d.ts +17 -0
  182. package/components/checkbox.js +4 -0
  183. package/components/checkbox.js.map +1 -0
  184. package/components/chip.d.ts +54 -0
  185. package/components/chip.js +4 -0
  186. package/components/chip.js.map +1 -0
  187. package/components/citations.d.ts +37 -0
  188. package/components/citations.js +5 -0
  189. package/components/citations.js.map +1 -0
  190. package/components/code-block.d.ts +13 -0
  191. package/components/code-block.js +5 -0
  192. package/components/code-block.js.map +1 -0
  193. package/components/combobox.d.ts +58 -0
  194. package/components/combobox.js +10 -0
  195. package/components/combobox.js.map +1 -0
  196. package/components/command-menu.d.ts +54 -0
  197. package/components/command-menu.js +6 -0
  198. package/components/command-menu.js.map +1 -0
  199. package/components/context-menu.d.ts +46 -0
  200. package/components/context-menu.js +6 -0
  201. package/components/context-menu.js.map +1 -0
  202. package/components/cookie-consent.d.ts +26 -0
  203. package/components/cookie-consent.js +5 -0
  204. package/components/cookie-consent.js.map +1 -0
  205. package/components/date-picker.d.ts +112 -0
  206. package/components/date-picker.js +9 -0
  207. package/components/date-picker.js.map +1 -0
  208. package/components/decision-card.d.ts +65 -0
  209. package/components/decision-card.js +7 -0
  210. package/components/decision-card.js.map +1 -0
  211. package/components/dialog.d.ts +68 -0
  212. package/components/dialog.js +5 -0
  213. package/components/dialog.js.map +1 -0
  214. package/components/donut-chart.d.ts +20 -0
  215. package/components/donut-chart.js +11 -0
  216. package/components/donut-chart.js.map +1 -0
  217. package/components/dot.d.ts +21 -0
  218. package/components/dot.js +4 -0
  219. package/components/dot.js.map +1 -0
  220. package/components/dropdown.d.ts +74 -0
  221. package/components/dropdown.js +5 -0
  222. package/components/dropdown.js.map +1 -0
  223. package/components/empty-state.d.ts +25 -0
  224. package/components/empty-state.js +4 -0
  225. package/components/empty-state.js.map +1 -0
  226. package/components/file-upload.d.ts +78 -0
  227. package/components/file-upload.js +7 -0
  228. package/components/file-upload.js.map +1 -0
  229. package/components/floating.d.ts +30 -0
  230. package/components/floating.js +3 -0
  231. package/components/floating.js.map +1 -0
  232. package/components/form-field.d.ts +35 -0
  233. package/components/form-field.js +4 -0
  234. package/components/form-field.js.map +1 -0
  235. package/components/hover-card.d.ts +30 -0
  236. package/components/hover-card.js +4 -0
  237. package/components/hover-card.js.map +1 -0
  238. package/components/input-otp.d.ts +49 -0
  239. package/components/input-otp.js +8 -0
  240. package/components/input-otp.js.map +1 -0
  241. package/components/input.d.ts +28 -0
  242. package/components/input.js +5 -0
  243. package/components/input.js.map +1 -0
  244. package/components/kbd.d.ts +37 -0
  245. package/components/kbd.js +4 -0
  246. package/components/kbd.js.map +1 -0
  247. package/components/line-chart.d.ts +29 -0
  248. package/components/line-chart.js +12 -0
  249. package/components/line-chart.js.map +1 -0
  250. package/components/message-actions.d.ts +24 -0
  251. package/components/message-actions.js +5 -0
  252. package/components/message-actions.js.map +1 -0
  253. package/components/message.d.ts +40 -0
  254. package/components/message.js +8 -0
  255. package/components/message.js.map +1 -0
  256. package/components/number-input.d.ts +33 -0
  257. package/components/number-input.js +8 -0
  258. package/components/number-input.js.map +1 -0
  259. package/components/pagination.d.ts +45 -0
  260. package/components/pagination.js +6 -0
  261. package/components/pagination.js.map +1 -0
  262. package/components/popover.d.ts +44 -0
  263. package/components/popover.js +4 -0
  264. package/components/popover.js.map +1 -0
  265. package/components/progress.d.ts +24 -0
  266. package/components/progress.js +4 -0
  267. package/components/progress.js.map +1 -0
  268. package/components/prompt-bar.d.ts +63 -0
  269. package/components/prompt-bar.js +6 -0
  270. package/components/prompt-bar.js.map +1 -0
  271. package/components/radio.d.ts +27 -0
  272. package/components/radio.js +4 -0
  273. package/components/radio.js.map +1 -0
  274. package/components/search-bar.d.ts +20 -0
  275. package/components/search-bar.js +5 -0
  276. package/components/search-bar.js.map +1 -0
  277. package/components/segmented-control.d.ts +32 -0
  278. package/components/segmented-control.js +5 -0
  279. package/components/segmented-control.js.map +1 -0
  280. package/components/select.d.ts +97 -0
  281. package/components/select.js +7 -0
  282. package/components/select.js.map +1 -0
  283. package/components/sheet.d.ts +37 -0
  284. package/components/sheet.js +6 -0
  285. package/components/sheet.js.map +1 -0
  286. package/components/sidebar.d.ts +52 -0
  287. package/components/sidebar.js +4 -0
  288. package/components/sidebar.js.map +1 -0
  289. package/components/skeleton.d.ts +18 -0
  290. package/components/skeleton.js +4 -0
  291. package/components/skeleton.js.map +1 -0
  292. package/components/slider.d.ts +57 -0
  293. package/components/slider.js +8 -0
  294. package/components/slider.js.map +1 -0
  295. package/components/sliding-indicator.d.ts +23 -0
  296. package/components/sliding-indicator.js +3 -0
  297. package/components/sliding-indicator.js.map +1 -0
  298. package/components/streaming-text.d.ts +33 -0
  299. package/components/streaming-text.js +4 -0
  300. package/components/streaming-text.js.map +1 -0
  301. package/components/switch.d.ts +15 -0
  302. package/components/switch.js +4 -0
  303. package/components/switch.js.map +1 -0
  304. package/components/table.d.ts +57 -0
  305. package/components/table.js +5 -0
  306. package/components/table.js.map +1 -0
  307. package/components/tabs.d.ts +45 -0
  308. package/components/tabs.js +5 -0
  309. package/components/tabs.js.map +1 -0
  310. package/components/textarea.d.ts +30 -0
  311. package/components/textarea.js +5 -0
  312. package/components/textarea.js.map +1 -0
  313. package/components/thinking.d.ts +64 -0
  314. package/components/thinking.js +5 -0
  315. package/components/thinking.js.map +1 -0
  316. package/components/toast.d.ts +71 -0
  317. package/components/toast.js +5 -0
  318. package/components/toast.js.map +1 -0
  319. package/components/toggle.d.ts +30 -0
  320. package/components/toggle.js +4 -0
  321. package/components/toggle.js.map +1 -0
  322. package/components/tooltip.d.ts +35 -0
  323. package/components/tooltip.js +5 -0
  324. package/components/tooltip.js.map +1 -0
  325. package/index.d.ts +64 -0
  326. package/index.js +231 -0
  327. package/index.js.map +1 -0
  328. package/lib/utils.d.ts +3 -0
  329. package/lib/utils.js +3 -0
  330. package/lib/utils.js.map +1 -0
  331. package/package.json +54 -4
  332. package/styles.css +2 -0
  333. package/theme/create-theme.d.ts +44 -0
  334. package/theme/index.d.ts +1 -0
@@ -0,0 +1,79 @@
1
+ import { Button } from './chunk-HNQUX43Z.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import * as React from 'react';
4
+ import { Clock, DoubleCheck, ThumbsUp, ThumbsDown, Copy, Link } from 'iconoir-react';
5
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
6
+
7
+ var divider = /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "h-3 w-px shrink-0 rounded-full bg-border-default" });
8
+ function MessageActions({
9
+ timestamp,
10
+ status = "delivered",
11
+ feedback: feedbackProp = null,
12
+ showShare = true,
13
+ onFeedback,
14
+ onCopy,
15
+ onShare,
16
+ className,
17
+ ...props
18
+ }) {
19
+ const [feedback, setFeedback] = React.useState(feedbackProp);
20
+ React.useEffect(() => setFeedback(feedbackProp), [feedbackProp]);
21
+ const toggle = (value) => {
22
+ const next = feedback === value ? null : value;
23
+ setFeedback(next);
24
+ onFeedback?.(next);
25
+ };
26
+ const thumb = "aria-pressed:bg-border-input aria-pressed:[&_svg]:text-text-subtle";
27
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "message-actions", className: cn("flex items-center gap-2", className), ...props, children: [
28
+ timestamp && /* @__PURE__ */ jsxs(Fragment, { children: [
29
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5", children: [
30
+ /* @__PURE__ */ jsxs("span", { className: "flex size-6 items-center justify-center text-text-muted", children: [
31
+ status === "sending" ? /* @__PURE__ */ jsx(Clock, { "aria-hidden": true, className: "size-icon-size [stroke-width:1.875]" }) : /* @__PURE__ */ jsx(DoubleCheck, { "aria-hidden": true, className: "size-icon-size [stroke-width:1.875]" }),
32
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: status === "sending" ? "Sending" : "Delivered" })
33
+ ] }),
34
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium whitespace-nowrap text-text-muted", children: timestamp })
35
+ ] }),
36
+ divider
37
+ ] }),
38
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-0.5", children: [
39
+ /* @__PURE__ */ jsx(
40
+ Button,
41
+ {
42
+ variant: "tertiary",
43
+ size: "xs",
44
+ iconOnly: true,
45
+ "aria-label": "Good response",
46
+ "aria-pressed": feedback === "like",
47
+ onClick: () => toggle("like"),
48
+ className: thumb,
49
+ children: /* @__PURE__ */ jsx(ThumbsUp, {})
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsx(
53
+ Button,
54
+ {
55
+ variant: "tertiary",
56
+ size: "xs",
57
+ iconOnly: true,
58
+ "aria-label": "Bad response",
59
+ "aria-pressed": feedback === "dislike",
60
+ onClick: () => toggle("dislike"),
61
+ className: thumb,
62
+ children: /* @__PURE__ */ jsx(ThumbsDown, {})
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "xs", iconOnly: true, "aria-label": "Copy", onClick: onCopy, children: /* @__PURE__ */ jsx(Copy, {}) })
66
+ ] }),
67
+ showShare && /* @__PURE__ */ jsxs(Fragment, { children: [
68
+ divider,
69
+ /* @__PURE__ */ jsxs(Button, { variant: "tertiary", size: "xs", onClick: onShare, children: [
70
+ /* @__PURE__ */ jsx(Link, {}),
71
+ "Share"
72
+ ] })
73
+ ] })
74
+ ] });
75
+ }
76
+
77
+ export { MessageActions };
78
+ //# sourceMappingURL=chunk-AN2RNJLR.js.map
79
+ //# sourceMappingURL=chunk-AN2RNJLR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/message-actions.tsx"],"names":[],"mappings":"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","file":"chunk-AN2RNJLR.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Clock, Copy, DoubleCheck, Link, ThumbsDown, ThumbsUp } from 'iconoir-react'\nimport { cn } from '../lib/utils'\nimport { Button } from './button'\n\n/**\n * MessageActions, 1:1 with uiKit `_chat/answerActions` (901:20164): the row under an assistant\n * reply. Delivery status (16px icon in a 24px box) and time in text/muted medium 13, then like,\n * dislike and copy as 24px tertiary icon buttons 2px apart, then Share (tertiary xs with a\n * label). Groups sit 8px apart with 1 × 12 border/default dividers between them.\n *\n * Feedback: a clicked thumb stays pressed (border/input fill, icon text/subtle) until the other\n * one is clicked or it is clicked again; `feedback` sets it, `onFeedback` reports it.\n * The status and time show only when there is a `timestamp`.\n */\nexport type MessageFeedback = 'like' | 'dislike' | null\n\nexport interface MessageActionsProps extends React.ComponentProps<'div'> {\n /** \"20 minutes ago\". Leave it out to drop the status and time. */\n timestamp?: string\n status?: 'sending' | 'delivered'\n /** The pressed thumb. Pass it with onFeedback to control it, or once to start from it. */\n feedback?: MessageFeedback\n showShare?: boolean\n onFeedback?: (value: MessageFeedback) => void\n onCopy?: () => void\n onShare?: () => void\n}\n\nconst divider = <span aria-hidden className=\"h-3 w-px shrink-0 rounded-full bg-border-default\" />\n\nexport function MessageActions({\n timestamp,\n status = 'delivered',\n feedback: feedbackProp = null,\n showShare = true,\n onFeedback,\n onCopy,\n onShare,\n className,\n ...props\n}: MessageActionsProps) {\n const [feedback, setFeedback] = React.useState<MessageFeedback>(feedbackProp)\n React.useEffect(() => setFeedback(feedbackProp), [feedbackProp])\n\n const toggle = (value: 'like' | 'dislike') => {\n const next = feedback === value ? null : value\n setFeedback(next)\n onFeedback?.(next)\n }\n\n const thumb = 'aria-pressed:bg-border-input aria-pressed:[&_svg]:text-text-subtle'\n\n return (\n <div data-slot=\"message-actions\" className={cn('flex items-center gap-2', className)} {...props}>\n {timestamp && (\n <>\n <span className=\"flex items-center gap-0.5\">\n <span className=\"flex size-6 items-center justify-center text-text-muted\">\n {status === 'sending' ? (\n <Clock aria-hidden className=\"size-icon-size [stroke-width:1.875]\" />\n ) : (\n <DoubleCheck aria-hidden className=\"size-icon-size [stroke-width:1.875]\" />\n )}\n <span className=\"sr-only\">{status === 'sending' ? 'Sending' : 'Delivered'}</span>\n </span>\n <span className=\"text-sm font-medium whitespace-nowrap text-text-muted\">{timestamp}</span>\n </span>\n {divider}\n </>\n )}\n <span className=\"flex items-center gap-0.5\">\n <Button\n variant=\"tertiary\"\n size=\"xs\"\n iconOnly\n aria-label=\"Good response\"\n aria-pressed={feedback === 'like'}\n onClick={() => toggle('like')}\n className={thumb}\n >\n <ThumbsUp />\n </Button>\n <Button\n variant=\"tertiary\"\n size=\"xs\"\n iconOnly\n aria-label=\"Bad response\"\n aria-pressed={feedback === 'dislike'}\n onClick={() => toggle('dislike')}\n className={thumb}\n >\n <ThumbsDown />\n </Button>\n <Button variant=\"tertiary\" size=\"xs\" iconOnly aria-label=\"Copy\" onClick={onCopy}>\n <Copy />\n </Button>\n </span>\n {showShare && (\n <>\n {divider}\n <Button variant=\"tertiary\" size=\"xs\" onClick={onShare}>\n <Link />\n Share\n </Button>\n </>\n )}\n </div>\n )\n}\n"]}
@@ -0,0 +1,36 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var dotVariants = cva(
7
+ "block size-2 rounded-full",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ solid: "bg-tone-fg",
12
+ outline: "border border-tone-fg"
13
+ }
14
+ },
15
+ defaultVariants: { variant: "solid" }
16
+ }
17
+ );
18
+ function Dot({ className, tone = "fuchsia", variant, label, ...props }) {
19
+ return /* @__PURE__ */ jsx(
20
+ "span",
21
+ {
22
+ "data-slot": "dot",
23
+ "data-tone": tone,
24
+ role: label ? "img" : void 0,
25
+ "aria-label": label,
26
+ "aria-hidden": label ? void 0 : true,
27
+ className: cn("inline-flex size-4 shrink-0 items-center justify-center", className),
28
+ ...props,
29
+ children: /* @__PURE__ */ jsx("span", { className: dotVariants({ variant }) })
30
+ }
31
+ );
32
+ }
33
+
34
+ export { Dot, dotVariants };
35
+ //# sourceMappingURL=chunk-B2K45IUR.js.map
36
+ //# sourceMappingURL=chunk-B2K45IUR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/dot.tsx"],"names":[],"mappings":";;;;;AAgBA,IAAM,WAAA,GAAc,GAAA;AAAA,EAClB,2BAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA,QACP,KAAA,EAAO,YAAA;AAAA,QACP,OAAA,EAAS;AAAA;AACX,KACF;AAAA,IACA,eAAA,EAAiB,EAAE,OAAA,EAAS,OAAA;AAAQ;AAExC;AAQO,SAAS,GAAA,CAAI,EAAE,SAAA,EAAW,IAAA,GAAO,WAAW,OAAA,EAAS,KAAA,EAAO,GAAG,KAAA,EAAM,EAAa;AACvF,EAAA,uBACE,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,KAAA;AAAA,MACV,WAAA,EAAW,IAAA;AAAA,MACX,IAAA,EAAM,QAAQ,KAAA,GAAQ,MAAA;AAAA,MACtB,YAAA,EAAY,KAAA;AAAA,MACZ,aAAA,EAAa,QAAQ,MAAA,GAAY,IAAA;AAAA,MACjC,SAAA,EAAW,EAAA,CAAG,yDAAA,EAA2D,SAAS,CAAA;AAAA,MACjF,GAAG,KAAA;AAAA,MAEJ,8BAAC,MAAA,EAAA,EAAK,SAAA,EAAW,YAAY,EAAE,OAAA,EAAS,CAAA,EAAG;AAAA;AAAA,GAC7C;AAEJ","file":"chunk-B2K45IUR.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '../lib/utils'\n\nexport type DotTone = 'fuchsia' | 'sky' | 'plum' | 'green'\n\n/**\n * Dot, 1:1 with the uiKit `Dot` set (369:6759, page dotIndicator): a 16px box with an 8px\n * indicator in the middle, in the tone's `tone/fg` colour. Solid is a filled circle; outline\n * is the same 8px circle drawn with a 1px stroke inside it, nothing in the middle.\n *\n * With a `label` the dot is an image with that name; without one it is decorative and hidden\n * from assistive tech (pair it with visible text, as the docs ask).\n */\nconst dotVariants = cva(\n 'block size-2 rounded-full',\n {\n variants: {\n variant: {\n solid: 'bg-tone-fg',\n outline: 'border border-tone-fg',\n },\n },\n defaultVariants: { variant: 'solid' },\n },\n)\n\nexport interface DotProps extends Omit<React.ComponentProps<'span'>, 'children'>, VariantProps<typeof dotVariants> {\n tone?: DotTone\n /** Accessible name, e.g. \"Running\". Leave it out when visible text already says it. */\n label?: string\n}\n\nexport function Dot({ className, tone = 'fuchsia', variant, label, ...props }: DotProps) {\n return (\n <span\n data-slot=\"dot\"\n data-tone={tone}\n role={label ? 'img' : undefined}\n aria-label={label}\n aria-hidden={label ? undefined : true}\n className={cn('inline-flex size-4 shrink-0 items-center justify-center', className)}\n {...props}\n >\n <span className={dotVariants({ variant })} />\n </span>\n )\n}\n\nexport { dotVariants }\n"]}
@@ -0,0 +1,82 @@
1
+ import { KbdGroup } from './chunk-BKZBWPUH.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import * as React from 'react';
4
+ import { Tooltip as Tooltip$1 } from 'radix-ui';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function TooltipBubble({
8
+ label,
9
+ shortcut,
10
+ shape = "default",
11
+ className,
12
+ ...props
13
+ }) {
14
+ return /* @__PURE__ */ jsxs(
15
+ "div",
16
+ {
17
+ "data-slot": "tooltip",
18
+ className: cn(
19
+ "flex items-center gap-2 bg-text-default py-1 pl-2.5 text-sm leading-(--text-sm--line-height) font-medium whitespace-nowrap text-bg-canvas",
20
+ "[box-shadow:0_8px_12px_0_var(--effect-shadow-md),0_1px_1.5px_0_var(--effect-shadow-ambient),inset_0_1px_0_0_var(--effect-highlight-top)]",
21
+ shape === "rounded" ? "rounded-pill" : "rounded-lg",
22
+ shortcut ? "pr-1.5" : "pr-2.5",
23
+ className
24
+ ),
25
+ ...props,
26
+ children: [
27
+ /* @__PURE__ */ jsx("span", { children: label }),
28
+ shortcut && /* @__PURE__ */ jsx(KbdGroup, { keys: shortcut, tone: "inverse" })
29
+ ]
30
+ }
31
+ );
32
+ }
33
+ function Tooltip({
34
+ label,
35
+ shortcut,
36
+ shape = "default",
37
+ side = "top",
38
+ delay = 300,
39
+ closeDelay = 0,
40
+ children,
41
+ open: openProp,
42
+ defaultOpen = false,
43
+ onOpenChange,
44
+ container,
45
+ className
46
+ }) {
47
+ const [inner, setInner] = React.useState(defaultOpen);
48
+ const open = openProp ?? inner;
49
+ const timer = React.useRef(void 0);
50
+ React.useEffect(() => () => clearTimeout(timer.current), []);
51
+ const change = (next) => {
52
+ clearTimeout(timer.current);
53
+ const apply = () => {
54
+ setInner(next);
55
+ onOpenChange?.(next);
56
+ };
57
+ if (!next && closeDelay > 0) timer.current = setTimeout(apply, closeDelay);
58
+ else apply();
59
+ };
60
+ return /* @__PURE__ */ jsx(Tooltip$1.Provider, { delayDuration: delay, children: /* @__PURE__ */ jsxs(Tooltip$1.Root, { open, onOpenChange: change, children: [
61
+ /* @__PURE__ */ jsx(Tooltip$1.Trigger, { asChild: true, children }),
62
+ /* @__PURE__ */ jsx(Tooltip$1.Portal, { container, children: /* @__PURE__ */ jsx(
63
+ Tooltip$1.Content,
64
+ {
65
+ side,
66
+ sideOffset: 8,
67
+ collisionPadding: 8,
68
+ className: cn(
69
+ "z-50 transition-[opacity,translate] duration-(--duration-fast) ease-(--ease-out)",
70
+ "starting:opacity-0",
71
+ "data-[side=top]:starting:translate-y-1 data-[side=bottom]:starting:-translate-y-1",
72
+ "data-[side=left]:starting:translate-x-1 data-[side=right]:starting:-translate-x-1"
73
+ ),
74
+ children: /* @__PURE__ */ jsx(TooltipBubble, { label, shortcut, shape, className })
75
+ }
76
+ ) })
77
+ ] }) });
78
+ }
79
+
80
+ export { Tooltip, TooltipBubble };
81
+ //# sourceMappingURL=chunk-B6V4VSGH.js.map
82
+ //# sourceMappingURL=chunk-B6V4VSGH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/tooltip.tsx"],"names":["TooltipPrimitive"],"mappings":";;;;;;AAyCO,SAAS,aAAA,CAAc;AAAA,EAC5B,KAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,GAAQ,SAAA;AAAA,EACR,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAmG;AACjG,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,SAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,QACT,2IAAA;AAAA,QACA,0IAAA;AAAA,QACA,KAAA,KAAU,YAAY,cAAA,GAAiB,YAAA;AAAA,QACvC,WAAW,QAAA,GAAW,QAAA;AAAA,QACtB;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEJ,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,UAAM,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QACZ,4BAAY,GAAA,CAAC,QAAA,EAAA,EAAS,IAAA,EAAM,QAAA,EAAU,MAAK,SAAA,EAAU;AAAA;AAAA;AAAA,GACxD;AAEJ;AAEO,SAAS,OAAA,CAAQ;AAAA,EACtB,KAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,GAAQ,SAAA;AAAA,EACR,IAAA,GAAO,KAAA;AAAA,EACP,KAAA,GAAQ,GAAA;AAAA,EACR,UAAA,GAAa,CAAA;AAAA,EACb,QAAA;AAAA,EACA,IAAA,EAAM,QAAA;AAAA,EACN,WAAA,GAAc,KAAA;AAAA,EACd,YAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAiB;AAEf,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAU,eAAS,WAAW,CAAA;AACpD,EAAA,MAAM,OAAO,QAAA,IAAY,KAAA;AACzB,EAAA,MAAM,KAAA,GAAc,aAAsC,MAAS,CAAA;AACnE,EAAM,KAAA,CAAA,SAAA,CAAU,MAAM,MAAM,YAAA,CAAa,MAAM,OAAO,CAAA,EAAG,EAAE,CAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,CAAC,IAAA,KAAkB;AAChC,IAAA,YAAA,CAAa,MAAM,OAAO,CAAA;AAC1B,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,YAAA,GAAe,IAAI,CAAA;AAAA,IACrB,CAAA;AACA,IAAA,IAAI,CAAC,QAAQ,UAAA,GAAa,CAAA,QAAS,OAAA,GAAU,UAAA,CAAW,OAAO,UAAU,CAAA;AAAA,SACpE,KAAA,EAAM;AAAA,EACb,CAAA;AACA,EAAA,uBACE,GAAA,CAACA,SAAA,CAAiB,QAAA,EAAjB,EAA0B,aAAA,EAAe,KAAA,EACxC,QAAA,kBAAA,IAAA,CAACA,SAAA,CAAiB,IAAA,EAAjB,EAAsB,IAAA,EAAY,YAAA,EAAc,MAAA,EAC/C,QAAA,EAAA;AAAA,oBAAA,GAAA,CAACA,SAAA,CAAiB,OAAA,EAAjB,EAAyB,OAAA,EAAO,MAAE,QAAA,EAAS,CAAA;AAAA,oBAC5C,GAAA,CAACA,SAAA,CAAiB,MAAA,EAAjB,EAAwB,SAAA,EACvB,QAAA,kBAAA,GAAA;AAAA,MAACA,SAAA,CAAiB,OAAA;AAAA,MAAjB;AAAA,QACC,IAAA;AAAA,QACA,UAAA,EAAY,CAAA;AAAA,QACZ,gBAAA,EAAkB,CAAA;AAAA,QAClB,SAAA,EAAW,EAAA;AAAA,UACT,kFAAA;AAAA,UACA,oBAAA;AAAA,UACA,mFAAA;AAAA,UACA;AAAA,SACF;AAAA,QAEA,QAAA,kBAAA,GAAA,CAAC,aAAA,EAAA,EAAc,KAAA,EAAc,QAAA,EAAoB,OAAc,SAAA,EAAsB;AAAA;AAAA,KACvF,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ","file":"chunk-B6V4VSGH.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Tooltip as TooltipPrimitive } from 'radix-ui'\nimport { cn } from '../lib/utils'\nimport { KbdGroup } from './kbd'\n\n/**\n * Tooltip, 1:1 with the uiKit `tooltip/shortcut` set (3306:17555): an inverse pill\n * (text/default fill, bg/canvas text, medium 13/19.5) with the action name and optional\n * keys: a KbdGroup of sm keys in the inverse tone, so they read on the dark pill in Light and\n * the light one in Dark. Padding 4 / 6 / 4 / 10, 8px between\n * label and keys. Shape default is radius-lg; rounded is a pill. Shadow md (0 8 12 shadow-md, 0 1 1.5 shadow-ambient) and the\n * 1px top highlight. Without a shortcut the right padding matches the left (10).\n *\n * Built on the Radix tooltip: it opens on hover after `delay` and at once on keyboard focus,\n * waits `closeDelay` after the pointer leaves before closing, closes on Escape, and links itself to the trigger with aria-describedby. It sits 8px from\n * the trigger and fades in from 4px towards it (`@starting-style`, ease-out, 150 ms).\n */\n\nexport interface TooltipProps {\n /** The action, in one or two words. */\n label: React.ReactNode\n /** Keys that run the action, e.g. \"⌘K\" or \"⌃⇧V\". */\n shortcut?: string\n shape?: 'default' | 'rounded'\n side?: 'top' | 'right' | 'bottom' | 'left'\n /** Hover delay in ms before it opens. */\n delay?: number\n /** How long it stays after the pointer leaves, in ms, so a quick slip off the trigger doesn't flicker it. */\n closeDelay?: number\n /** The trigger. It must be focusable (a button, a link). */\n children: React.ReactNode\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Portal target. Defaults to `document.body`. */\n container?: HTMLElement | null\n className?: string\n}\n\nexport function TooltipBubble({\n label,\n shortcut,\n shape = 'default',\n className,\n ...props\n}: Pick<TooltipProps, 'label' | 'shortcut' | 'shape' | 'className'> & React.ComponentProps<'div'>) {\n return (\n <div\n data-slot=\"tooltip\"\n className={cn(\n 'flex items-center gap-2 bg-text-default py-1 pl-2.5 text-sm leading-(--text-sm--line-height) font-medium whitespace-nowrap text-bg-canvas',\n '[box-shadow:0_8px_12px_0_var(--effect-shadow-md),0_1px_1.5px_0_var(--effect-shadow-ambient),inset_0_1px_0_0_var(--effect-highlight-top)]',\n shape === 'rounded' ? 'rounded-pill' : 'rounded-lg',\n shortcut ? 'pr-1.5' : 'pr-2.5',\n className,\n )}\n {...props}\n >\n <span>{label}</span>\n {shortcut && <KbdGroup keys={shortcut} tone=\"inverse\" />}\n </div>\n )\n}\n\nexport function Tooltip({\n label,\n shortcut,\n shape = 'default',\n side = 'top',\n delay = 300,\n closeDelay = 0,\n children,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n container,\n className,\n}: TooltipProps) {\n // Open state lives here so closing can wait `closeDelay`; opening again cancels the wait.\n const [inner, setInner] = React.useState(defaultOpen)\n const open = openProp ?? inner\n const timer = React.useRef<ReturnType<typeof setTimeout>>(undefined)\n React.useEffect(() => () => clearTimeout(timer.current), [])\n const change = (next: boolean) => {\n clearTimeout(timer.current)\n const apply = () => {\n setInner(next)\n onOpenChange?.(next)\n }\n if (!next && closeDelay > 0) timer.current = setTimeout(apply, closeDelay)\n else apply()\n }\n return (\n <TooltipPrimitive.Provider delayDuration={delay}>\n <TooltipPrimitive.Root open={open} onOpenChange={change}>\n <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>\n <TooltipPrimitive.Portal container={container}>\n <TooltipPrimitive.Content\n side={side}\n sideOffset={8}\n collisionPadding={8}\n className={cn(\n 'z-50 transition-[opacity,translate] duration-(--duration-fast) ease-(--ease-out)',\n 'starting:opacity-0',\n 'data-[side=top]:starting:translate-y-1 data-[side=bottom]:starting:-translate-y-1',\n 'data-[side=left]:starting:translate-x-1 data-[side=right]:starting:-translate-x-1',\n )}\n >\n <TooltipBubble label={label} shortcut={shortcut} shape={shape} className={className} />\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n </TooltipPrimitive.Root>\n </TooltipPrimitive.Provider>\n )\n}\n"]}
@@ -0,0 +1,59 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import * as React from 'react';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ var isSingle = (children) => typeof children === "string" ? [...children.trim()].length === 1 : React.isValidElement(children);
6
+ function Kbd({ size = "sm", tone = "default", className, children, ...props }) {
7
+ const square = isSingle(children);
8
+ return /* @__PURE__ */ jsx(
9
+ "kbd",
10
+ {
11
+ "data-slot": "kbd",
12
+ "data-square": square || void 0,
13
+ className: cn(
14
+ "inline-flex shrink-0 items-center justify-center rounded-sm border-[0.75px] font-sans text-2xs leading-none font-medium tracking-normal whitespace-nowrap",
15
+ size === "sm" ? "h-[18px] min-w-[18px]" : "h-5 min-w-5",
16
+ // A single key is exactly square with nothing on the sides, so the glyph sits in the middle.
17
+ square ? size === "sm" ? "w-[18px] px-0" : "w-5 px-0" : size === "sm" ? "px-1" : "px-1.5",
18
+ tone === "default" ? "border-border-default bg-component-kbd-bg text-text-muted" : "border-action-inverse-border bg-action-inverse-bg-hover text-bg-canvas/72 dark:border-action-inverse-bg-pressed dark:bg-text-default",
19
+ // Glyph icons (arrows, return) take the key's colour at 10px.
20
+ "[&>svg]:size-2.5 [&>svg]:shrink-0",
21
+ className
22
+ ),
23
+ ...props,
24
+ children
25
+ }
26
+ );
27
+ }
28
+ function keysOf(shortcut) {
29
+ if (/[\s+]/.test(shortcut.trim())) return shortcut.split(/[\s+]+/).filter(Boolean);
30
+ const keys = [];
31
+ let rest = "";
32
+ for (const ch of shortcut) {
33
+ if ("\u2318\u2303\u21E7\u2325".includes(ch)) keys.push(ch);
34
+ else rest += ch;
35
+ }
36
+ if (rest.trim()) keys.push(rest.trim());
37
+ return keys;
38
+ }
39
+ function KbdGroup({ keys, size, tone, className, ...props }) {
40
+ const list = typeof keys === "string" ? keysOf(keys) : keys;
41
+ return /* @__PURE__ */ jsx("span", { "data-slot": "kbd-group", className: cn("inline-flex shrink-0 items-center gap-0.5", className), ...props, children: list.map((k, i) => /* @__PURE__ */ jsx(Kbd, { size, tone, children: k }, i)) });
42
+ }
43
+ var glyph = { viewBox: "0 0 10 10", fill: "none", stroke: "currentColor", strokeWidth: 0.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true };
44
+ var KbdArrowUp = () => /* @__PURE__ */ jsx("svg", { ...glyph, children: /* @__PURE__ */ jsx("path", { d: "M5.00018 8.17963L5.00018 1.82037M8.00316 4.82335L5.00018 1.82037L1.9972 4.82335" }) });
45
+ var KbdArrowDown = () => /* @__PURE__ */ jsx("svg", { ...glyph, children: /* @__PURE__ */ jsx("path", { d: "M4.99982 1.82037L4.99982 8.17963M1.99684 5.17665L4.99982 8.17963L8.0028 5.17665" }) });
46
+ var KbdReturn = () => /* @__PURE__ */ jsxs("svg", { ...glyph, children: [
47
+ /* @__PURE__ */ jsx("path", { d: "M4.27083 8.02083L2.8125 6.5625L4.27083 5.10417" }),
48
+ /* @__PURE__ */ jsx("path", { d: "M2.8125 6.5625H5.3125C6.23296 6.5625 6.97917 5.81629 6.97917 4.89583V1.97917" })
49
+ ] });
50
+ function KbdHint({ keys, label, className, ...props }) {
51
+ return /* @__PURE__ */ jsxs("span", { "data-slot": "kbd-hint", className: cn("flex items-center gap-1.5", className), ...props, children: [
52
+ /* @__PURE__ */ jsx(KbdGroup, { keys }),
53
+ /* @__PURE__ */ jsx("span", { className: "text-xs leading-4 tracking-normal whitespace-nowrap text-text-muted", children: label })
54
+ ] });
55
+ }
56
+
57
+ export { Kbd, KbdArrowDown, KbdArrowUp, KbdGroup, KbdHint, KbdReturn, keysOf };
58
+ //# sourceMappingURL=chunk-BKZBWPUH.js.map
59
+ //# sourceMappingURL=chunk-BKZBWPUH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/kbd.tsx"],"names":[],"mappings":"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","file":"chunk-BKZBWPUH.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\n\n/**\n * Kbd, 1:1 with the uiKit `Kbd` set (4021:3415): one keyboard key. sm is 18px high with 4px\n * sides, md 20px with 6px; a single character or glyph makes it an exact square, radius-sm, a 0.75px border/default edge on\n * component/kbd/bg (bg/card in Light, bg/muted in Dark), the 11px medium Keycap glyph in\n * text/muted. Put keys of one shortcut 2px apart, or pass `keys` and let `KbdGroup` do it.\n *\n * `tone=\"inverse\"` is for keys on an inverse surface (a tooltip): a darker key on the dark pill\n * in Light, a lighter one on the light pill in Dark.\n */\nexport interface KbdProps extends React.ComponentProps<'kbd'> {\n size?: 'sm' | 'md'\n tone?: 'default' | 'inverse'\n}\n\n/** One character or one glyph icon: the key is a square. */\nconst isSingle = (children: React.ReactNode) =>\n typeof children === 'string' ? [...children.trim()].length === 1 : React.isValidElement(children)\n\nexport function Kbd({ size = 'sm', tone = 'default', className, children, ...props }: KbdProps) {\n const square = isSingle(children)\n return (\n <kbd\n data-slot=\"kbd\"\n data-square={square || undefined}\n className={cn(\n 'inline-flex shrink-0 items-center justify-center rounded-sm border-[0.75px] font-sans text-2xs leading-none font-medium tracking-normal whitespace-nowrap',\n size === 'sm' ? 'h-[18px] min-w-[18px]' : 'h-5 min-w-5',\n // A single key is exactly square with nothing on the sides, so the glyph sits in the middle.\n square ? (size === 'sm' ? 'w-[18px] px-0' : 'w-5 px-0') : size === 'sm' ? 'px-1' : 'px-1.5',\n tone === 'default'\n ? 'border-border-default bg-component-kbd-bg text-text-muted'\n : 'border-action-inverse-border bg-action-inverse-bg-hover text-bg-canvas/72 dark:border-action-inverse-bg-pressed dark:bg-text-default',\n // Glyph icons (arrows, return) take the key's colour at 10px.\n '[&>svg]:size-2.5 [&>svg]:shrink-0',\n className,\n )}\n {...props}\n >\n {children}\n </kbd>\n )\n}\n\n/**\n * Splits a shortcut into keys: modifier glyphs one by one, the rest as one key (\"Esc\", \"K\").\n * Spaces or \"+\" split it explicitly (\"Ctrl + K\").\n */\nexport function keysOf(shortcut: string) {\n if (/[\\s+]/.test(shortcut.trim())) return shortcut.split(/[\\s+]+/).filter(Boolean)\n const keys: string[] = []\n let rest = ''\n for (const ch of shortcut) {\n if ('⌘⌃⇧⌥'.includes(ch)) keys.push(ch)\n else rest += ch\n }\n if (rest.trim()) keys.push(rest.trim())\n return keys\n}\n\nexport interface KbdGroupProps extends Omit<React.ComponentProps<'span'>, 'children'> {\n /** A shortcut such as \"⌘K\" or \"⌃⇧V\", split into keys, or the keys themselves. */\n keys: string | React.ReactNode[]\n size?: KbdProps['size']\n tone?: KbdProps['tone']\n}\n\n/** The keys of one shortcut, 2px apart. */\nexport function KbdGroup({ keys, size, tone, className, ...props }: KbdGroupProps) {\n const list = typeof keys === 'string' ? keysOf(keys) : keys\n return (\n <span data-slot=\"kbd-group\" className={cn('inline-flex shrink-0 items-center gap-0.5', className)} {...props}>\n {list.map((k, i) => (\n <Kbd key={i} size={size} tone={tone}>\n {k}\n </Kbd>\n ))}\n </span>\n )\n}\n\n/* ---------- glyphs for keys that have no character ---------- */\n\nconst glyph = { viewBox: '0 0 10 10', fill: 'none', stroke: 'currentColor', strokeWidth: 0.75, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': true } as const\n\nexport const KbdArrowUp = () => (\n <svg {...glyph}>\n <path d=\"M5.00018 8.17963L5.00018 1.82037M8.00316 4.82335L5.00018 1.82037L1.9972 4.82335\" />\n </svg>\n)\nexport const KbdArrowDown = () => (\n <svg {...glyph}>\n <path d=\"M4.99982 1.82037L4.99982 8.17963M1.99684 5.17665L4.99982 8.17963L8.0028 5.17665\" />\n </svg>\n)\nexport const KbdReturn = () => (\n <svg {...glyph}>\n <path d=\"M4.27083 8.02083L2.8125 6.5625L4.27083 5.10417\" />\n <path d=\"M2.8125 6.5625H5.3125C6.23296 6.5625 6.97917 5.81629 6.97917 4.89583V1.97917\" />\n </svg>\n)\n\nexport interface KbdHintProps extends Omit<React.ComponentProps<'span'>, 'children'> {\n keys: React.ReactNode[]\n label: React.ReactNode\n}\n\n/** A key hint for a menu footer: keys, then what they do in 12px text/muted, 6px apart. */\nexport function KbdHint({ keys, label, className, ...props }: KbdHintProps) {\n return (\n <span data-slot=\"kbd-hint\" className={cn('flex items-center gap-1.5', className)} {...props}>\n <KbdGroup keys={keys} />\n <span className=\"text-xs leading-4 tracking-normal whitespace-nowrap text-text-muted\">{label}</span>\n </span>\n )\n}\n"]}
@@ -0,0 +1,220 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import * as React from 'react';
3
+ import { Slot, Tooltip, Collapsible } from 'radix-ui';
4
+ import { NavArrowRight } from 'iconoir-react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ var rowFocus = "outline-none satin-focus:[box-shadow:inset_0_0_0_1px_var(--border-focus)]";
8
+ function Sidebar({ className, ...props }) {
9
+ return /* @__PURE__ */ jsx("nav", { "data-slot": "sidebar", className: cn("flex flex-col gap-0.5", className), ...props });
10
+ }
11
+ function SidebarItem({
12
+ className,
13
+ label,
14
+ icon,
15
+ active = false,
16
+ count,
17
+ iconOnly = false,
18
+ disabled = false,
19
+ asChild = false,
20
+ href,
21
+ children,
22
+ ...props
23
+ }) {
24
+ const Comp = asChild ? Slot.Root : "a";
25
+ const showCount = typeof count === "number" && count > 0;
26
+ const row = /* @__PURE__ */ jsx(
27
+ Comp,
28
+ {
29
+ "data-slot": "sidebar-item",
30
+ "data-active": active || void 0,
31
+ "aria-current": active ? "page" : void 0,
32
+ "aria-disabled": disabled || void 0,
33
+ "aria-label": iconOnly ? showCount ? `${label}, ${count}` : label : void 0,
34
+ href: disabled ? void 0 : href,
35
+ tabIndex: disabled ? -1 : void 0,
36
+ className: cn(
37
+ "flex h-8 shrink-0 items-center gap-2 rounded-lg px-2 text-sm leading-4 font-medium tracking-normal text-text-muted no-underline select-none",
38
+ "transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)",
39
+ "[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]",
40
+ "not-data-active:satin-hover:bg-bg-muted",
41
+ rowFocus,
42
+ "data-active:bg-border-input data-active:text-text-default",
43
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
44
+ iconOnly && "relative size-8 justify-center px-0",
45
+ className
46
+ ),
47
+ ...props,
48
+ children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
49
+ icon,
50
+ !iconOnly && /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label }),
51
+ showCount && !iconOnly && /* @__PURE__ */ jsx(SidebarCount, { count }),
52
+ showCount && iconOnly && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute top-1 right-1 size-1.5 rounded-full bg-action-destructive-bg" })
53
+ ] })
54
+ }
55
+ );
56
+ if (!iconOnly) return row;
57
+ return /* @__PURE__ */ jsx(Tooltip.Provider, { delayDuration: 300, children: /* @__PURE__ */ jsxs(Tooltip.Root, { children: [
58
+ /* @__PURE__ */ jsx(Tooltip.Trigger, { asChild: true, children: row }),
59
+ /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(
60
+ Tooltip.Content,
61
+ {
62
+ side: "right",
63
+ sideOffset: 6,
64
+ collisionPadding: 8,
65
+ className: "z-50 rounded-md bg-action-inverse-bg px-2 py-1 text-xs font-medium text-text-on-inverse [box-shadow:0_1px_2px_0_var(--effect-shadow-xs)]",
66
+ children: label
67
+ }
68
+ ) })
69
+ ] }) });
70
+ }
71
+ function SidebarCount({ count }) {
72
+ return (
73
+ // 11/12 has no type token in the kit; Figma uses it raw for this counter.
74
+ /* @__PURE__ */ jsx("span", { className: "inline-flex h-4 min-w-[18px] shrink-0 items-center justify-center rounded-xs bg-action-destructive-bg px-1 text-[11px] leading-3 font-medium tracking-normal text-text-on-solid tabular-nums", children: count > 99 ? "99+" : count })
75
+ );
76
+ }
77
+ function SidebarGroup({
78
+ className,
79
+ label,
80
+ icon,
81
+ count,
82
+ defaultOpen = true,
83
+ open: openProp,
84
+ onOpenChange,
85
+ children,
86
+ triggerProps,
87
+ ...props
88
+ }) {
89
+ const [uncontrolled, setUncontrolled] = React.useState(defaultOpen);
90
+ const open = openProp ?? uncontrolled;
91
+ const regionId = React.useId();
92
+ return /* @__PURE__ */ jsxs(
93
+ Collapsible.Root,
94
+ {
95
+ "data-slot": "sidebar-group",
96
+ open,
97
+ onOpenChange: (next) => {
98
+ if (openProp == null) setUncontrolled(next);
99
+ onOpenChange?.(next);
100
+ },
101
+ className: cn("group/sidebar-group flex flex-col gap-0.5", className),
102
+ ...props,
103
+ children: [
104
+ /* @__PURE__ */ jsxs(
105
+ Collapsible.Trigger,
106
+ {
107
+ "aria-controls": regionId,
108
+ ...triggerProps,
109
+ className: cn(
110
+ "flex h-8 w-full shrink-0 items-center gap-2 rounded-lg px-3 text-left text-text-muted",
111
+ "transition-[background-color,box-shadow] duration-(--duration-fast) ease-(--ease-out)",
112
+ "[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]",
113
+ "not-data-active:satin-hover:bg-bg-muted",
114
+ rowFocus,
115
+ triggerProps?.className
116
+ ),
117
+ children: [
118
+ icon,
119
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm leading-4 font-medium tracking-normal text-text-default", children: label }),
120
+ typeof count === "number" && /* @__PURE__ */ jsx("span", { className: "shrink-0 px-1.5 py-0.5 text-sm leading-4 font-medium tracking-normal text-tone-fg tabular-nums", children: count }),
121
+ /* @__PURE__ */ jsx(
122
+ NavArrowRight,
123
+ {
124
+ "aria-hidden": true,
125
+ className: "transition-transform duration-(--duration-base) ease-(--ease-out) group-data-[state=open]/sidebar-group:rotate-90 motion-reduce:transition-none"
126
+ }
127
+ )
128
+ ]
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsx("div", { id: regionId, "data-state": open ? "open" : "closed", className: "satin-expand", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children }) })
132
+ ]
133
+ }
134
+ );
135
+ }
136
+ function SidebarSubItem({
137
+ className,
138
+ label,
139
+ active = false,
140
+ disabled = false,
141
+ asChild = false,
142
+ href,
143
+ children,
144
+ ...props
145
+ }) {
146
+ const Comp = asChild ? Slot.Root : "a";
147
+ return /* @__PURE__ */ jsx(
148
+ Comp,
149
+ {
150
+ "data-slot": "sidebar-sub-item",
151
+ "data-active": active || void 0,
152
+ "aria-current": active ? "page" : void 0,
153
+ "aria-disabled": disabled || void 0,
154
+ href: disabled ? void 0 : href,
155
+ tabIndex: disabled ? -1 : void 0,
156
+ className: cn(
157
+ "flex h-8 shrink-0 items-center rounded-lg pr-3 pl-[34px] text-sm font-normal text-text-muted no-underline select-none",
158
+ "transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)",
159
+ "not-data-active:satin-hover:bg-bg-muted not-data-active:satin-hover:text-text-default",
160
+ rowFocus,
161
+ "data-active:bg-bg-selected data-active:text-text-default",
162
+ "aria-disabled:pointer-events-none aria-disabled:opacity-50",
163
+ className
164
+ ),
165
+ ...props,
166
+ children: asChild ? children : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label })
167
+ }
168
+ );
169
+ }
170
+ function SidebarSubGroup({
171
+ className,
172
+ label,
173
+ children,
174
+ active = false,
175
+ open: openProp,
176
+ defaultOpen,
177
+ onOpenChange,
178
+ ...props
179
+ }) {
180
+ const [uncontrolled, setUncontrolled] = React.useState(defaultOpen ?? active);
181
+ const open = openProp ?? uncontrolled;
182
+ const regionId = React.useId();
183
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "sidebar-sub-group", "data-state": open ? "open" : "closed", className: cn("group/sub-group flex flex-col gap-0.5", className), ...props, children: [
184
+ /* @__PURE__ */ jsxs(
185
+ "button",
186
+ {
187
+ type: "button",
188
+ "aria-expanded": open,
189
+ "aria-controls": regionId,
190
+ "data-active": active || void 0,
191
+ onClick: () => {
192
+ if (openProp == null) setUncontrolled(!open);
193
+ onOpenChange?.(!open);
194
+ },
195
+ className: cn(
196
+ "flex h-8 w-full shrink-0 items-center gap-2 rounded-lg pr-3 pl-[34px] text-left text-sm font-normal text-text-muted select-none",
197
+ "transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)",
198
+ "satin-hover:bg-bg-muted satin-hover:text-text-default data-active:text-text-default",
199
+ "[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]",
200
+ rowFocus
201
+ ),
202
+ children: [
203
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: label }),
204
+ /* @__PURE__ */ jsx(
205
+ NavArrowRight,
206
+ {
207
+ "aria-hidden": true,
208
+ className: "text-text-muted transition-transform duration-(--duration-base) ease-(--ease-out) group-data-[state=open]/sub-group:rotate-90 motion-reduce:transition-none"
209
+ }
210
+ )
211
+ ]
212
+ }
213
+ ),
214
+ /* @__PURE__ */ jsx("div", { id: regionId, "data-state": open ? "open" : "closed", className: "satin-expand", children: /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5 [&>[data-slot=sidebar-sub-item]]:pl-[46px]", children }) })
215
+ ] });
216
+ }
217
+
218
+ export { Sidebar, SidebarGroup, SidebarItem, SidebarSubGroup, SidebarSubItem };
219
+ //# sourceMappingURL=chunk-BNTPPZCK.js.map
220
+ //# sourceMappingURL=chunk-BNTPPZCK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/sidebar.tsx"],"names":[],"mappings":"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","file":"chunk-BNTPPZCK.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Collapsible, Slot, Tooltip } from 'radix-ui'\nimport { NavArrowRight } from 'iconoir-react'\nimport { cn } from '../lib/utils'\n\n/**\n * Sidebar, 1:1 with the uiKit sidebar sets: `sidebar/navigation` (0:3358), `sidebar/groupHeader`\n * (3468:18403) and `sidebar/subItem` (3468:18360).\n *\n * - `SidebarItem` is a 32px link row: 14px icon, medium 13/16 label in text/muted, radius-lg,\n * 8px padding. Hover fills bg/muted; the current page fills border/input and turns the label\n * and icon text/default. `count` adds a red 16px counter; `iconOnly` is the 32 × 32 rail with\n * the label in a tooltip.\n * - `SidebarGroup` is a collapsible group: the header row (12px padding, icon, label in\n * text/default, a plain count, chevron right → down) and its `SidebarSubItem`s.\n * - `SidebarSubItem` is a regular 13px row whose text starts in line with the group label\n * (34px in). Hover bg/muted, active bg/selected, disabled 50%.\n * - `SidebarSubGroup` is a sub-item that holds sub-items of its own (Chart → Bar chart,\n * Channel chart): the same row with a chevron on the right, folding open and shut like the\n * group (satin-expand, the chevron turning right → down). Its sub-items start 12px further\n * in (46px). It opens on its own when one of them is the current page, and its label turns\n * text/default while it holds the current page.\n *\n * Rows sit 2px apart. Focus draws the 1px border/focus outline Figma shows on the focus\n * variants, inset so the row doesn't move. Every state also answers to `data-force`.\n */\n\nconst rowFocus =\n 'outline-none satin-focus:[box-shadow:inset_0_0_0_1px_var(--border-focus)]'\n\nexport interface SidebarProps extends React.ComponentProps<'nav'> {}\n\n/** The navigation landmark. Name it with `aria-label` when a page has more than one nav. */\nexport function Sidebar({ className, ...props }: SidebarProps) {\n return <nav data-slot=\"sidebar\" className={cn('flex flex-col gap-0.5', className)} {...props} />\n}\n\nexport interface SidebarItemProps extends Omit<React.ComponentProps<'a'>, 'children'> {\n label: string\n icon?: React.ReactNode\n /** The current page. Sets `aria-current=\"page\"`. */\n active?: boolean\n /** Unread or pending work. Hidden at 0. */\n count?: number\n /** The collapsed rail: icon only, label in a tooltip. */\n iconOnly?: boolean\n disabled?: boolean\n /** Render your router's link instead of `<a>`. */\n asChild?: boolean\n children?: React.ReactNode\n}\n\nexport function SidebarItem({\n className,\n label,\n icon,\n active = false,\n count,\n iconOnly = false,\n disabled = false,\n asChild = false,\n href,\n children,\n ...props\n}: SidebarItemProps) {\n const Comp = asChild ? Slot.Root : 'a'\n const showCount = typeof count === 'number' && count > 0\n\n const row = (\n <Comp\n data-slot=\"sidebar-item\"\n data-active={active || undefined}\n aria-current={active ? 'page' : undefined}\n aria-disabled={disabled || undefined}\n aria-label={iconOnly ? (showCount ? `${label}, ${count}` : label) : undefined}\n href={disabled ? undefined : href}\n tabIndex={disabled ? -1 : undefined}\n className={cn(\n 'flex h-8 shrink-0 items-center gap-2 rounded-lg px-2 text-sm leading-4 font-medium tracking-normal text-text-muted no-underline select-none',\n 'transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)',\n '[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]',\n 'not-data-active:satin-hover:bg-bg-muted',\n rowFocus,\n 'data-active:bg-border-input data-active:text-text-default',\n 'aria-disabled:pointer-events-none aria-disabled:opacity-50',\n iconOnly && 'relative size-8 justify-center px-0',\n className,\n )}\n {...props}\n >\n {asChild ? (\n children\n ) : (\n <>\n {icon}\n {!iconOnly && <span className=\"min-w-0 flex-1 truncate\">{label}</span>}\n {showCount && !iconOnly && <SidebarCount count={count} />}\n {showCount && iconOnly && (\n <span aria-hidden className=\"absolute top-1 right-1 size-1.5 rounded-full bg-action-destructive-bg\" />\n )}\n </>\n )}\n </Comp>\n )\n\n if (!iconOnly) return row\n return (\n <Tooltip.Provider delayDuration={300}>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{row}</Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n side=\"right\"\n sideOffset={6}\n collisionPadding={8}\n className=\"z-50 rounded-md bg-action-inverse-bg px-2 py-1 text-xs font-medium text-text-on-inverse [box-shadow:0_1px_2px_0_var(--effect-shadow-xs)]\"\n >\n {label}\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </Tooltip.Provider>\n )\n}\n\n/** The red counter from sidebar/navigation: 16 high, 18 wide at least, radius-xs. */\nfunction SidebarCount({ count }: { count: number }) {\n return (\n // 11/12 has no type token in the kit; Figma uses it raw for this counter.\n <span className=\"inline-flex h-4 min-w-[18px] shrink-0 items-center justify-center rounded-xs bg-action-destructive-bg px-1 text-[11px] leading-3 font-medium tracking-normal text-text-on-solid tabular-nums\">\n {count > 99 ? '99+' : count}\n </span>\n )\n}\n\nexport interface SidebarGroupProps\n extends Omit<React.ComponentProps<typeof Collapsible.Root>, 'children'> {\n label: string\n icon?: React.ReactNode\n /** How many items the group holds. */\n count?: number\n children?: React.ReactNode\n /** Forwarded to the header button, e.g. `data-force=\"hover\"` on a state sheet. */\n triggerProps?: React.ComponentProps<'button'> & { 'data-force'?: string }\n}\n\nexport function SidebarGroup({\n className,\n label,\n icon,\n count,\n defaultOpen = true,\n open: openProp,\n onOpenChange,\n children,\n triggerProps,\n ...props\n}: SidebarGroupProps) {\n // The group keeps its own open state and region, not Radix's Content: Content measures itself\n // with transitions switched off on every toggle, which would cut the fold (satin-expand).\n const [uncontrolled, setUncontrolled] = React.useState(defaultOpen)\n const open = openProp ?? uncontrolled\n const regionId = React.useId()\n return (\n <Collapsible.Root\n data-slot=\"sidebar-group\"\n open={open}\n onOpenChange={(next) => {\n if (openProp == null) setUncontrolled(next)\n onOpenChange?.(next)\n }}\n className={cn('group/sidebar-group flex flex-col gap-0.5', className)}\n {...props}\n >\n <Collapsible.Trigger\n aria-controls={regionId}\n {...triggerProps}\n className={cn(\n 'flex h-8 w-full shrink-0 items-center gap-2 rounded-lg px-3 text-left text-text-muted',\n 'transition-[background-color,box-shadow] duration-(--duration-fast) ease-(--ease-out)',\n '[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]',\n 'not-data-active:satin-hover:bg-bg-muted',\n rowFocus,\n triggerProps?.className,\n )}\n >\n {icon}\n <span className=\"min-w-0 flex-1 truncate text-sm leading-4 font-medium tracking-normal text-text-default\">\n {label}\n </span>\n {typeof count === 'number' && (\n <span className=\"shrink-0 px-1.5 py-0.5 text-sm leading-4 font-medium tracking-normal text-tone-fg tabular-nums\">\n {count}\n </span>\n )}\n <NavArrowRight\n aria-hidden\n className=\"transition-transform duration-(--duration-base) ease-(--ease-out) group-data-[state=open]/sidebar-group:rotate-90 motion-reduce:transition-none\"\n />\n </Collapsible.Trigger>\n {/* Always mounted so it can fold away: grows downwards from under the header (motion.css). */}\n <div id={regionId} data-state={open ? 'open' : 'closed'} className=\"satin-expand\">\n <div className=\"flex flex-col gap-0.5\">{children}</div>\n </div>\n </Collapsible.Root>\n )\n}\n\nexport interface SidebarSubItemProps extends Omit<React.ComponentProps<'a'>, 'children'> {\n label: string\n active?: boolean\n disabled?: boolean\n asChild?: boolean\n children?: React.ReactNode\n}\n\nexport function SidebarSubItem({\n className,\n label,\n active = false,\n disabled = false,\n asChild = false,\n href,\n children,\n ...props\n}: SidebarSubItemProps) {\n const Comp = asChild ? Slot.Root : 'a'\n return (\n <Comp\n data-slot=\"sidebar-sub-item\"\n data-active={active || undefined}\n aria-current={active ? 'page' : undefined}\n aria-disabled={disabled || undefined}\n href={disabled ? undefined : href}\n tabIndex={disabled ? -1 : undefined}\n className={cn(\n 'flex h-8 shrink-0 items-center rounded-lg pr-3 pl-[34px] text-sm font-normal text-text-muted no-underline select-none',\n 'transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)',\n 'not-data-active:satin-hover:bg-bg-muted not-data-active:satin-hover:text-text-default',\n rowFocus,\n 'data-active:bg-bg-selected data-active:text-text-default',\n 'aria-disabled:pointer-events-none aria-disabled:opacity-50',\n className,\n )}\n {...props}\n >\n {asChild ? children : <span className=\"min-w-0 flex-1 truncate\">{label}</span>}\n </Comp>\n )\n}\n\nexport interface SidebarSubGroupProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n label: string\n /** Its `SidebarSubItem`s; they sit 12px further in. */\n children?: React.ReactNode\n /** One of its sub-items is the current page: opens it by default and marks the label. */\n active?: boolean\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n}\n\nexport function SidebarSubGroup({\n className,\n label,\n children,\n active = false,\n open: openProp,\n defaultOpen,\n onOpenChange,\n ...props\n}: SidebarSubGroupProps) {\n const [uncontrolled, setUncontrolled] = React.useState(defaultOpen ?? active)\n const open = openProp ?? uncontrolled\n const regionId = React.useId()\n return (\n <div data-slot=\"sidebar-sub-group\" data-state={open ? 'open' : 'closed'} className={cn('group/sub-group flex flex-col gap-0.5', className)} {...props}>\n <button\n type=\"button\"\n aria-expanded={open}\n aria-controls={regionId}\n data-active={active || undefined}\n onClick={() => {\n if (openProp == null) setUncontrolled(!open)\n onOpenChange?.(!open)\n }}\n className={cn(\n 'flex h-8 w-full shrink-0 items-center gap-2 rounded-lg pr-3 pl-[34px] text-left text-sm font-normal text-text-muted select-none',\n 'transition-[background-color,color,box-shadow] duration-(--duration-fast) ease-(--ease-out)',\n 'satin-hover:bg-bg-muted satin-hover:text-text-default data-active:text-text-default',\n '[&_svg]:size-icon-size-sm [&_svg]:shrink-0 [&_svg]:[stroke-width:1.875]',\n rowFocus,\n )}\n >\n <span className=\"min-w-0 flex-1 truncate\">{label}</span>\n <NavArrowRight\n aria-hidden\n className=\"text-text-muted transition-transform duration-(--duration-base) ease-(--ease-out) group-data-[state=open]/sub-group:rotate-90 motion-reduce:transition-none\"\n />\n </button>\n <div id={regionId} data-state={open ? 'open' : 'closed'} className=\"satin-expand\">\n <div className=\"flex flex-col gap-0.5 [&>[data-slot=sidebar-sub-item]]:pl-[46px]\">{children}</div>\n </div>\n </div>\n )\n}\n"]}