@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 @@
1
+ {"version":3,"sources":["../src/components/pagination.tsx"],"names":["className","dir"],"mappings":"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","file":"chunk-QS4N4MNP.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { NavArrowLeft, NavArrowRight } from 'iconoir-react'\nimport { cn } from '../lib/utils'\nimport { Button } from './button'\nimport { SLIDE_MS, useSlidingIndicator } from './sliding-indicator'\n\n/**\n * Pagination, 1:1 with the uiKit `Pagination` set (4025:3807), two layouts:\n * - full: Previous and Next (tertiary md buttons with their arrows) around the page numbers,\n * 4px apart: the first and last page, the current one with `siblings` on each side, and an\n * ellipsis where pages are skipped. Pages are 28px squares, radius 10, 13px text/muted;\n * hover bg/hover and text/default; the current page bg/selected, text/default, medium.\n * - compact: icon-only Previous and Next around \"Page 5 of 12\" (13px, text/muted), 8px apart.\n *\n * Moving between pages (`motion`), the pages keep their places and only their numbers change:\n * - scroll (default): the pages are a strip. Each page slides from where it was to its new place,\n * a page coming into view slides out from under the ellipsis on the side the reader pages\n * towards, one leaving slides under the other and fades, and the pill under the current\n * page moves on the same 300 ms curve (sliding-indicator.tsx, shared with Tabs and the\n * Segmented control). Nothing is clipped and no number changes in place.\n * - slide: the current page's bg/selected pill slides under the numbers to the new\n * page, like the Segmented control's, 200 ms on ease-out; a number that changes in place\n * fades out before the new one fades in.\n * - none: no motion; the current page simply takes the pill.\n *\n * Previous and Next are disabled at the ends. With `getHref`, every page is a link (for pages\n * the server renders); without it they are buttons that call `onPageChange`.\n *\n * A `nav` named \"Pagination\"; the current page has aria-current=\"page\".\n */\nexport interface PaginationProps extends Omit<React.ComponentProps<'nav'>, 'children'> {\n /** How many pages there are. */\n pageCount: number\n /** The current page, from 1. */\n page?: number\n defaultPage?: number\n onPageChange?: (page: number) => void\n /** Each page's URL: pages become links. */\n getHref?: (page: number) => string\n layout?: 'full' | 'compact'\n /** Pages shown on each side of the current one (full layout). */\n siblings?: number\n previousLabel?: string\n nextLabel?: string\n /** How the row moves when the page changes. */\n motion?: 'slide' | 'scroll' | 'none'\n}\n\n/** The pages to show, with 'gap' where an ellipsis stands for skipped ones. Always 2 × siblings + 5 slots when there are enough pages, so the bar keeps its width. */\nexport function paginationRange(page: number, pageCount: number, siblings = 1): (number | 'gap')[] {\n const slots = siblings * 2 + 5\n const span = (a: number, b: number) => Array.from({ length: b - a + 1 }, (_, i) => a + i)\n if (pageCount <= slots) return span(1, pageCount)\n const left = Math.max(page - siblings, 1)\n const right = Math.min(page + siblings, pageCount)\n const showLeftGap = left > 3\n const showRightGap = right < pageCount - 2\n if (!showLeftGap) return [...span(1, slots - 2), 'gap', pageCount]\n if (!showRightGap) return [1, 'gap', ...span(pageCount - (slots - 3), pageCount)]\n return [1, 'gap', ...span(left, right), 'gap', pageCount]\n}\n\nconst pageClass = cn(\n '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',\n 'transition-colors duration-(--duration-fast) ease-(--ease-out) outline-none focus-visible:shadow-border-focus',\n 'hover:bg-bg-hover hover:text-text-default',\n 'aria-[current=page]:font-medium aria-[current=page]:text-text-default aria-[current=page]:hover:bg-transparent',\n)\n\ntype Dir = 'next' | 'prev'\n\n/** The strip's move, ms, and one page's step along it (a 28px page and the 4px gap), px. */\nconst STRIP_MS = SLIDE_MS\nconst STEP_PX = 32\n\n/**\n * A slot's number. When it changes, the old one stays on top of the new one for the length of\n * its exit, both in one grid cell, so the slot keeps the wider of the two and nothing jumps.\n */\nfunction PageText({ text, dir, motion }: { text: string; dir: Dir; motion: 'fade' | 'scroll' | 'none' }) {\n const [state, setState] = React.useState({ text, old: null as string | null, dir, n: 0 })\n if (state.text !== text) setState({ text, old: motion === 'none' ? null : state.text, dir, n: state.n + 1 })\n const animate = motion !== 'none' && state.n > 0\n return (\n // Clipped to the wider number, so in the compact \"Page 5 of 12\" a moving number never runs\n // into the words around it.\n <span className=\"inline-grid overflow-hidden align-bottom\">\n {state.old != null && (\n <span\n key={`o${state.n}`}\n aria-hidden\n data-motion={motion}\n data-phase=\"out\"\n data-dir={state.dir}\n className=\"satin-page-text col-start-1 row-start-1 text-center\"\n onAnimationEnd={() => setState((s) => ({ ...s, old: null }))}\n >\n {state.old}\n </span>\n )}\n <span\n key={`n${state.n}`}\n data-motion={animate ? motion : undefined}\n data-phase={animate ? 'in' : undefined}\n data-dir={state.dir}\n className=\"satin-page-text col-start-1 row-start-1 text-center\"\n >\n {state.text}\n </span>\n </span>\n )\n}\n\nexport function Pagination({\n pageCount,\n page: pageProp,\n defaultPage = 1,\n onPageChange,\n getHref,\n layout = 'full',\n siblings = 1,\n previousLabel = 'Previous',\n nextLabel = 'Next',\n motion = 'scroll',\n className,\n 'aria-label': ariaLabel = 'Pagination',\n ...props\n}: PaginationProps) {\n const [uncontrolled, setUncontrolled] = React.useState(defaultPage)\n const page = Math.min(Math.max(pageProp ?? uncontrolled, 1), Math.max(pageCount, 1))\n const go = (p: number) => {\n if (p < 1 || p > pageCount || p === page) return\n // Where every page is on screen right now (mid-move too), for the strip to move from.\n if (motion === 'scroll') snapshot()\n if (pageProp == null) setUncontrolled(p)\n onPageChange?.(p)\n }\n\n // Which way the reader is paging, for the scroll motion.\n const prevPage = React.useRef(page)\n const dir: Dir = page >= prevPage.current ? 'next' : 'prev'\n React.useEffect(() => {\n prevPage.current = page\n }, [page])\n\n // The pill under the current page slides to the new one (sliding-indicator.tsx); with\n // motion off it just moves.\n const listRef = React.useRef<HTMLUListElement>(null)\n const pill = useSlidingIndicator<HTMLLIElement>(listRef, '[aria-current=\"page\"]', `${page}|${pageCount}|${layout}|${siblings}`, {\n animate: motion !== 'none',\n })\n const textMotion = motion === 'slide' ? 'fade' : 'none'\n\n /* ---- scroll: the pages are a strip that moves (FLIP) ---- */\n // Each page is its own element, keyed by its number. When the page changes, every page that\n // stays slides from where it was to where it now is; a page coming into view slides in from\n // the side the reader is paging towards, out from under the ellipsis; one leaving slides\n // the other way and fades as it goes under the other ellipsis. The pill under the current\n // page moves on the same curve, so a page sliding into it lands with it.\n const ghostRef = React.useRef<HTMLLIElement>(null)\n const before = React.useRef<Map<string, { x: number; node: HTMLElement }> | null>(null)\n function snapshot() {\n const list = listRef.current\n if (!list) return\n const base = list.getBoundingClientRect().left\n const map = new Map<string, { x: number; node: HTMLElement }>()\n list.querySelectorAll<HTMLElement>('[data-cell]').forEach((li) => {\n const face = li.firstElementChild as HTMLElement | null\n if (face) map.set(li.dataset.cell!, { x: li.getBoundingClientRect().left - base, node: face.cloneNode(true) as HTMLElement })\n })\n before.current = map\n }\n React.useLayoutEffect(() => {\n const prev = before.current\n before.current = null\n const list = listRef.current\n if (!prev || !list || motion !== 'scroll' || layout !== 'full') return\n if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) return\n const sign = dir === 'next' ? 1 : -1\n const timing: KeyframeAnimationOptions = { duration: STRIP_MS, easing: 'cubic-bezier(0.23, 1, 0.32, 1)' }\n const seen = new Set<string>()\n list.querySelectorAll<HTMLElement>('[data-cell]').forEach((li) => {\n const key = li.dataset.cell!\n seen.add(key)\n li.getAnimations().forEach((a) => a.cancel())\n const from = prev.get(key)\n if (from) {\n const dx = from.x - li.offsetLeft\n if (Math.abs(dx) > 0.5) li.animate([{ transform: `translateX(${dx}px)` }, { transform: 'none' }], timing)\n } else {\n li.animate([{ transform: `translateX(${sign * STEP_PX}px)`, opacity: 0 }, { transform: 'none', opacity: 1 }], timing)\n }\n })\n // Pages that left: a copy of each, where it was, sliding off and fading.\n const layer = ghostRef.current\n if (!layer) return\n for (const [key, { x, node }] of prev) {\n if (seen.has(key)) continue\n node.removeAttribute('aria-current')\n node.style.cssText = `position:absolute;top:0;left:${x}px;margin:0`\n layer.appendChild(node)\n node\n .animate([{ transform: 'none', opacity: 1 }, { transform: `translateX(${-sign * STEP_PX}px)`, opacity: 0 }], {\n ...timing,\n duration: STRIP_MS * 0.6,\n })\n .finished.then(\n () => node.remove(),\n () => node.remove(),\n )\n }\n }, [page, motion, layout, dir])\n\n // A page as a link or a button; the same skin either way.\n const target = (p: number, className: string, children: React.ReactNode, extra?: React.HTMLAttributes<HTMLElement>) =>\n getHref ? (\n <a href={getHref(p)} className={className} onClick={() => go(p)} {...extra}>\n {children}\n </a>\n ) : (\n <button type=\"button\" className={cn('cursor-pointer', className)} onClick={() => go(p)} {...extra}>\n {children}\n </button>\n )\n\n const step = (dir: -1 | 1) => {\n const to = page + dir\n const disabled = to < 1 || to > pageCount\n const label = dir < 0 ? previousLabel : nextLabel\n const icon = dir < 0 ? <NavArrowLeft aria-hidden /> : <NavArrowRight aria-hidden />\n const compact = layout === 'compact'\n const content = compact ? icon : dir < 0 ? <>{icon}{label}</> : <>{label}{icon}</>\n // A link can't be disabled: at the ends it is a disabled button instead.\n return getHref && !disabled ? (\n <Button asChild variant=\"tertiary\" iconOnly={compact} aria-label={compact ? label : undefined}>\n <a href={getHref(to)} rel={dir < 0 ? 'prev' : 'next'} onClick={() => go(to)}>\n {content}\n </a>\n </Button>\n ) : (\n <Button variant=\"tertiary\" iconOnly={compact} aria-label={compact ? label : undefined} disabled={disabled} onClick={() => go(to)}>\n {content}\n </Button>\n )\n }\n\n return (\n <nav data-slot=\"pagination\" data-layout={layout} aria-label={ariaLabel} className={cn('flex items-center', className)} {...props}>\n {layout === 'compact' ? (\n <div className=\"flex items-center gap-2\">\n {step(-1)}\n <span className=\"text-sm text-text-muted tabular-nums\" aria-live=\"polite\">\n Page <PageText text={String(page)} dir={dir} motion={motion === 'scroll' ? 'scroll' : textMotion} /> of {pageCount}\n </span>\n {step(1)}\n </div>\n ) : (\n <ul ref={listRef} className=\"relative flex items-center gap-1\">\n <li\n ref={pill.ref}\n aria-hidden\n role=\"presentation\"\n className=\"pointer-events-none absolute top-0 left-0 h-control-height rounded-lg bg-bg-selected opacity-0\"\n />\n {/* Copies of the pages that just left, playing out; under the live pages. */}\n <li ref={ghostRef} aria-hidden role=\"presentation\" className=\"pointer-events-none absolute inset-0 overflow-visible\" />\n <li>{step(-1)}</li>\n {motion === 'scroll'\n ? // The strip: pages keyed by their number, the two ellipses by their side.\n paginationRange(page, pageCount, siblings).map((p, i, all) => {\n const key = p === 'gap' ? (i < all.length / 2 ? 'gap-start' : 'gap-end') : `p${p}`\n return (\n <li key={key} data-cell={key} className=\"relative\">\n {p === 'gap' ? (\n <span aria-hidden className={cn(pageClass, 'pointer-events-none')}>\n …\n </span>\n ) : (\n target(p, pageClass, p, {\n 'aria-current': p === page ? 'page' : undefined,\n 'aria-label': `Page ${p}`,\n } as React.HTMLAttributes<HTMLElement>)\n )}\n </li>\n )\n })\n : // Slots keep their places (keyed by position), so paging changes numbers, not elements.\n paginationRange(page, pageCount, siblings).map((p, i) => {\n const gap = p === 'gap'\n // A slot is the same element whether it holds a page or the ellipsis, so a page\n // coming out from behind \"…\" (or going behind it) plays the same motion as a number.\n const text = <PageText text={gap ? '…' : String(p)} dir={dir} motion={textMotion} />\n return (\n <li key={i}>\n {gap\n ? React.createElement(getHref ? 'a' : 'button', {\n className: cn(pageClass, 'pointer-events-none'),\n 'aria-hidden': true,\n tabIndex: -1,\n ...(getHref ? {} : { type: 'button', disabled: true }),\n children: text,\n })\n : target(p, pageClass, text, {\n 'aria-current': p === page ? 'page' : undefined,\n 'aria-label': `Page ${p}`,\n } as React.HTMLAttributes<HTMLElement>)}\n </li>\n )\n })}\n <li>{step(1)}</li>\n </ul>\n )}\n </nav>\n )\n}\n"]}
@@ -0,0 +1,98 @@
1
+ import { useFormField } from './chunk-UBNHSZSE.js';
2
+ import { cn } from './chunk-H63FYCMY.js';
3
+ import * as React from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function Textarea({
7
+ label,
8
+ optional,
9
+ hint,
10
+ error,
11
+ maxLength,
12
+ className,
13
+ wrapperClassName,
14
+ id,
15
+ disabled,
16
+ required,
17
+ value,
18
+ defaultValue,
19
+ onChange,
20
+ "aria-describedby": ariaDescribedBy,
21
+ "data-force": force,
22
+ ...props
23
+ }) {
24
+ const field = useFormField();
25
+ const autoId = React.useId();
26
+ const textareaId = id ?? field?.id ?? autoId;
27
+ const isDisabled = disabled ?? field?.disabled ?? false;
28
+ const hasMessage = typeof error === "string" || React.isValidElement(error);
29
+ const invalid = Boolean(error) || (field?.invalid ?? false);
30
+ const message = hasMessage ? error : hint;
31
+ const [uncontrolled, setUncontrolled] = React.useState(defaultValue != null ? String(defaultValue) : "");
32
+ const text = value != null ? String(value) : uncontrolled;
33
+ const messageId = message ? `${textareaId}-hint` : void 0;
34
+ const counterId = maxLength != null ? `${textareaId}-counter` : void 0;
35
+ const describedBy = [ariaDescribedBy, field?.describedBy, messageId, counterId].filter(Boolean).join(" ") || void 0;
36
+ return /* @__PURE__ */ jsxs(
37
+ "div",
38
+ {
39
+ "data-slot": "textarea-wrapper",
40
+ "data-disabled": isDisabled || void 0,
41
+ className: cn("satin-textarea-root grid w-full gap-2", wrapperClassName),
42
+ children: [
43
+ label && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
44
+ /* @__PURE__ */ jsx("label", { htmlFor: textareaId, className: "text-sm leading-[18px] font-medium text-text-default", children: label }),
45
+ optional && /* @__PURE__ */ jsx("span", { className: "text-sm text-text-muted", children: "(Optional)" })
46
+ ] }),
47
+ /* @__PURE__ */ jsxs("div", { className: "relative flex", children: [
48
+ /* @__PURE__ */ jsx(
49
+ "textarea",
50
+ {
51
+ id: textareaId,
52
+ "data-slot": "textarea",
53
+ "data-filled": text.length > 0 || void 0,
54
+ "data-invalid": invalid || void 0,
55
+ "data-disabled": isDisabled || void 0,
56
+ "data-force": force,
57
+ className: cn("satin-field satin-textarea", className),
58
+ disabled: isDisabled,
59
+ required: required ?? field?.required,
60
+ "aria-invalid": invalid || void 0,
61
+ "aria-describedby": describedBy,
62
+ value,
63
+ defaultValue,
64
+ onChange: (e) => {
65
+ if (value == null) setUncontrolled(e.target.value);
66
+ onChange?.(e.target.value);
67
+ },
68
+ ...props
69
+ }
70
+ ),
71
+ /* @__PURE__ */ jsx("svg", { className: "satin-textarea-grip", viewBox: "0 0 7 7", fill: "none", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M6.5 0.5L0.5 6.5M6.5 4L4 6.5", stroke: "currentColor", strokeLinecap: "round" }) })
72
+ ] }),
73
+ (message || maxLength != null) && /* @__PURE__ */ jsxs(
74
+ "div",
75
+ {
76
+ className: cn(
77
+ "flex items-start gap-2 text-sm",
78
+ hasMessage ? "text-action-destructive-bg" : "text-text-muted"
79
+ ),
80
+ children: [
81
+ /* @__PURE__ */ jsx("p", { id: messageId, className: "min-w-0 flex-1", children: message }),
82
+ maxLength != null && /* @__PURE__ */ jsxs("p", { id: counterId, className: cn("shrink-0 whitespace-nowrap", !hasMessage && "text-text-muted"), children: [
83
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Characters used: " }),
84
+ text.length,
85
+ "/",
86
+ maxLength
87
+ ] })
88
+ ]
89
+ }
90
+ )
91
+ ]
92
+ }
93
+ );
94
+ }
95
+
96
+ export { Textarea };
97
+ //# sourceMappingURL=chunk-QUF2IPOZ.js.map
98
+ //# sourceMappingURL=chunk-QUF2IPOZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/textarea.tsx"],"names":[],"mappings":"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","file":"chunk-QUF2IPOZ.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\nimport { useFormField } from './form-field'\n\n/**\n * Textarea, 1:1 with the uiKit `Textarea` set (3647:17812): the Input skin (surface fill,\n * border/default, radius-lg, shadow xs; border/strong on hover, border/focus and the focus\n * ring on focus, action/destructive/bg on error) at 96px tall with a resize grip. Above it a\n * label (medium 13/18) with an optional \"(Optional)\" in muted 13; under it a hint row: the\n * hint (muted) and, with `maxLength`, a counter (text/subtle) on the right. An error message\n * replaces the hint and turns the whole row action/destructive/bg. Disabled is bg/muted with\n * text/subtle and the whole field at 60%.\n *\n * `maxLength` drives the counter and is not enforced, so a pasted text can run over and show\n * it (134/120); pair it with `error` to say what to fix. The look is styles/components/\n * input.css (`.satin-field`) plus textarea.css.\n */\nexport interface TextareaProps extends Omit<React.ComponentProps<'textarea'>, 'onChange' | 'maxLength'> {\n label?: React.ReactNode\n /** Adds a muted \"(Optional)\" after the label. */\n optional?: boolean\n hint?: React.ReactNode\n /** An error message (replaces the hint), or `true` to mark the field invalid without one. */\n error?: React.ReactNode | boolean\n /** Shows a `length/maxLength` counter. */\n maxLength?: number\n onChange?: (value: string) => void\n /** Classes for the outer wrapper (label + field + hint row). `className` styles the field. */\n wrapperClassName?: string\n /** Show a state without interacting, for state sheets. */\n 'data-force'?: 'hover' | 'focus'\n}\n\nexport function Textarea({\n label,\n optional,\n hint,\n error,\n maxLength,\n className,\n wrapperClassName,\n id,\n disabled,\n required,\n value,\n defaultValue,\n onChange,\n 'aria-describedby': ariaDescribedBy,\n 'data-force': force,\n ...props\n}: TextareaProps) {\n const field = useFormField()\n const autoId = React.useId()\n const textareaId = id ?? field?.id ?? autoId\n const isDisabled = disabled ?? field?.disabled ?? false\n const hasMessage = typeof error === 'string' || React.isValidElement(error)\n const invalid = Boolean(error) || (field?.invalid ?? false)\n const message = hasMessage ? error : hint\n\n const [uncontrolled, setUncontrolled] = React.useState(defaultValue != null ? String(defaultValue) : '')\n const text = value != null ? String(value) : uncontrolled\n\n const messageId = message ? `${textareaId}-hint` : undefined\n const counterId = maxLength != null ? `${textareaId}-counter` : undefined\n const describedBy =\n [ariaDescribedBy, field?.describedBy, messageId, counterId].filter(Boolean).join(' ') || undefined\n\n return (\n <div\n data-slot=\"textarea-wrapper\"\n data-disabled={isDisabled || undefined}\n className={cn('satin-textarea-root grid w-full gap-2', wrapperClassName)}\n >\n {label && (\n <div className=\"flex items-center gap-1\">\n <label htmlFor={textareaId} className=\"text-sm leading-[18px] font-medium text-text-default\">\n {label}\n </label>\n {optional && <span className=\"text-sm text-text-muted\">(Optional)</span>}\n </div>\n )}\n <div className=\"relative flex\">\n <textarea\n id={textareaId}\n data-slot=\"textarea\"\n data-filled={text.length > 0 || undefined}\n data-invalid={invalid || undefined}\n data-disabled={isDisabled || undefined}\n data-force={force}\n className={cn('satin-field satin-textarea', className)}\n disabled={isDisabled}\n required={required ?? field?.required}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n value={value}\n defaultValue={defaultValue}\n onChange={(e) => {\n if (value == null) setUncontrolled(e.target.value)\n onChange?.(e.target.value)\n }}\n {...props}\n />\n {/* Figma's resizeHandle, 7px at 1px in text/subtle. */}\n <svg className=\"satin-textarea-grip\" viewBox=\"0 0 7 7\" fill=\"none\" aria-hidden>\n <path d=\"M6.5 0.5L0.5 6.5M6.5 4L4 6.5\" stroke=\"currentColor\" strokeLinecap=\"round\" />\n </svg>\n </div>\n {(message || maxLength != null) && (\n <div\n className={cn(\n 'flex items-start gap-2 text-sm',\n hasMessage ? 'text-action-destructive-bg' : 'text-text-muted',\n )}\n >\n <p id={messageId} className=\"min-w-0 flex-1\">\n {message}\n </p>\n {maxLength != null && (\n <p id={counterId} className={cn('shrink-0 whitespace-nowrap', !hasMessage && 'text-text-muted')}>\n <span className=\"sr-only\">Characters used: </span>\n {text.length}/{maxLength}\n </p>\n )}\n </div>\n )}\n </div>\n )\n}\n"]}
@@ -0,0 +1,126 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import * as React from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ var PAUSE = { ".": 140, "!": 140, "?": 140, ",": 50, ";": 50, ":": 50, "\n": 90 };
6
+ var CATCH_UP_S = 0.9;
7
+ var CARET_LAG = 90;
8
+ function split(text, byWord) {
9
+ return byWord ? text.match(/\S+\s*|\s+/g) ?? [] : Array.from(text);
10
+ }
11
+ function StreamingText({
12
+ text,
13
+ streaming = false,
14
+ speed = 80,
15
+ reveal = "blur",
16
+ caret = true,
17
+ onDone,
18
+ className,
19
+ ...props
20
+ }) {
21
+ const units = React.useMemo(() => split(text, reveal === "word"), [text, reveal]);
22
+ const box = React.useRef(null);
23
+ const shown = React.useRef(0);
24
+ const caretEl = React.useRef(null);
25
+ const done = React.useRef(onDone);
26
+ done.current = onDone;
27
+ const finished = React.useRef(false);
28
+ const prevText = React.useRef(text);
29
+ if (!text.startsWith(prevText.current)) {
30
+ shown.current = 0;
31
+ finished.current = false;
32
+ }
33
+ prevText.current = text;
34
+ React.useEffect(() => {
35
+ const el = box.current;
36
+ if (!el) return;
37
+ const spans = [...el.querySelectorAll(".satin-stream-unit")];
38
+ for (let i = 0; i < spans.length; i++) {
39
+ if (i < shown.current) spans[i].setAttribute("data-on", "");
40
+ else spans[i].removeAttribute("data-on");
41
+ }
42
+ let mark = caretEl.current;
43
+ if (!mark) {
44
+ mark = document.createElement("span");
45
+ mark.className = "satin-stream-caret";
46
+ mark.setAttribute("aria-hidden", "true");
47
+ caretEl.current = mark;
48
+ }
49
+ const litAt = [];
50
+ const placeCaret = (now = Infinity) => {
51
+ if (!caret || !streaming && shown.current >= spans.length) return mark.remove();
52
+ let i = shown.current - 1;
53
+ if (reveal !== "none") while (i >= 0 && litAt[i] !== void 0 && now - litAt[i] < CARET_LAG) i--;
54
+ const last2 = spans[i];
55
+ if (last2) {
56
+ if (last2.nextSibling !== mark) last2.after(mark);
57
+ } else el.prepend(mark);
58
+ };
59
+ const finish = () => {
60
+ placeCaret();
61
+ if (!streaming && shown.current >= spans.length && !finished.current) {
62
+ finished.current = true;
63
+ done.current?.();
64
+ }
65
+ };
66
+ if (typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches) {
67
+ spans.forEach((s) => s.setAttribute("data-on", ""));
68
+ shown.current = spans.length;
69
+ finish();
70
+ return;
71
+ }
72
+ let raf = 0;
73
+ let last = performance.now();
74
+ let wait = 0;
75
+ let budget = 0;
76
+ const tick = (now) => {
77
+ const dt = Math.min(now - last, 100);
78
+ last = now;
79
+ const backlog = spans.length - shown.current;
80
+ const unitsPerLetter = reveal === "word" ? 5 : 1;
81
+ const rate = Math.max(speed / unitsPerLetter, backlog / CATCH_UP_S);
82
+ const catchingUp = backlog / CATCH_UP_S > speed / unitsPerLetter;
83
+ if (wait > 0 && !catchingUp) wait -= dt;
84
+ else {
85
+ budget += rate * dt / 1e3;
86
+ while (budget >= 1 && shown.current < spans.length) {
87
+ const s = spans[shown.current++];
88
+ s.setAttribute("data-on", "");
89
+ litAt[shown.current - 1] = now;
90
+ budget -= 1;
91
+ const ch = (s.textContent ?? "").trimEnd().slice(-1) || (s.textContent ?? "");
92
+ const pause = PAUSE[ch];
93
+ if (pause && !catchingUp) {
94
+ wait = pause;
95
+ budget = 0;
96
+ break;
97
+ }
98
+ }
99
+ if (shown.current >= spans.length) budget = 0;
100
+ }
101
+ placeCaret(now);
102
+ if (shown.current < spans.length) raf = requestAnimationFrame(tick);
103
+ else finish();
104
+ };
105
+ if (shown.current < spans.length) raf = requestAnimationFrame(tick);
106
+ else finish();
107
+ return () => cancelAnimationFrame(raf);
108
+ }, [units, streaming, speed, reveal, caret]);
109
+ React.useEffect(() => () => caretEl.current?.remove(), []);
110
+ return /* @__PURE__ */ jsx(
111
+ "div",
112
+ {
113
+ ref: box,
114
+ "data-slot": "streaming-text",
115
+ "data-reveal": reveal,
116
+ "aria-busy": streaming || void 0,
117
+ className: cn("satin-stream text-body whitespace-pre-wrap text-text-default", className),
118
+ ...props,
119
+ children: units.map((u, i) => /* @__PURE__ */ jsx("span", { className: "satin-stream-unit", children: u }, i))
120
+ }
121
+ );
122
+ }
123
+
124
+ export { StreamingText };
125
+ //# sourceMappingURL=chunk-RTJ76X5U.js.map
126
+ //# sourceMappingURL=chunk-RTJ76X5U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/streaming-text.tsx"],"names":["last"],"mappings":"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","file":"chunk-RTJ76X5U.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\n\n/**\n * Streaming text: an agent's answer writing itself out as it arrives, in the assistant\n * Message's type (text/default 13/19.5).\n *\n * Give it the text received so far and keep it growing; `streaming` while more is coming. A\n * model sends text in uneven chunks, so the component doesn't print them as they land: it\n * writes at an even pace (`speed`, letters a second), stops briefly after a full stop or a\n * comma, and speeds up when it falls behind, so a backlog never takes more than about a second\n * to catch up. A caret (2px, action/primary/bg) sits at the end while it writes.\n *\n * `reveal` is how each piece comes in: `blur` (default) fades every letter in from a 2px blur\n * over 220 ms, `fade` without the blur, `word` a word at a time, `none` prints letters as they\n * come with no motion. Only the letters arriving animate; the rest carry no filter.\n *\n * The whole text received is in the DOM from the start (letters not yet written are only\n * transparent), so screen readers get it at once; the box is aria-busy while it streams.\n * With reduced motion it shows everything received straight away.\n */\nexport interface StreamingTextProps extends Omit<React.ComponentProps<'div'>, 'children'> {\n /** Everything received so far. Grow it as chunks arrive. */\n text: string\n /** More is coming: keeps the caret and the pace going. */\n streaming?: boolean\n /** Letters written a second at the even pace. */\n speed?: number\n reveal?: 'blur' | 'fade' | 'word' | 'none'\n /** The caret at the end while it writes. */\n caret?: boolean\n /** Called once everything received is written and `streaming` is off. */\n onDone?: () => void\n}\n\n/** Extra pause after these, ms, at the even pace. */\nconst PAUSE: Record<string, number> = { '.': 140, '!': 140, '?': 140, ',': 50, ';': 50, ':': 50, '\\n': 90 }\n/** A backlog is cleared within about this long, s. */\nconst CATCH_UP_S = 0.9\n/** The caret sits after the last letter lit at least this long ago, ms: one already readable,\n * not one still coming in from transparent, so it never runs ahead of the visible text. */\nconst CARET_LAG = 90\n\n/** Letters, or words with the space after them, each one unit to light. */\nfunction split(text: string, byWord: boolean) {\n return byWord ? (text.match(/\\S+\\s*|\\s+/g) ?? []) : Array.from(text)\n}\n\nexport function StreamingText({\n text,\n streaming = false,\n speed = 80,\n reveal = 'blur',\n caret = true,\n onDone,\n className,\n ...props\n}: StreamingTextProps) {\n const units = React.useMemo(() => split(text, reveal === 'word'), [text, reveal])\n const box = React.useRef<HTMLDivElement>(null)\n const shown = React.useRef(0)\n const caretEl = React.useRef<HTMLSpanElement | null>(null)\n const done = React.useRef(onDone)\n done.current = onDone\n const finished = React.useRef(false)\n\n // Start over when the text is replaced rather than extended (a new answer).\n const prevText = React.useRef(text)\n if (!text.startsWith(prevText.current)) {\n shown.current = 0\n finished.current = false\n }\n prevText.current = text\n\n React.useEffect(() => {\n const el = box.current\n if (!el) return\n const spans = [...el.querySelectorAll<HTMLElement>('.satin-stream-unit')]\n // Spans re-rendered from scratch (a reset) lose their lit state: put it back up to `shown`.\n for (let i = 0; i < spans.length; i++) {\n if (i < shown.current) spans[i].setAttribute('data-on', '')\n else spans[i].removeAttribute('data-on')\n }\n\n let mark = caretEl.current\n if (!mark) {\n mark = document.createElement('span')\n mark.className = 'satin-stream-caret'\n mark.setAttribute('aria-hidden', 'true')\n caretEl.current = mark\n }\n const litAt: number[] = []\n const placeCaret = (now = Infinity) => {\n if (!caret || (!streaming && shown.current >= spans.length)) return mark!.remove()\n let i = shown.current - 1\n if (reveal !== 'none') while (i >= 0 && litAt[i] !== undefined && now - litAt[i] < CARET_LAG) i--\n const last = spans[i]\n if (last) {\n if (last.nextSibling !== mark) last.after(mark!)\n } else el.prepend(mark!)\n }\n const finish = () => {\n placeCaret()\n if (!streaming && shown.current >= spans.length && !finished.current) {\n finished.current = true\n done.current?.()\n }\n }\n\n if (typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {\n spans.forEach((s) => s.setAttribute('data-on', ''))\n shown.current = spans.length\n finish()\n return\n }\n\n let raf = 0\n let last = performance.now()\n let wait = 0 // ms left of a pause\n let budget = 0 // units owed at the current pace\n const tick = (now: number) => {\n const dt = Math.min(now - last, 100)\n last = now\n const backlog = spans.length - shown.current\n // Letters (or words) a second: the even pace, or faster to clear a backlog in time.\n const unitsPerLetter = reveal === 'word' ? 5 : 1\n const rate = Math.max(speed / unitsPerLetter, backlog / CATCH_UP_S)\n const catchingUp = backlog / CATCH_UP_S > speed / unitsPerLetter\n if (wait > 0 && !catchingUp) wait -= dt\n else {\n budget += (rate * dt) / 1000\n while (budget >= 1 && shown.current < spans.length) {\n const s = spans[shown.current++]\n s.setAttribute('data-on', '')\n litAt[shown.current - 1] = now\n budget -= 1\n const ch = (s.textContent ?? '').trimEnd().slice(-1) || (s.textContent ?? '')\n const pause = PAUSE[ch]\n if (pause && !catchingUp) {\n wait = pause\n budget = 0\n break\n }\n }\n if (shown.current >= spans.length) budget = 0\n }\n placeCaret(now)\n if (shown.current < spans.length) raf = requestAnimationFrame(tick)\n else finish()\n }\n if (shown.current < spans.length) raf = requestAnimationFrame(tick)\n else finish()\n return () => cancelAnimationFrame(raf)\n }, [units, streaming, speed, reveal, caret])\n\n React.useEffect(() => () => caretEl.current?.remove(), [])\n\n return (\n <div\n ref={box}\n data-slot=\"streaming-text\"\n data-reveal={reveal}\n aria-busy={streaming || undefined}\n className={cn('satin-stream text-body whitespace-pre-wrap text-text-default', className)}\n {...props}\n >\n {units.map((u, i) => (\n <span key={i} className=\"satin-stream-unit\">\n {u}\n </span>\n ))}\n </div>\n )\n}\n"]}
@@ -0,0 +1,40 @@
1
+ import { cn } from './chunk-H63FYCMY.js';
2
+ import * as React from 'react';
3
+ import { Switch as Switch$1 } from 'radix-ui';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ function Switch({ className, label, description, placement = "left", id, ...props }) {
7
+ const autoId = React.useId();
8
+ const switchId = id ?? autoId;
9
+ const descriptionId = description ? `${switchId}-description` : void 0;
10
+ const control = /* @__PURE__ */ jsx(
11
+ Switch$1.Root,
12
+ {
13
+ id: switchId,
14
+ "data-slot": "switch",
15
+ "aria-describedby": descriptionId,
16
+ className: cn("peer satin-switch", className),
17
+ ...props,
18
+ children: /* @__PURE__ */ jsx(Switch$1.Thumb, { className: "satin-switch-thumb" })
19
+ }
20
+ );
21
+ if (!label && !description) return control;
22
+ return /* @__PURE__ */ jsxs(
23
+ "div",
24
+ {
25
+ "data-slot": "switch-field",
26
+ className: cn("flex items-start gap-2.5", placement === "right" && "flex-row-reverse justify-between"),
27
+ children: [
28
+ control,
29
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-0.5 text-sm leading-[19.5px] peer-disabled:opacity-50", children: [
30
+ label && /* @__PURE__ */ jsx("label", { htmlFor: switchId, className: "font-medium text-text-default", children: label }),
31
+ description && /* @__PURE__ */ jsx("p", { id: descriptionId, className: "text-text-muted", children: description })
32
+ ] })
33
+ ]
34
+ }
35
+ );
36
+ }
37
+
38
+ export { Switch };
39
+ //# sourceMappingURL=chunk-SH6NG6VN.js.map
40
+ //# sourceMappingURL=chunk-SH6NG6VN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/switch.tsx"],"names":["SwitchPrimitive"],"mappings":";;;;;AAmBO,SAAS,MAAA,CAAO,EAAE,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,YAAY,MAAA,EAAQ,EAAA,EAAI,GAAG,KAAA,EAAM,EAAgB;AACvG,EAAA,MAAM,SAAe,KAAA,CAAA,KAAA,EAAM;AAC3B,EAAA,MAAM,WAAW,EAAA,IAAM,MAAA;AACvB,EAAA,MAAM,aAAA,GAAgB,WAAA,GAAc,CAAA,EAAG,QAAQ,CAAA,YAAA,CAAA,GAAiB,MAAA;AAEhE,EAAA,MAAM,OAAA,mBACJ,GAAA;AAAA,IAACA,QAAA,CAAgB,IAAA;AAAA,IAAhB;AAAA,MACC,EAAA,EAAI,QAAA;AAAA,MACJ,WAAA,EAAU,QAAA;AAAA,MACV,kBAAA,EAAkB,aAAA;AAAA,MAClB,SAAA,EAAW,EAAA,CAAG,mBAAA,EAAqB,SAAS,CAAA;AAAA,MAC3C,GAAG,KAAA;AAAA,MAEJ,QAAA,kBAAA,GAAA,CAACA,QAAA,CAAgB,KAAA,EAAhB,EAAsB,WAAU,oBAAA,EAAqB;AAAA;AAAA,GACxD;AAGF,EAAA,IAAI,CAAC,KAAA,IAAS,CAAC,WAAA,EAAa,OAAO,OAAA;AAEnC,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,cAAA;AAAA,MACV,SAAA,EAAW,EAAA,CAAG,0BAAA,EAA4B,SAAA,KAAc,WAAW,kCAAkC,CAAA;AAAA,MAEpG,QAAA,EAAA;AAAA,QAAA,OAAA;AAAA,wBACD,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gEAAA,EACZ,QAAA,EAAA;AAAA,UAAA,KAAA,wBACE,OAAA,EAAA,EAAM,OAAA,EAAS,QAAA,EAAU,SAAA,EAAU,iCACjC,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UAED,+BACC,GAAA,CAAC,GAAA,EAAA,EAAE,IAAI,aAAA,EAAe,SAAA,EAAU,mBAC7B,QAAA,EAAA,WAAA,EACH;AAAA,SAAA,EAEJ;AAAA;AAAA;AAAA,GACF;AAEJ","file":"chunk-SH6NG6VN.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { Switch as SwitchPrimitive } from 'radix-ui'\nimport { cn } from '../lib/utils'\n\n/**\n * Switch, 1:1 with the uiKit `_switchBase` (3647:17617) and `Switch` (3647:17714) sets: a\n * 32 × 18 track (border/input off, calm green on, each with its hover), a 14px white thumb,\n * a 2px focus ring, 50% when disabled. Label medium 13/19.5, description muted, 10px from\n * the track. Use it for settings that apply at once; use a checkbox inside a form.\n * The look of every state lives in styles/components.css.\n */\nexport interface SwitchProps extends React.ComponentProps<typeof SwitchPrimitive.Root> {\n label?: React.ReactNode\n description?: React.ReactNode\n placement?: 'left' | 'right'\n}\n\nexport function Switch({ className, label, description, placement = 'left', id, ...props }: SwitchProps) {\n const autoId = React.useId()\n const switchId = id ?? autoId\n const descriptionId = description ? `${switchId}-description` : undefined\n\n const control = (\n <SwitchPrimitive.Root\n id={switchId}\n data-slot=\"switch\"\n aria-describedby={descriptionId}\n className={cn('peer satin-switch', className)}\n {...props}\n >\n <SwitchPrimitive.Thumb className=\"satin-switch-thumb\" />\n </SwitchPrimitive.Root>\n )\n\n if (!label && !description) return control\n\n return (\n <div\n data-slot=\"switch-field\"\n className={cn('flex items-start gap-2.5', placement === 'right' && 'flex-row-reverse justify-between')}\n >\n {control}\n <div className=\"grid gap-0.5 text-sm leading-[19.5px] peer-disabled:opacity-50\">\n {label && (\n <label htmlFor={switchId} className=\"font-medium text-text-default\">\n {label}\n </label>\n )}\n {description && (\n <p id={descriptionId} className=\"text-text-muted\">\n {description}\n </p>\n )}\n </div>\n </div>\n )\n}\n"]}
@@ -0,0 +1,195 @@
1
+ import { niceMax } from './chunk-DO3TBNSC.js';
2
+ import { ChartCard, defaultFormat, ChartTooltip } from './chunk-YPJYW624.js';
3
+ import { cn } from './chunk-H63FYCMY.js';
4
+ import * as React from 'react';
5
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
6
+
7
+ var TRACK = 180;
8
+ function smoothPath(pts) {
9
+ const n = pts.length;
10
+ if (n === 0) return "";
11
+ if (n === 1) return `M ${pts[0][0]} ${pts[0][1]}`;
12
+ const dx = [], dy = [], m = [];
13
+ for (let i = 0; i < n - 1; i++) {
14
+ dx[i] = pts[i + 1][0] - pts[i][0];
15
+ dy[i] = (pts[i + 1][1] - pts[i][1]) / dx[i];
16
+ }
17
+ m[0] = dy[0];
18
+ m[n - 1] = dy[n - 2];
19
+ for (let i = 1; i < n - 1; i++) m[i] = dy[i - 1] * dy[i] <= 0 ? 0 : (dy[i - 1] + dy[i]) / 2;
20
+ for (let i = 0; i < n - 1; i++) {
21
+ if (dy[i] === 0) {
22
+ m[i] = 0;
23
+ m[i + 1] = 0;
24
+ continue;
25
+ }
26
+ const a = m[i] / dy[i], b = m[i + 1] / dy[i], h = a * a + b * b;
27
+ if (h > 9) {
28
+ const t = 3 / Math.sqrt(h);
29
+ m[i] = t * a * dy[i];
30
+ m[i + 1] = t * b * dy[i];
31
+ }
32
+ }
33
+ let d = `M ${pts[0][0]} ${pts[0][1]}`;
34
+ for (let i = 0; i < n - 1; i++) {
35
+ const h = dx[i] / 3;
36
+ d += ` C ${pts[i][0] + h} ${pts[i][1] + m[i] * h} ${pts[i + 1][0] - h} ${pts[i + 1][1] - m[i + 1] * h} ${pts[i + 1][0]} ${pts[i + 1][1]}`;
37
+ }
38
+ return d;
39
+ }
40
+ function LineCard({
41
+ data,
42
+ formatValue = defaultFormat,
43
+ highlight,
44
+ unit,
45
+ area = false,
46
+ reducedMotion,
47
+ total,
48
+ ...props
49
+ }) {
50
+ const gradientId = React.useId();
51
+ const [hovered, setHovered] = React.useState(null);
52
+ const [anchor, setAnchor] = React.useState(null);
53
+ const n = data.length;
54
+ const active = (hovered != null && hovered < n ? hovered : null) ?? highlight ?? null;
55
+ const signature = data.map((d) => `${d.label}:${d.value}`).join("|");
56
+ const [redraw, setRedraw] = React.useState({ signature, n: 0 });
57
+ if (redraw.signature !== signature) setRedraw({ signature, n: redraw.n + 1 });
58
+ const fade = redraw.n > 0 && !reducedMotion;
59
+ const max = niceMax(Math.max(0, ...data.map((d) => d.value)));
60
+ const ticks = [4, 3, 2, 1, 0].map((i) => max / 4 * i);
61
+ const sum = data.reduce((s, d) => s + d.value, 0);
62
+ const x = (i) => n <= 1 ? 50 : i / (n - 1) * 100;
63
+ const y = (v) => TRACK - v / max * TRACK;
64
+ const pts = data.map((d, i) => [x(i), y(d.value)]);
65
+ const line = smoothPath(pts);
66
+ const step = Math.max(1, Math.ceil(n / 7));
67
+ const showLabel = (i) => (n - 1 - i) % step === 0;
68
+ const pick = (e) => {
69
+ const r = e.currentTarget.getBoundingClientRect();
70
+ const f = (e.clientX - r.left) / r.width;
71
+ setHovered(Math.max(0, Math.min(n - 1, Math.round(f * (n - 1)))));
72
+ };
73
+ const fmt = (v) => `${formatValue(v)}${unit ? ` ${unit}` : ""}`;
74
+ return /* @__PURE__ */ jsx(ChartCard, { total: total ?? defaultFormat(sum), ...props, children: /* @__PURE__ */ jsxs("div", { className: "relative pt-2 pl-8", children: [
75
+ ticks.map((t, i) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
76
+ i < 4 && /* @__PURE__ */ jsx(
77
+ "span",
78
+ {
79
+ "aria-hidden": true,
80
+ className: "absolute right-0 left-8 h-px border-t border-dashed border-border-subtle",
81
+ style: { top: 8 + TRACK / 4 * i }
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsx(
85
+ "span",
86
+ {
87
+ "aria-hidden": true,
88
+ className: cn("absolute left-6 w-6 -translate-x-full text-right text-xs leading-[18px] text-text-muted", fade && "satin-bar-fade"),
89
+ style: { top: 8 + TRACK / 4 * i - 9 },
90
+ children: formatValue(t)
91
+ },
92
+ `${redraw.n}-${i}`
93
+ )
94
+ ] }, i)),
95
+ /* @__PURE__ */ jsxs(
96
+ "div",
97
+ {
98
+ role: "group",
99
+ "aria-label": `${props.title}, ${n} points`,
100
+ tabIndex: 0,
101
+ className: "relative rounded-md outline-none focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]",
102
+ style: { height: TRACK },
103
+ onPointerMove: pick,
104
+ onPointerLeave: () => setHovered(null),
105
+ onFocus: () => setHovered((h) => h ?? n - 1),
106
+ onBlur: () => setHovered(null),
107
+ onKeyDown: (e) => {
108
+ if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
109
+ e.preventDefault();
110
+ setHovered((h) => Math.max(0, Math.min(n - 1, (h ?? n - 1) + (e.key === "ArrowRight" ? 1 : -1))));
111
+ },
112
+ children: [
113
+ /* @__PURE__ */ jsxs(
114
+ "svg",
115
+ {
116
+ "aria-hidden": true,
117
+ viewBox: `0 0 100 ${TRACK}`,
118
+ preserveAspectRatio: "none",
119
+ className: cn("absolute inset-0 size-full overflow-visible", fade && "satin-bar-fade"),
120
+ children: [
121
+ area && /* @__PURE__ */ jsxs(Fragment, { children: [
122
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", x2: "0", y1: "0", y2: "1", children: [
123
+ /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: "var(--chart-3)", stopOpacity: "0.28" }),
124
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "var(--chart-3)", stopOpacity: "0" })
125
+ ] }) }),
126
+ /* @__PURE__ */ jsx("path", { d: `${line} L 100 ${TRACK} L 0 ${TRACK} Z`, fill: `url(#${gradientId})` })
127
+ ] }),
128
+ active != null && /* @__PURE__ */ jsx(
129
+ "line",
130
+ {
131
+ x1: x(active),
132
+ x2: x(active),
133
+ y1: y(data[active].value) + 4,
134
+ y2: TRACK,
135
+ stroke: "var(--border-strong)",
136
+ strokeDasharray: "4 4",
137
+ vectorEffect: "non-scaling-stroke"
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsx(
141
+ "path",
142
+ {
143
+ d: line,
144
+ fill: "none",
145
+ stroke: "var(--chart-3)",
146
+ strokeWidth: 2,
147
+ strokeLinecap: "round",
148
+ strokeLinejoin: "round",
149
+ vectorEffect: "non-scaling-stroke"
150
+ }
151
+ )
152
+ ]
153
+ },
154
+ redraw.n
155
+ ),
156
+ active != null && /* @__PURE__ */ jsxs(Fragment, { children: [
157
+ /* @__PURE__ */ jsx(
158
+ "span",
159
+ {
160
+ ref: setAnchor,
161
+ "aria-hidden": true,
162
+ className: "pointer-events-none absolute size-2 -translate-1/2 rounded-full border-2 border-chart-3 bg-bg-card",
163
+ style: { left: `${x(active)}%`, top: y(data[active].value) }
164
+ }
165
+ ),
166
+ /* @__PURE__ */ jsx(ChartTooltip, { anchor, sideOffset: 6, label: data[active].tooltipLabel ?? data[active].label, value: fmt(data[active].value) }),
167
+ /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: `${data[active].tooltipLabel ?? data[active].label}: ${fmt(data[active].value)}` })
168
+ ] })
169
+ ]
170
+ }
171
+ ),
172
+ /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "relative mt-1.5 h-5", children: data.map(
173
+ (d, i) => showLabel(i) ? /* @__PURE__ */ jsx(
174
+ "span",
175
+ {
176
+ className: cn(
177
+ "absolute -translate-x-1/2 text-sm leading-(--text-sm--line-height) whitespace-nowrap",
178
+ i === active ? "font-medium text-text-default" : "text-text-muted",
179
+ fade && "satin-bar-fade"
180
+ ),
181
+ style: { left: `${x(i)}%` },
182
+ children: d.label
183
+ },
184
+ `${redraw.n}-${d.label}-${i}`
185
+ ) : null
186
+ ) })
187
+ ] }) });
188
+ }
189
+ function AreaCard(props) {
190
+ return /* @__PURE__ */ jsx(LineCard, { ...props, area: true });
191
+ }
192
+
193
+ export { AreaCard, LineCard };
194
+ //# sourceMappingURL=chunk-SHDFUXYV.js.map
195
+ //# sourceMappingURL=chunk-SHDFUXYV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/line-chart.tsx"],"names":["Fragment"],"mappings":"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","file":"chunk-SHDFUXYV.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { cn } from '../lib/utils'\nimport { niceMax } from './bar-chart'\nimport { ChartCard, ChartTooltip, defaultFormat, type ChartCardBaseProps } from './chart'\n\n/**\n * Line and Area chart, 1:1 with the uiKit `chart/lineCard` (4076:6759) and `chart/areaCard`\n * (4070:7627), in the shared ChartCard (chart.tsx).\n *\n * One metric over the period: a smooth 2px line in chart/3 (monotone, so it never overshoots a\n * point) over a 180px plot with a 32px axis gutter and 4 dashed border-subtle gridlines at nice\n * ticks, the x labels 6px under it (at most about seven, evenly picked). `AreaCard` fills under\n * the line with chart/3 fading from 28% to nothing at the baseline. No legend: the title says\n * what is plotted and the KPI above gives its total.\n *\n * Hover (or `highlight`) picks the nearest point: a dashed border-strong drop line from it to the\n * baseline, an 8px dot ringed in chart/3 on bg/card, the tooltip above it (date and value) and\n * its x label in text/default. Every point is also reachable with the keyboard (arrow keys on the\n * focused plot). When the data changes the plot fades in on its new scale, unless motion is\n * reduced.\n */\nexport interface LineCardProps extends ChartCardBaseProps {\n /** Unit after the value in the tooltip (\"orders\"). */\n unit?: string\n /** Fill under the line. `AreaCard` sets it. */\n area?: boolean\n /** Swap the plot without the fade when the data changes, as under prefers-reduced-motion. */\n reducedMotion?: boolean\n}\n\nconst TRACK = 180\n\n/** Monotone cubic (Fritsch–Carlson) through the points, as an SVG path. */\nfunction smoothPath(pts: [number, number][]) {\n const n = pts.length\n if (n === 0) return ''\n if (n === 1) return `M ${pts[0][0]} ${pts[0][1]}`\n const dx: number[] = [], dy: number[] = [], m: number[] = []\n for (let i = 0; i < n - 1; i++) {\n dx[i] = pts[i + 1][0] - pts[i][0]\n dy[i] = (pts[i + 1][1] - pts[i][1]) / dx[i]\n }\n m[0] = dy[0]\n m[n - 1] = dy[n - 2]\n for (let i = 1; i < n - 1; i++) m[i] = dy[i - 1] * dy[i] <= 0 ? 0 : (dy[i - 1] + dy[i]) / 2\n for (let i = 0; i < n - 1; i++) {\n if (dy[i] === 0) {\n m[i] = 0\n m[i + 1] = 0\n continue\n }\n const a = m[i] / dy[i], b = m[i + 1] / dy[i], h = a * a + b * b\n if (h > 9) {\n const t = 3 / Math.sqrt(h)\n m[i] = t * a * dy[i]\n m[i + 1] = t * b * dy[i]\n }\n }\n let d = `M ${pts[0][0]} ${pts[0][1]}`\n for (let i = 0; i < n - 1; i++) {\n const h = dx[i] / 3\n d += ` C ${pts[i][0] + h} ${pts[i][1] + m[i] * h} ${pts[i + 1][0] - h} ${pts[i + 1][1] - m[i + 1] * h} ${pts[i + 1][0]} ${pts[i + 1][1]}`\n }\n return d\n}\n\nexport function LineCard({\n data,\n formatValue = defaultFormat,\n highlight,\n unit,\n area = false,\n reducedMotion,\n total,\n ...props\n}: LineCardProps) {\n const gradientId = React.useId()\n const [hovered, setHovered] = React.useState<number | null>(null)\n const [anchor, setAnchor] = React.useState<HTMLElement | null>(null)\n const n = data.length\n const active = (hovered != null && hovered < n ? hovered : null) ?? highlight ?? null\n\n const signature = data.map((d) => `${d.label}:${d.value}`).join('|')\n const [redraw, setRedraw] = React.useState({ signature, n: 0 })\n if (redraw.signature !== signature) setRedraw({ signature, n: redraw.n + 1 })\n const fade = redraw.n > 0 && !reducedMotion\n\n const max = niceMax(Math.max(0, ...data.map((d) => d.value)))\n const ticks = [4, 3, 2, 1, 0].map((i) => (max / 4) * i)\n const sum = data.reduce((s, d) => s + d.value, 0)\n // x in 0–100 (percent of the plot), y in px down from the top of the track.\n const x = (i: number) => (n <= 1 ? 50 : (i / (n - 1)) * 100)\n const y = (v: number) => TRACK - (v / max) * TRACK\n const pts = data.map((d, i) => [x(i), y(d.value)] as [number, number])\n const line = smoothPath(pts)\n const step = Math.max(1, Math.ceil(n / 7))\n const showLabel = (i: number) => (n - 1 - i) % step === 0\n\n const pick = (e: React.PointerEvent<HTMLDivElement>) => {\n const r = e.currentTarget.getBoundingClientRect()\n const f = (e.clientX - r.left) / r.width\n setHovered(Math.max(0, Math.min(n - 1, Math.round(f * (n - 1)))))\n }\n const fmt = (v: number) => `${formatValue(v)}${unit ? ` ${unit}` : ''}`\n\n return (\n <ChartCard total={total ?? defaultFormat(sum)} {...props}>\n <div className=\"relative pt-2 pl-8\">\n {ticks.map((t, i) => (\n <React.Fragment key={i}>\n {i < 4 && (\n <span\n aria-hidden\n className=\"absolute right-0 left-8 h-px border-t border-dashed border-border-subtle\"\n style={{ top: 8 + (TRACK / 4) * i }}\n />\n )}\n <span\n aria-hidden\n key={`${redraw.n}-${i}`}\n className={cn('absolute left-6 w-6 -translate-x-full text-right text-xs leading-[18px] text-text-muted', fade && 'satin-bar-fade')}\n style={{ top: 8 + (TRACK / 4) * i - 9 }}\n >\n {formatValue(t)}\n </span>\n </React.Fragment>\n ))}\n <div\n role=\"group\"\n aria-label={`${props.title}, ${n} points`}\n tabIndex={0}\n className=\"relative rounded-md outline-none focus-visible:[box-shadow:0_0_0_2px_var(--action-focus-ring)]\"\n style={{ height: TRACK }}\n onPointerMove={pick}\n onPointerLeave={() => setHovered(null)}\n onFocus={() => setHovered((h) => h ?? n - 1)}\n onBlur={() => setHovered(null)}\n onKeyDown={(e) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return\n e.preventDefault()\n setHovered((h) => Math.max(0, Math.min(n - 1, (h ?? n - 1) + (e.key === 'ArrowRight' ? 1 : -1))))\n }}\n >\n <svg\n key={redraw.n}\n aria-hidden\n viewBox={`0 0 100 ${TRACK}`}\n preserveAspectRatio=\"none\"\n className={cn('absolute inset-0 size-full overflow-visible', fade && 'satin-bar-fade')}\n >\n {area && (\n <>\n <defs>\n <linearGradient id={gradientId} x1=\"0\" x2=\"0\" y1=\"0\" y2=\"1\">\n <stop offset=\"0\" stopColor=\"var(--chart-3)\" stopOpacity=\"0.28\" />\n <stop offset=\"1\" stopColor=\"var(--chart-3)\" stopOpacity=\"0\" />\n </linearGradient>\n </defs>\n <path d={`${line} L 100 ${TRACK} L 0 ${TRACK} Z`} fill={`url(#${gradientId})`} />\n </>\n )}\n {active != null && (\n <line\n x1={x(active)}\n x2={x(active)}\n y1={y(data[active].value) + 4}\n y2={TRACK}\n stroke=\"var(--border-strong)\"\n strokeDasharray=\"4 4\"\n vectorEffect=\"non-scaling-stroke\"\n />\n )}\n <path\n d={line}\n fill=\"none\"\n stroke=\"var(--chart-3)\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n vectorEffect=\"non-scaling-stroke\"\n />\n </svg>\n {active != null && (\n <>\n <span\n ref={setAnchor}\n aria-hidden\n className=\"pointer-events-none absolute size-2 -translate-1/2 rounded-full border-2 border-chart-3 bg-bg-card\"\n style={{ left: `${x(active)}%`, top: y(data[active].value) }}\n />\n <ChartTooltip anchor={anchor} sideOffset={6} label={data[active].tooltipLabel ?? data[active].label} value={fmt(data[active].value)} />\n <span className=\"sr-only\" aria-live=\"polite\">\n {`${data[active].tooltipLabel ?? data[active].label}: ${fmt(data[active].value)}`}\n </span>\n </>\n )}\n </div>\n <div aria-hidden className=\"relative mt-1.5 h-5\">\n {data.map((d, i) =>\n showLabel(i) ? (\n <span\n key={`${redraw.n}-${d.label}-${i}`}\n className={cn(\n 'absolute -translate-x-1/2 text-sm leading-(--text-sm--line-height) whitespace-nowrap',\n i === active ? 'font-medium text-text-default' : 'text-text-muted',\n fade && 'satin-bar-fade',\n )}\n style={{ left: `${x(i)}%` }}\n >\n {d.label}\n </span>\n ) : null,\n )}\n </div>\n </div>\n </ChartCard>\n )\n}\n\n/** The Line chart with the gradient under its line. */\nexport function AreaCard(props: Omit<LineCardProps, 'area'>) {\n return <LineCard {...props} area />\n}\n"]}