@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,166 @@
1
+ import { menuItemClass, MenuItemContent } from './chunk-3DINAQLL.js';
2
+ import { Kbd, KbdHint, KbdArrowUp, KbdArrowDown, KbdReturn } from './chunk-BKZBWPUH.js';
3
+ import { cn } from './chunk-H63FYCMY.js';
4
+ import * as React from 'react';
5
+ import { Dialog } from 'radix-ui';
6
+ import { Search } from 'iconoir-react';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ var hit = (item, q) => {
10
+ const t = q.trim().toLowerCase();
11
+ if (!t) return true;
12
+ return [item.label, item.description ?? "", ...item.keywords ?? []].some((s) => s.toLowerCase().includes(t));
13
+ };
14
+ function CommandMenu({
15
+ groups,
16
+ open: openProp,
17
+ defaultOpen = false,
18
+ onOpenChange,
19
+ hotkey = true,
20
+ placeholder = "Type a command or search\u2026",
21
+ emptyText = (q) => `No results for \u201C${q}\u201D`,
22
+ hints = true,
23
+ modal = true,
24
+ container,
25
+ onOpenAutoFocus,
26
+ className
27
+ }) {
28
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
29
+ const open = openProp ?? uncontrolledOpen;
30
+ const setOpen = React.useCallback(
31
+ (next) => {
32
+ if (openProp == null) setUncontrolledOpen(next);
33
+ onOpenChange?.(next);
34
+ },
35
+ [openProp, onOpenChange]
36
+ );
37
+ const [query, setQuery] = React.useState("");
38
+ const [active, setActive] = React.useState(0);
39
+ const listId = React.useId();
40
+ const listRef = React.useRef(null);
41
+ React.useEffect(() => {
42
+ if (!hotkey) return;
43
+ const onKey = (e) => {
44
+ if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
45
+ e.preventDefault();
46
+ setOpen(!open);
47
+ }
48
+ };
49
+ document.addEventListener("keydown", onKey);
50
+ return () => document.removeEventListener("keydown", onKey);
51
+ }, [hotkey, open, setOpen]);
52
+ React.useEffect(() => {
53
+ if (open) {
54
+ setQuery("");
55
+ setActive(0);
56
+ }
57
+ }, [open]);
58
+ const shown = groups.map((g) => ({ ...g, items: g.items.filter((i) => hit(i, query)) })).filter((g) => g.items.length);
59
+ const flat = shown.flatMap((g) => g.items);
60
+ const optionId = (i) => `${listId}-${i}`;
61
+ React.useEffect(() => {
62
+ listRef.current?.querySelector(`[id="${optionId(active)}"]`)?.scrollIntoView({ block: "nearest" });
63
+ }, [active]);
64
+ const run = (item) => {
65
+ if (!item || item.disabled) return;
66
+ setOpen(false);
67
+ item.onSelect?.();
68
+ };
69
+ const position = container ? "absolute" : "fixed";
70
+ let index = -1;
71
+ return /* @__PURE__ */ jsx(Dialog.Root, { open, onOpenChange: setOpen, modal, children: /* @__PURE__ */ jsxs(Dialog.Portal, { container, children: [
72
+ /* @__PURE__ */ jsx(Dialog.Overlay, { className: cn(position, "inset-0 z-50 bg-black-a40") }),
73
+ /* @__PURE__ */ jsx("div", { className: cn(position, "pointer-events-none inset-0 z-50 flex items-center justify-center p-4"), children: /* @__PURE__ */ jsxs(
74
+ Dialog.Content,
75
+ {
76
+ "data-slot": "command-menu",
77
+ "aria-describedby": void 0,
78
+ onOpenAutoFocus,
79
+ className: cn(
80
+ "pointer-events-auto flex h-fit max-h-[min(480px,76vh)] w-[520px] max-w-full flex-col overflow-hidden",
81
+ "rounded-2xl border border-border-subtle bg-bg-popover",
82
+ "[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]",
83
+ "outline-none data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]",
84
+ className
85
+ ),
86
+ children: [
87
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: "Command menu" }),
88
+ /* @__PURE__ */ jsxs("label", { className: "flex h-12 shrink-0 items-center gap-2 border-b border-border-subtle px-4 text-text-muted", children: [
89
+ /* @__PURE__ */ jsx(Search, { "aria-hidden": true, className: "size-4 shrink-0 [stroke-width:1.875]" }),
90
+ /* @__PURE__ */ jsx(
91
+ "input",
92
+ {
93
+ role: "combobox",
94
+ "aria-expanded": true,
95
+ "aria-controls": listId,
96
+ "aria-autocomplete": "list",
97
+ "aria-activedescendant": flat[active] ? optionId(active) : void 0,
98
+ "aria-label": "Search commands",
99
+ value: query,
100
+ placeholder,
101
+ onChange: (e) => {
102
+ setQuery(e.target.value);
103
+ setActive(0);
104
+ },
105
+ onKeyDown: (e) => {
106
+ if (e.key === "ArrowDown" || e.key === "ArrowUp") {
107
+ e.preventDefault();
108
+ const step = e.key === "ArrowDown" ? 1 : -1;
109
+ setActive((a) => flat.length ? (a + step + flat.length) % flat.length : 0);
110
+ } else if (e.key === "Enter") {
111
+ e.preventDefault();
112
+ run(flat[active]);
113
+ }
114
+ },
115
+ className: "min-w-0 flex-1 bg-transparent text-base leading-[21px] text-text-default outline-none placeholder:text-text-muted focus-visible:ring-0"
116
+ }
117
+ ),
118
+ /* @__PURE__ */ jsx(Kbd, { size: "md", "aria-hidden": true, children: "Esc" })
119
+ ] }),
120
+ /* @__PURE__ */ jsx("div", { ref: listRef, id: listId, role: "listbox", "aria-label": "Commands", className: "flex min-h-0 flex-col gap-2 overflow-y-auto p-2", children: flat.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-2 py-8 text-center text-sm text-text-muted", children: emptyText(query) }) : shown.map((g, gi) => /* @__PURE__ */ jsxs("div", { role: "group", "aria-labelledby": `${listId}-g${gi}`, className: "flex flex-col", children: [
121
+ /* @__PURE__ */ jsx("div", { id: `${listId}-g${gi}`, className: "flex h-6 items-center px-2 text-xs leading-3 font-medium tracking-normal text-text-muted", children: g.label }),
122
+ g.items.map((item) => {
123
+ index += 1;
124
+ const i = index;
125
+ return /* @__PURE__ */ jsx(
126
+ "div",
127
+ {
128
+ id: optionId(i),
129
+ role: "option",
130
+ "aria-selected": i === active,
131
+ "aria-disabled": item.disabled || void 0,
132
+ "data-highlighted": i === active ? "" : void 0,
133
+ "data-disabled": item.disabled ? "" : void 0,
134
+ onPointerMove: () => setActive(i),
135
+ onMouseDown: (e) => e.preventDefault(),
136
+ onClick: () => run(item),
137
+ className: menuItemClass,
138
+ children: /* @__PURE__ */ jsx(
139
+ MenuItemContent,
140
+ {
141
+ label: item.label,
142
+ description: item.description,
143
+ icon: item.icon,
144
+ layout: "inline",
145
+ shortcut: item.shortcut
146
+ }
147
+ )
148
+ },
149
+ item.id
150
+ );
151
+ })
152
+ ] }, gi)) }),
153
+ hints && /* @__PURE__ */ jsxs("div", { "aria-hidden": true, className: "flex h-10 shrink-0 items-center gap-4 border-t border-border-subtle px-4", children: [
154
+ /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdArrowUp, {}, "up"), /* @__PURE__ */ jsx(KbdArrowDown, {}, "down")], label: "Navigate" }),
155
+ /* @__PURE__ */ jsx(KbdHint, { keys: [/* @__PURE__ */ jsx(KbdReturn, {}, "return")], label: "Open" }),
156
+ /* @__PURE__ */ jsx(KbdHint, { className: "ml-auto", keys: ["Esc"], label: "Close" })
157
+ ] })
158
+ ]
159
+ }
160
+ ) })
161
+ ] }) });
162
+ }
163
+
164
+ export { CommandMenu };
165
+ //# sourceMappingURL=chunk-P4O6TGDR.js.map
166
+ //# sourceMappingURL=chunk-P4O6TGDR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/command-menu.tsx"],"names":["DialogPrimitive"],"mappings":"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","file":"chunk-P4O6TGDR.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Dialog as DialogPrimitive } from 'radix-ui'\nimport { Search } from 'iconoir-react'\nimport { cn } from '../lib/utils'\nimport { menuItemClass, MenuItemContent } from './dropdown'\nimport { Kbd, KbdArrowDown, KbdArrowUp, KbdHint, KbdReturn } from './kbd'\n\n/**\n * Command menu, 1:1 with the uiKit `Command menu` set (4024:3582): the ⌘K palette. A 520px\n * popover surface (radius-2xl, border/subtle, the shadcn `lg` shadow) with a 48px search row\n * (16px icon, 14px query, an Esc key, 16px in) over a border/subtle rule; titled groups 8px\n * apart in 8px of padding, each with a 24px heading (12px medium, text/muted) and inline menu\n * rows; and a 40px footer of key hints (Navigate, Open on the left, Close on the right).\n *\n * Rows are the Dropdown's: a 16px icon, the label, an optional description after it and an\n * optional `shortcut` (Kbd sm) on the right. The highlighted row takes the menu highlight,\n * bg/selected, whether the pointer or the arrow keys put it there. The first match is\n * highlighted; Enter runs it and closes the menu.\n *\n * It sits in the middle of the screen (or of its `container`).\n *\n * Built on the Radix Dialog (focus trap, Escape, focus back to where it was). With `hotkey`,\n * ⌘K or Ctrl+K anywhere on the page toggles it.\n */\nexport interface CommandItem {\n id: string\n label: string\n description?: string\n icon?: React.ReactNode\n /** Keys that run it outside the menu, e.g. \"⌘N\". Optional. */\n shortcut?: string\n /** More words to match on. */\n keywords?: string[]\n disabled?: boolean\n onSelect?: () => void\n}\n\nexport interface CommandGroup {\n label: React.ReactNode\n items: CommandItem[]\n}\n\nexport interface CommandMenuProps {\n groups: CommandGroup[]\n open?: boolean\n defaultOpen?: boolean\n onOpenChange?: (open: boolean) => void\n /** Toggle the menu with ⌘K / Ctrl+K. */\n hotkey?: boolean\n placeholder?: string\n /** Shown when nothing matches; gets the query. */\n emptyText?: (query: string) => React.ReactNode\n /** Show the footer of key hints. */\n hints?: boolean\n /** Modal blocks the page and shows the overlay; turn it off for inline previews. */\n modal?: boolean\n /** Portal target. Defaults to `document.body`. */\n container?: HTMLElement | null\n onOpenAutoFocus?: (event: Event) => void\n className?: string\n}\n\nconst hit = (item: CommandItem, q: string) => {\n const t = q.trim().toLowerCase()\n if (!t) return true\n return [item.label, item.description ?? '', ...(item.keywords ?? [])].some((s) => s.toLowerCase().includes(t))\n}\n\nexport function CommandMenu({\n groups,\n open: openProp,\n defaultOpen = false,\n onOpenChange,\n hotkey = true,\n placeholder = 'Type a command or search…',\n emptyText = (q) => `No results for “${q}”`,\n hints = true,\n modal = true,\n container,\n onOpenAutoFocus,\n className,\n}: CommandMenuProps) {\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen)\n const open = openProp ?? uncontrolledOpen\n const setOpen = React.useCallback(\n (next: boolean) => {\n if (openProp == null) setUncontrolledOpen(next)\n onOpenChange?.(next)\n },\n [openProp, onOpenChange],\n )\n\n const [query, setQuery] = React.useState('')\n const [active, setActive] = React.useState(0)\n const listId = React.useId()\n const listRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!hotkey) return\n const onKey = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {\n e.preventDefault()\n setOpen(!open)\n }\n }\n document.addEventListener('keydown', onKey)\n return () => document.removeEventListener('keydown', onKey)\n }, [hotkey, open, setOpen])\n\n // A fresh query every time it opens.\n React.useEffect(() => {\n if (open) {\n setQuery('')\n setActive(0)\n }\n }, [open])\n\n const shown = groups.map((g) => ({ ...g, items: g.items.filter((i) => hit(i, query)) })).filter((g) => g.items.length)\n const flat = shown.flatMap((g) => g.items)\n const optionId = (i: number) => `${listId}-${i}`\n\n // Keep the highlighted row in view as the arrows move it.\n React.useEffect(() => {\n listRef.current?.querySelector(`[id=\"${optionId(active)}\"]`)?.scrollIntoView({ block: 'nearest' })\n }, [active])\n\n const run = (item: CommandItem | undefined) => {\n if (!item || item.disabled) return\n setOpen(false)\n item.onSelect?.()\n }\n\n const position = container ? 'absolute' : 'fixed'\n let index = -1\n\n return (\n <DialogPrimitive.Root open={open} onOpenChange={setOpen} modal={modal}>\n <DialogPrimitive.Portal container={container}>\n <DialogPrimitive.Overlay className={cn(position, 'inset-0 z-50 bg-black-a40')} />\n <div className={cn(position, 'pointer-events-none inset-0 z-50 flex items-center justify-center p-4')}>\n <DialogPrimitive.Content\n data-slot=\"command-menu\"\n aria-describedby={undefined}\n onOpenAutoFocus={onOpenAutoFocus}\n className={cn(\n 'pointer-events-auto flex h-fit max-h-[min(480px,76vh)] w-[520px] max-w-full flex-col overflow-hidden',\n 'rounded-2xl border border-border-subtle bg-bg-popover',\n '[box-shadow:0_4px_6px_-4px_var(--effect-shadow-sm),0_10px_15px_-3px_var(--effect-shadow-sm)]',\n 'outline-none data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]',\n className,\n )}\n >\n <DialogPrimitive.Title className=\"sr-only\">Command menu</DialogPrimitive.Title>\n <label className=\"flex h-12 shrink-0 items-center gap-2 border-b border-border-subtle px-4 text-text-muted\">\n <Search aria-hidden className=\"size-4 shrink-0 [stroke-width:1.875]\" />\n <input\n role=\"combobox\"\n aria-expanded\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={flat[active] ? optionId(active) : undefined}\n aria-label=\"Search commands\"\n value={query}\n placeholder={placeholder}\n onChange={(e) => {\n setQuery(e.target.value)\n setActive(0)\n }}\n onKeyDown={(e) => {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault()\n const step = e.key === 'ArrowDown' ? 1 : -1\n setActive((a) => (flat.length ? (a + step + flat.length) % flat.length : 0))\n } else if (e.key === 'Enter') {\n e.preventDefault()\n run(flat[active])\n }\n }}\n className=\"min-w-0 flex-1 bg-transparent text-base leading-[21px] text-text-default outline-none placeholder:text-text-muted focus-visible:ring-0\"\n />\n <Kbd size=\"md\" aria-hidden>\n Esc\n </Kbd>\n </label>\n\n <div ref={listRef} id={listId} role=\"listbox\" aria-label=\"Commands\" className=\"flex min-h-0 flex-col gap-2 overflow-y-auto p-2\">\n {flat.length === 0 ? (\n <p className=\"px-2 py-8 text-center text-sm text-text-muted\">{emptyText(query)}</p>\n ) : (\n shown.map((g, gi) => (\n <div key={gi} role=\"group\" aria-labelledby={`${listId}-g${gi}`} className=\"flex flex-col\">\n <div id={`${listId}-g${gi}`} className=\"flex h-6 items-center px-2 text-xs leading-3 font-medium tracking-normal text-text-muted\">\n {g.label}\n </div>\n {g.items.map((item) => {\n index += 1\n const i = index\n return (\n <div\n key={item.id}\n id={optionId(i)}\n role=\"option\"\n aria-selected={i === active}\n aria-disabled={item.disabled || undefined}\n data-highlighted={i === active ? '' : undefined}\n data-disabled={item.disabled ? '' : undefined}\n onPointerMove={() => setActive(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => run(item)}\n className={menuItemClass}\n >\n <MenuItemContent\n label={item.label}\n description={item.description}\n icon={item.icon}\n layout=\"inline\"\n shortcut={item.shortcut}\n />\n </div>\n )\n })}\n </div>\n ))\n )}\n </div>\n\n {hints && (\n <div aria-hidden className=\"flex h-10 shrink-0 items-center gap-4 border-t border-border-subtle px-4\">\n <KbdHint keys={[<KbdArrowUp key=\"up\" />, <KbdArrowDown key=\"down\" />]} label=\"Navigate\" />\n <KbdHint keys={[<KbdReturn key=\"return\" />]} label=\"Open\" />\n <KbdHint className=\"ml-auto\" keys={['Esc']} label=\"Close\" />\n </div>\n )}\n </DialogPrimitive.Content>\n </div>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n )\n}\n"]}
@@ -0,0 +1,81 @@
1
+ import { menuSurfaceClass, MenuItemContent, menuItemClass } from './chunk-3DINAQLL.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import 'react';
4
+ import { ContextMenu as ContextMenu$1 } from 'radix-ui';
5
+ import { NavArrowRight } from 'iconoir-react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var contentClass = cn(
9
+ "pointer-events-auto z-50 flex w-[255px] max-w-[calc(100vw-16px)] flex-col overflow-x-clip overflow-y-auto p-1",
10
+ menuSurfaceClass,
11
+ "outline-none data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]"
12
+ );
13
+ function ContextMenu({
14
+ trigger,
15
+ children,
16
+ onOpenChange,
17
+ container,
18
+ modal = true,
19
+ onFocusOutside,
20
+ className
21
+ }) {
22
+ return /* @__PURE__ */ jsxs(ContextMenu$1.Root, { onOpenChange, modal, children: [
23
+ /* @__PURE__ */ jsx(ContextMenu$1.Trigger, { asChild: true, children: trigger }),
24
+ /* @__PURE__ */ jsx(ContextMenu$1.Portal, { container, children: /* @__PURE__ */ jsx(
25
+ ContextMenu$1.Content,
26
+ {
27
+ "data-slot": "context-menu",
28
+ collisionPadding: 8,
29
+ onFocusOutside,
30
+ className: cn(contentClass, "origin-(--radix-context-menu-content-transform-origin)", "max-h-(--radix-context-menu-content-available-height)", className),
31
+ children
32
+ }
33
+ ) })
34
+ ] });
35
+ }
36
+ function ContextMenuItem({ label, icon, shortcut, description, destructive, className, ...props }) {
37
+ return /* @__PURE__ */ jsx(
38
+ ContextMenu$1.Item,
39
+ {
40
+ "data-slot": "context-menu-item",
41
+ textValue: label,
42
+ className: cn(menuItemClass, destructive && "[&_*]:text-action-destructive-fg", className),
43
+ ...props,
44
+ children: /* @__PURE__ */ jsx(MenuItemContent, { label, icon, shortcut, description, layout: "inline" })
45
+ }
46
+ );
47
+ }
48
+ function ContextMenuSub({ label, icon, children, disabled }) {
49
+ return /* @__PURE__ */ jsxs(ContextMenu$1.Sub, { children: [
50
+ /* @__PURE__ */ jsxs(
51
+ ContextMenu$1.SubTrigger,
52
+ {
53
+ "data-slot": "context-menu-sub",
54
+ disabled,
55
+ textValue: label,
56
+ className: cn(menuItemClass, "data-[state=open]:bg-bg-selected"),
57
+ children: [
58
+ /* @__PURE__ */ jsx(MenuItemContent, { label, icon, layout: "inline" }),
59
+ /* @__PURE__ */ jsx(NavArrowRight, { "aria-hidden": true, className: "size-4 text-text-muted [stroke-width:1.875]" })
60
+ ]
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(
64
+ ContextMenu$1.SubContent,
65
+ {
66
+ sideOffset: 4,
67
+ alignOffset: -5,
68
+ collisionPadding: 8,
69
+ className: cn(contentClass, "w-[220px] origin-(--radix-context-menu-content-transform-origin)"),
70
+ children
71
+ }
72
+ ) })
73
+ ] });
74
+ }
75
+ function ContextMenuSeparator({ className }) {
76
+ return /* @__PURE__ */ jsx(ContextMenu$1.Separator, { className: cn("-mx-1 my-1 h-px bg-bg-muted", className) });
77
+ }
78
+
79
+ export { ContextMenu, ContextMenuItem, ContextMenuSeparator, ContextMenuSub };
80
+ //# sourceMappingURL=chunk-PF3YBUKT.js.map
81
+ //# sourceMappingURL=chunk-PF3YBUKT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/context-menu.tsx"],"names":["ContextPrimitive"],"mappings":"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","file":"chunk-PF3YBUKT.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { ContextMenu as ContextPrimitive } from 'radix-ui'\nimport { NavArrowRight } from 'iconoir-react'\nimport { cn } from '../lib/utils'\nimport { MenuItemContent, menuItemClass, menuSurfaceClass, type MenuItemContentProps } from './dropdown'\n\n/**\n * ContextMenu, 1:1 with the uiKit design (🆕 context menu & hover card): DropdownMenu's surface\n * and rows, opened by right-click (or a long press) on its target, at the pointer. 255 wide, 4px\n * in, rows 0 apart, separators a 1px bg/muted rule. Shortcuts on the right as Kbd; a submenu row\n * ends in a text/muted chevron (the kit's `showSubmenu`) and opens beside it, 4px off; destructive\n * rows are action/destructive/fg (red-400 in dark), icon included, and go last.\n *\n * Built on the Radix ContextMenu: arrow keys, typeahead, Escape, Shift+F10 / the menu key on the\n * focused target.\n */\nexport interface ContextMenuProps {\n /** What right-click opens the menu on. Rendered with `asChild`, so pass one element. */\n trigger: React.ReactNode\n /** `ContextMenuItem`s, `ContextMenuSub`s and `ContextMenuSeparator`s. */\n children: React.ReactNode\n onOpenChange?: (open: boolean) => void\n /** Portal target. Defaults to `document.body`. */\n container?: HTMLElement | null\n /** Modal menus block the rest of the page while open. */\n modal?: boolean\n /** Focus moved outside a non-modal menu; call `preventDefault()` to keep it open. */\n onFocusOutside?: (event: Event) => void\n className?: string\n}\n\nconst contentClass = cn(\n 'pointer-events-auto z-50 flex w-[255px] max-w-[calc(100vw-16px)] flex-col overflow-x-clip overflow-y-auto p-1',\n menuSurfaceClass,\n 'outline-none data-[state=open]:animate-[satin-enter_var(--duration-base)_var(--ease-out)]',\n)\n\nexport function ContextMenu({\n trigger,\n children,\n onOpenChange,\n container,\n modal = true,\n onFocusOutside,\n className,\n}: ContextMenuProps) {\n return (\n <ContextPrimitive.Root onOpenChange={onOpenChange} modal={modal}>\n <ContextPrimitive.Trigger asChild>{trigger}</ContextPrimitive.Trigger>\n <ContextPrimitive.Portal container={container}>\n <ContextPrimitive.Content\n data-slot=\"context-menu\"\n collisionPadding={8}\n onFocusOutside={onFocusOutside}\n className={cn(contentClass, 'origin-(--radix-context-menu-content-transform-origin)', 'max-h-(--radix-context-menu-content-available-height)', className)}\n >\n {children}\n </ContextPrimitive.Content>\n </ContextPrimitive.Portal>\n </ContextPrimitive.Root>\n )\n}\n\nexport interface ContextMenuItemProps\n extends Omit<React.ComponentProps<typeof ContextPrimitive.Item>, 'children'>,\n Pick<MenuItemContentProps, 'icon' | 'shortcut' | 'description'> {\n label: string\n /** Deletes or removes: action/destructive/fg, and best placed last. */\n destructive?: boolean\n}\n\nexport function ContextMenuItem({ label, icon, shortcut, description, destructive, className, ...props }: ContextMenuItemProps) {\n return (\n <ContextPrimitive.Item\n data-slot=\"context-menu-item\"\n textValue={label}\n className={cn(menuItemClass, destructive && '[&_*]:text-action-destructive-fg', className)}\n {...props}\n >\n <MenuItemContent label={label} icon={icon} shortcut={shortcut} description={description} layout=\"inline\" />\n </ContextPrimitive.Item>\n )\n}\n\nexport interface ContextMenuSubProps extends Pick<MenuItemContentProps, 'icon'> {\n label: string\n /** The submenu's items. */\n children: React.ReactNode\n disabled?: boolean\n}\n\n/** A row that opens a submenu beside it (hover, →, or Enter). */\nexport function ContextMenuSub({ label, icon, children, disabled }: ContextMenuSubProps) {\n return (\n <ContextPrimitive.Sub>\n <ContextPrimitive.SubTrigger\n data-slot=\"context-menu-sub\"\n disabled={disabled}\n textValue={label}\n className={cn(menuItemClass, 'data-[state=open]:bg-bg-selected')}\n >\n <MenuItemContent label={label} icon={icon} layout=\"inline\" />\n <NavArrowRight aria-hidden className=\"size-4 text-text-muted [stroke-width:1.875]\" />\n </ContextPrimitive.SubTrigger>\n <ContextPrimitive.Portal>\n <ContextPrimitive.SubContent\n sideOffset={4}\n alignOffset={-5}\n collisionPadding={8}\n className={cn(contentClass, 'w-[220px] origin-(--radix-context-menu-content-transform-origin)')}\n >\n {children}\n </ContextPrimitive.SubContent>\n </ContextPrimitive.Portal>\n </ContextPrimitive.Sub>\n )\n}\n\n/** A 1px bg/muted rule between groups of rows. */\nexport function ContextMenuSeparator({ className }: { className?: string }) {\n return <ContextPrimitive.Separator className={cn('-mx-1 my-1 h-px bg-bg-muted', className)} />\n}\n"]}
@@ -0,0 +1,47 @@
1
+ import { Thinking } from './chunk-ESC5JCVQ.js';
2
+ import { MessageActions } from './chunk-AN2RNJLR.js';
3
+ import { cn } from './chunk-H63FYCMY.js';
4
+ import 'react';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+
7
+ function Message({
8
+ role = "assistant",
9
+ thinking,
10
+ thinkingLabel = "Thought for a moment",
11
+ source,
12
+ actions = true,
13
+ timestamp,
14
+ onFeedback,
15
+ onCopy,
16
+ onShare,
17
+ className,
18
+ children,
19
+ ...props
20
+ }) {
21
+ if (role === "user") {
22
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "message", "data-role": "user", className: cn("flex flex-col items-end gap-2", className), ...props, children: [
23
+ source && /* @__PURE__ */ jsx(SourceCard, { source }),
24
+ /* @__PURE__ */ jsx("div", { className: "max-w-full rounded-xl rounded-br-xs bg-action-inverse-bg px-3 py-2", children: /* @__PURE__ */ jsx("div", { className: "max-w-64 text-body break-words text-text-on-inverse", children }) })
25
+ ] });
26
+ }
27
+ return /* @__PURE__ */ jsxs("div", { "data-slot": "message", "data-role": "assistant", className: cn("flex flex-col items-start gap-3", className), ...props, children: [
28
+ thinking && thinking.length > 0 && /* @__PURE__ */ jsx(Thinking, { state: "collapsed", label: thinkingLabel, steps: thinking }),
29
+ /* @__PURE__ */ jsx("div", { className: "w-full text-body break-words text-text-default", children }),
30
+ actions && /* @__PURE__ */ jsx(MessageActions, { timestamp, onFeedback, onCopy, onShare })
31
+ ] });
32
+ }
33
+ function SourceCard({ source }) {
34
+ const body = /* @__PURE__ */ jsxs(Fragment, { children: [
35
+ source.icon && /* @__PURE__ */ jsx("span", { className: "flex size-4 shrink-0 items-center justify-center [&>*]:size-4", children: source.icon }),
36
+ /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col overflow-clip whitespace-nowrap", children: [
37
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm leading-[18px] font-medium text-text-default", children: source.title }),
38
+ source.url != null && /* @__PURE__ */ jsx("span", { className: "truncate text-xs leading-3 tracking-normal text-text-muted", children: source.url })
39
+ ] })
40
+ ] });
41
+ const cls = "flex max-w-full items-center gap-2.5 overflow-clip rounded-lg border border-border-subtle bg-bg-canvas py-2 pr-3 pl-2.5";
42
+ return source.href ? /* @__PURE__ */ jsx("a", { href: source.href, className: cls, children: body }) : /* @__PURE__ */ jsx("div", { className: cls, children: body });
43
+ }
44
+
45
+ export { Message };
46
+ //# sourceMappingURL=chunk-PVOLDO4G.js.map
47
+ //# sourceMappingURL=chunk-PVOLDO4G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/message.tsx"],"names":[],"mappings":";;;;;;AA6CO,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA,GAAO,WAAA;AAAA,EACP,QAAA;AAAA,EACA,aAAA,GAAgB,sBAAA;AAAA,EAChB,MAAA;AAAA,EACA,OAAA,GAAU,IAAA;AAAA,EACV,SAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAiB;AACf,EAAA,IAAI,SAAS,MAAA,EAAQ;AACnB,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,SAAA,EAAU,WAAA,EAAU,MAAA,EAAO,SAAA,EAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA,EAAI,GAAG,KAAA,EACtG,QAAA,EAAA;AAAA,MAAA,MAAA,oBAAU,GAAA,CAAC,cAAW,MAAA,EAAgB,CAAA;AAAA,sBACvC,GAAA,CAAC,SAAI,SAAA,EAAU,oEAAA,EACb,8BAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qDAAA,EAAuD,QAAA,EAAS,CAAA,EACjF;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,WAAA,EAAU,SAAA,EAAU,WAAA,EAAU,WAAA,EAAY,SAAA,EAAW,EAAA,CAAG,iCAAA,EAAmC,SAAS,CAAA,EAAI,GAAG,KAAA,EAC7G,QAAA,EAAA;AAAA,IAAA,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,oBAAK,GAAA,CAAC,QAAA,EAAA,EAAS,OAAM,WAAA,EAAY,KAAA,EAAO,aAAA,EAAe,KAAA,EAAO,QAAA,EAAU,CAAA;AAAA,oBACvG,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDAAA,EAAkD,QAAA,EAAS,CAAA;AAAA,IACzE,2BAAW,GAAA,CAAC,cAAA,EAAA,EAAe,SAAA,EAAsB,UAAA,EAAwB,QAAgB,OAAA,EAAkB;AAAA,GAAA,EAC9G,CAAA;AAEJ;AAEA,SAAS,UAAA,CAAW,EAAE,MAAA,EAAO,EAA8B;AACzD,EAAA,MAAM,uBACJ,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,MAAA,CAAO,wBAAQ,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+DAAA,EAAiE,iBAAO,IAAA,EAAK,CAAA;AAAA,oBAC7G,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uDAAA,EACd,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,+DAAA,EAAiE,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA;AAAA,MAC7F,MAAA,CAAO,OAAO,IAAA,oBACb,GAAA,CAAC,UAAK,SAAA,EAAU,4DAAA,EAA8D,iBAAO,GAAA,EAAI;AAAA,KAAA,EAE7F;AAAA,GAAA,EACF,CAAA;AAEF,EAAA,MAAM,GAAA,GAAM,yHAAA;AACZ,EAAA,OAAO,MAAA,CAAO,IAAA,mBACZ,GAAA,CAAC,GAAA,EAAA,EAAE,MAAM,MAAA,CAAO,IAAA,EAAM,SAAA,EAAW,GAAA,EAC9B,gBACH,CAAA,mBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,KAAM,QAAA,EAAA,IAAA,EAAK,CAAA;AAE/B","file":"chunk-PVOLDO4G.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\nimport { MessageActions, type MessageFeedback } from './message-actions'\nimport { Thinking, type ThinkingStep } from './thinking'\n\n/**\n * Message, 1:1 with the uiKit Message docs view (3890:70165), composed from `_chat/userMessage`\n * (901:20155), `_chat/source` and `_chat/answerActions` (901:20164, see MessageActions).\n *\n * user: a right-aligned action/inverse bubble (12px corners, 4px bottom-right), 12 × 8\n * padding, text/on-inverse 13/19.5, wrapping at 256px of text. A source card sits 8px above\n * it: bg/canvas, border/subtle, radius 10, 16px logo, title medium 13/18, url 12/12 muted.\n *\n * assistant: no bubble, so long answers read like a document — text/default 13/19.5, with\n * the collapsed Thinking above and the actions below, 12px apart.\n */\nexport interface MessageSource {\n /** The page or message title, \"Q3 pipeline review\". */\n title: React.ReactNode\n /** Shown under the title, \"docs.sature.app/q3-review\". */\n url?: React.ReactNode\n /** A 16px logo or favicon. */\n icon?: React.ReactNode\n /** Makes the card a link. */\n href?: string\n}\n\nexport interface MessageProps extends React.ComponentProps<'div'> {\n role?: 'user' | 'assistant'\n /** The steps the agent ran; shows a collapsed Thinking above an assistant answer. */\n thinking?: ThinkingStep[]\n /** The summary on that Thinking header. */\n thinkingLabel?: React.ReactNode\n /** A page or message the user brought in, shown as a card above their bubble. */\n source?: MessageSource\n /** Feedback, copy and share under an assistant answer. Off while it streams. */\n actions?: boolean\n timestamp?: string\n onFeedback?: (value: MessageFeedback) => void\n onCopy?: () => void\n onShare?: () => void\n}\n\nexport function Message({\n role = 'assistant',\n thinking,\n thinkingLabel = 'Thought for a moment',\n source,\n actions = true,\n timestamp,\n onFeedback,\n onCopy,\n onShare,\n className,\n children,\n ...props\n}: MessageProps) {\n if (role === 'user') {\n return (\n <div data-slot=\"message\" data-role=\"user\" className={cn('flex flex-col items-end gap-2', className)} {...props}>\n {source && <SourceCard source={source} />}\n <div className=\"max-w-full rounded-xl rounded-br-xs bg-action-inverse-bg px-3 py-2\">\n <div className=\"max-w-64 text-body break-words text-text-on-inverse\">{children}</div>\n </div>\n </div>\n )\n }\n\n return (\n <div data-slot=\"message\" data-role=\"assistant\" className={cn('flex flex-col items-start gap-3', className)} {...props}>\n {thinking && thinking.length > 0 && <Thinking state=\"collapsed\" label={thinkingLabel} steps={thinking} />}\n <div className=\"w-full text-body break-words text-text-default\">{children}</div>\n {actions && <MessageActions timestamp={timestamp} onFeedback={onFeedback} onCopy={onCopy} onShare={onShare} />}\n </div>\n )\n}\n\nfunction SourceCard({ source }: { source: MessageSource }) {\n const body = (\n <>\n {source.icon && <span className=\"flex size-4 shrink-0 items-center justify-center [&>*]:size-4\">{source.icon}</span>}\n <span className=\"flex min-w-0 flex-col overflow-clip whitespace-nowrap\">\n <span className=\"truncate text-sm leading-[18px] font-medium text-text-default\">{source.title}</span>\n {source.url != null && (\n <span className=\"truncate text-xs leading-3 tracking-normal text-text-muted\">{source.url}</span>\n )}\n </span>\n </>\n )\n const cls = 'flex max-w-full items-center gap-2.5 overflow-clip rounded-lg border border-border-subtle bg-bg-canvas py-2 pr-3 pl-2.5'\n return source.href ? (\n <a href={source.href} className={cls}>\n {body}\n </a>\n ) : (\n <div className={cls}>{body}</div>\n )\n}\n"]}
@@ -0,0 +1,215 @@
1
+ import { useSlidingIndicator, SLIDE_MS } from './chunk-J3NSDRVH.js';
2
+ import { Button } from './chunk-HNQUX43Z.js';
3
+ import { cn } from './chunk-H63FYCMY.js';
4
+ import * as React from 'react';
5
+ import { NavArrowLeft, NavArrowRight } from 'iconoir-react';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+
8
+ function paginationRange(page, pageCount, siblings = 1) {
9
+ const slots = siblings * 2 + 5;
10
+ const span = (a, b) => Array.from({ length: b - a + 1 }, (_, i) => a + i);
11
+ if (pageCount <= slots) return span(1, pageCount);
12
+ const left = Math.max(page - siblings, 1);
13
+ const right = Math.min(page + siblings, pageCount);
14
+ const showLeftGap = left > 3;
15
+ const showRightGap = right < pageCount - 2;
16
+ if (!showLeftGap) return [...span(1, slots - 2), "gap", pageCount];
17
+ if (!showRightGap) return [1, "gap", ...span(pageCount - (slots - 3), pageCount)];
18
+ return [1, "gap", ...span(left, right), "gap", pageCount];
19
+ }
20
+ var pageClass = cn(
21
+ "relative z-10 grid h-control-height min-w-control-height place-items-center overflow-hidden rounded-lg px-1.5 text-sm text-text-muted tabular-nums",
22
+ "transition-colors duration-(--duration-fast) ease-(--ease-out) outline-none focus-visible:shadow-border-focus",
23
+ "hover:bg-bg-hover hover:text-text-default",
24
+ "aria-[current=page]:font-medium aria-[current=page]:text-text-default aria-[current=page]:hover:bg-transparent"
25
+ );
26
+ var STRIP_MS = SLIDE_MS;
27
+ var STEP_PX = 32;
28
+ function PageText({ text, dir, motion }) {
29
+ const [state, setState] = React.useState({ text, old: null, dir, n: 0 });
30
+ if (state.text !== text) setState({ text, old: motion === "none" ? null : state.text, dir, n: state.n + 1 });
31
+ const animate = motion !== "none" && state.n > 0;
32
+ return (
33
+ // Clipped to the wider number, so in the compact "Page 5 of 12" a moving number never runs
34
+ // into the words around it.
35
+ /* @__PURE__ */ jsxs("span", { className: "inline-grid overflow-hidden align-bottom", children: [
36
+ state.old != null && /* @__PURE__ */ jsx(
37
+ "span",
38
+ {
39
+ "aria-hidden": true,
40
+ "data-motion": motion,
41
+ "data-phase": "out",
42
+ "data-dir": state.dir,
43
+ className: "satin-page-text col-start-1 row-start-1 text-center",
44
+ onAnimationEnd: () => setState((s) => ({ ...s, old: null })),
45
+ children: state.old
46
+ },
47
+ `o${state.n}`
48
+ ),
49
+ /* @__PURE__ */ jsx(
50
+ "span",
51
+ {
52
+ "data-motion": animate ? motion : void 0,
53
+ "data-phase": animate ? "in" : void 0,
54
+ "data-dir": state.dir,
55
+ className: "satin-page-text col-start-1 row-start-1 text-center",
56
+ children: state.text
57
+ },
58
+ `n${state.n}`
59
+ )
60
+ ] })
61
+ );
62
+ }
63
+ function Pagination({
64
+ pageCount,
65
+ page: pageProp,
66
+ defaultPage = 1,
67
+ onPageChange,
68
+ getHref,
69
+ layout = "full",
70
+ siblings = 1,
71
+ previousLabel = "Previous",
72
+ nextLabel = "Next",
73
+ motion = "scroll",
74
+ className,
75
+ "aria-label": ariaLabel = "Pagination",
76
+ ...props
77
+ }) {
78
+ const [uncontrolled, setUncontrolled] = React.useState(defaultPage);
79
+ const page = Math.min(Math.max(pageProp ?? uncontrolled, 1), Math.max(pageCount, 1));
80
+ const go = (p) => {
81
+ if (p < 1 || p > pageCount || p === page) return;
82
+ if (motion === "scroll") snapshot();
83
+ if (pageProp == null) setUncontrolled(p);
84
+ onPageChange?.(p);
85
+ };
86
+ const prevPage = React.useRef(page);
87
+ const dir = page >= prevPage.current ? "next" : "prev";
88
+ React.useEffect(() => {
89
+ prevPage.current = page;
90
+ }, [page]);
91
+ const listRef = React.useRef(null);
92
+ const pill = useSlidingIndicator(listRef, '[aria-current="page"]', `${page}|${pageCount}|${layout}|${siblings}`, {
93
+ animate: motion !== "none"
94
+ });
95
+ const textMotion = motion === "slide" ? "fade" : "none";
96
+ const ghostRef = React.useRef(null);
97
+ const before = React.useRef(null);
98
+ function snapshot() {
99
+ const list = listRef.current;
100
+ if (!list) return;
101
+ const base = list.getBoundingClientRect().left;
102
+ const map = /* @__PURE__ */ new Map();
103
+ list.querySelectorAll("[data-cell]").forEach((li) => {
104
+ const face = li.firstElementChild;
105
+ if (face) map.set(li.dataset.cell, { x: li.getBoundingClientRect().left - base, node: face.cloneNode(true) });
106
+ });
107
+ before.current = map;
108
+ }
109
+ React.useLayoutEffect(() => {
110
+ const prev = before.current;
111
+ before.current = null;
112
+ const list = listRef.current;
113
+ if (!prev || !list || motion !== "scroll" || layout !== "full") return;
114
+ if (typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) return;
115
+ const sign = dir === "next" ? 1 : -1;
116
+ const timing = { duration: STRIP_MS, easing: "cubic-bezier(0.23, 1, 0.32, 1)" };
117
+ const seen = /* @__PURE__ */ new Set();
118
+ list.querySelectorAll("[data-cell]").forEach((li) => {
119
+ const key = li.dataset.cell;
120
+ seen.add(key);
121
+ li.getAnimations().forEach((a) => a.cancel());
122
+ const from = prev.get(key);
123
+ if (from) {
124
+ const dx = from.x - li.offsetLeft;
125
+ if (Math.abs(dx) > 0.5) li.animate([{ transform: `translateX(${dx}px)` }, { transform: "none" }], timing);
126
+ } else {
127
+ li.animate([{ transform: `translateX(${sign * STEP_PX}px)`, opacity: 0 }, { transform: "none", opacity: 1 }], timing);
128
+ }
129
+ });
130
+ const layer = ghostRef.current;
131
+ if (!layer) return;
132
+ for (const [key, { x, node }] of prev) {
133
+ if (seen.has(key)) continue;
134
+ node.removeAttribute("aria-current");
135
+ node.style.cssText = `position:absolute;top:0;left:${x}px;margin:0`;
136
+ layer.appendChild(node);
137
+ node.animate([{ transform: "none", opacity: 1 }, { transform: `translateX(${-sign * STEP_PX}px)`, opacity: 0 }], {
138
+ ...timing,
139
+ duration: STRIP_MS * 0.6
140
+ }).finished.then(
141
+ () => node.remove(),
142
+ () => node.remove()
143
+ );
144
+ }
145
+ }, [page, motion, layout, dir]);
146
+ const target = (p, className2, children, extra) => getHref ? /* @__PURE__ */ jsx("a", { href: getHref(p), className: className2, onClick: () => go(p), ...extra, children }) : /* @__PURE__ */ jsx("button", { type: "button", className: cn("cursor-pointer", className2), onClick: () => go(p), ...extra, children });
147
+ const step = (dir2) => {
148
+ const to = page + dir2;
149
+ const disabled = to < 1 || to > pageCount;
150
+ const label = dir2 < 0 ? previousLabel : nextLabel;
151
+ const icon = dir2 < 0 ? /* @__PURE__ */ jsx(NavArrowLeft, { "aria-hidden": true }) : /* @__PURE__ */ jsx(NavArrowRight, { "aria-hidden": true });
152
+ const compact = layout === "compact";
153
+ const content = compact ? icon : dir2 < 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
154
+ icon,
155
+ label
156
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
157
+ label,
158
+ icon
159
+ ] });
160
+ return getHref && !disabled ? /* @__PURE__ */ jsx(Button, { asChild: true, variant: "tertiary", iconOnly: compact, "aria-label": compact ? label : void 0, children: /* @__PURE__ */ jsx("a", { href: getHref(to), rel: dir2 < 0 ? "prev" : "next", onClick: () => go(to), children: content }) }) : /* @__PURE__ */ jsx(Button, { variant: "tertiary", iconOnly: compact, "aria-label": compact ? label : void 0, disabled, onClick: () => go(to), children: content });
161
+ };
162
+ return /* @__PURE__ */ jsx("nav", { "data-slot": "pagination", "data-layout": layout, "aria-label": ariaLabel, className: cn("flex items-center", className), ...props, children: layout === "compact" ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
163
+ step(-1),
164
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-text-muted tabular-nums", "aria-live": "polite", children: [
165
+ "Page ",
166
+ /* @__PURE__ */ jsx(PageText, { text: String(page), dir, motion: motion === "scroll" ? "scroll" : textMotion }),
167
+ " of ",
168
+ pageCount
169
+ ] }),
170
+ step(1)
171
+ ] }) : /* @__PURE__ */ jsxs("ul", { ref: listRef, className: "relative flex items-center gap-1", children: [
172
+ /* @__PURE__ */ jsx(
173
+ "li",
174
+ {
175
+ ref: pill.ref,
176
+ "aria-hidden": true,
177
+ role: "presentation",
178
+ className: "pointer-events-none absolute top-0 left-0 h-control-height rounded-lg bg-bg-selected opacity-0"
179
+ }
180
+ ),
181
+ /* @__PURE__ */ jsx("li", { ref: ghostRef, "aria-hidden": true, role: "presentation", className: "pointer-events-none absolute inset-0 overflow-visible" }),
182
+ /* @__PURE__ */ jsx("li", { children: step(-1) }),
183
+ motion === "scroll" ? (
184
+ // The strip: pages keyed by their number, the two ellipses by their side.
185
+ paginationRange(page, pageCount, siblings).map((p, i, all) => {
186
+ const key = p === "gap" ? i < all.length / 2 ? "gap-start" : "gap-end" : `p${p}`;
187
+ return /* @__PURE__ */ jsx("li", { "data-cell": key, className: "relative", children: p === "gap" ? /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: cn(pageClass, "pointer-events-none"), children: "\u2026" }) : target(p, pageClass, p, {
188
+ "aria-current": p === page ? "page" : void 0,
189
+ "aria-label": `Page ${p}`
190
+ }) }, key);
191
+ })
192
+ ) : (
193
+ // Slots keep their places (keyed by position), so paging changes numbers, not elements.
194
+ paginationRange(page, pageCount, siblings).map((p, i) => {
195
+ const gap = p === "gap";
196
+ const text = /* @__PURE__ */ jsx(PageText, { text: gap ? "\u2026" : String(p), dir, motion: textMotion });
197
+ return /* @__PURE__ */ jsx("li", { children: gap ? React.createElement(getHref ? "a" : "button", {
198
+ className: cn(pageClass, "pointer-events-none"),
199
+ "aria-hidden": true,
200
+ tabIndex: -1,
201
+ ...getHref ? {} : { type: "button", disabled: true },
202
+ children: text
203
+ }) : target(p, pageClass, text, {
204
+ "aria-current": p === page ? "page" : void 0,
205
+ "aria-label": `Page ${p}`
206
+ }) }, i);
207
+ })
208
+ ),
209
+ /* @__PURE__ */ jsx("li", { children: step(1) })
210
+ ] }) });
211
+ }
212
+
213
+ export { Pagination, paginationRange };
214
+ //# sourceMappingURL=chunk-QS4N4MNP.js.map
215
+ //# sourceMappingURL=chunk-QS4N4MNP.js.map