@tollerud/ui 1.1.5 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/AGENTS.md +36 -13
  2. package/CHANGELOG.md +411 -0
  3. package/COMPONENTS.md +951 -0
  4. package/GETTING_STARTED.md +159 -0
  5. package/README.md +51 -43
  6. package/SKILL.md +59 -24
  7. package/components.json +18 -0
  8. package/dist/accordion.d.ts +20 -0
  9. package/dist/accordion.js +5 -0
  10. package/dist/accordion.js.map +1 -0
  11. package/dist/action-diff.d.ts +26 -0
  12. package/dist/action-diff.js +5 -0
  13. package/dist/action-diff.js.map +1 -0
  14. package/dist/action-row.d.ts +36 -0
  15. package/dist/action-row.js +6 -0
  16. package/dist/action-row.js.map +1 -0
  17. package/dist/alert-inbox.d.ts +23 -0
  18. package/dist/alert-inbox.js +6 -0
  19. package/dist/alert-inbox.js.map +1 -0
  20. package/dist/alert.d.ts +33 -0
  21. package/dist/alert.js +5 -0
  22. package/dist/alert.js.map +1 -0
  23. package/dist/approval-card.d.ts +27 -0
  24. package/dist/approval-card.js +5 -0
  25. package/dist/approval-card.js.map +1 -0
  26. package/dist/area-chart.d.ts +10 -0
  27. package/dist/area-chart.js +5 -0
  28. package/dist/area-chart.js.map +1 -0
  29. package/dist/avatar.d.ts +28 -0
  30. package/dist/avatar.js +5 -0
  31. package/dist/avatar.js.map +1 -0
  32. package/dist/backup-status-panel.d.ts +25 -0
  33. package/dist/backup-status-panel.js +6 -0
  34. package/dist/backup-status-panel.js.map +1 -0
  35. package/dist/badge.d.ts +17 -0
  36. package/dist/badge.js +5 -0
  37. package/dist/badge.js.map +1 -0
  38. package/dist/bar-chart.d.ts +15 -0
  39. package/dist/bar-chart.js +5 -0
  40. package/dist/bar-chart.js.map +1 -0
  41. package/dist/bento-dashboard.d.ts +30 -0
  42. package/dist/bento-dashboard.js +10 -0
  43. package/dist/bento-dashboard.js.map +1 -0
  44. package/dist/breadcrumb.d.ts +16 -0
  45. package/dist/breadcrumb.js +5 -0
  46. package/dist/breadcrumb.js.map +1 -0
  47. package/dist/button.d.ts +29 -0
  48. package/dist/button.js +5 -0
  49. package/dist/button.js.map +1 -0
  50. package/dist/card.d.ts +10 -0
  51. package/dist/card.js +5 -0
  52. package/dist/card.js.map +1 -0
  53. package/dist/checkbox.d.ts +9 -0
  54. package/dist/checkbox.js +5 -0
  55. package/dist/checkbox.js.map +1 -0
  56. package/dist/chunk-2QWKOCWF.js +79 -0
  57. package/dist/chunk-2QWKOCWF.js.map +1 -0
  58. package/dist/chunk-3LTW224O.js +53 -0
  59. package/dist/chunk-3LTW224O.js.map +1 -0
  60. package/dist/chunk-3XTZPDNV.js +94 -0
  61. package/dist/chunk-3XTZPDNV.js.map +1 -0
  62. package/dist/chunk-435JHF7G.js +65 -0
  63. package/dist/chunk-435JHF7G.js.map +1 -0
  64. package/dist/chunk-4PA2ACNF.js +52 -0
  65. package/dist/chunk-4PA2ACNF.js.map +1 -0
  66. package/dist/chunk-5GWHUJ5D.js +29 -0
  67. package/dist/chunk-5GWHUJ5D.js.map +1 -0
  68. package/dist/chunk-6FUKJD3W.js +123 -0
  69. package/dist/chunk-6FUKJD3W.js.map +1 -0
  70. package/dist/chunk-6IS2AYYG.js +106 -0
  71. package/dist/chunk-6IS2AYYG.js.map +1 -0
  72. package/dist/chunk-6PZKU6ZL.js +78 -0
  73. package/dist/chunk-6PZKU6ZL.js.map +1 -0
  74. package/dist/chunk-6SKTH45H.js +75 -0
  75. package/dist/chunk-6SKTH45H.js.map +1 -0
  76. package/dist/chunk-6UXW5YUC.js +77 -0
  77. package/dist/chunk-6UXW5YUC.js.map +1 -0
  78. package/dist/chunk-7EP2T3OW.js +52 -0
  79. package/dist/chunk-7EP2T3OW.js.map +1 -0
  80. package/dist/chunk-7J5QXUQN.js +38 -0
  81. package/dist/chunk-7J5QXUQN.js.map +1 -0
  82. package/dist/chunk-A6L5C3IJ.js +47 -0
  83. package/dist/chunk-A6L5C3IJ.js.map +1 -0
  84. package/dist/chunk-ADE22JSR.js +54 -0
  85. package/dist/chunk-ADE22JSR.js.map +1 -0
  86. package/dist/chunk-ANW6J6PV.js +42 -0
  87. package/dist/chunk-ANW6J6PV.js.map +1 -0
  88. package/dist/chunk-APFFKNPS.js +80 -0
  89. package/dist/chunk-APFFKNPS.js.map +1 -0
  90. package/dist/chunk-AQT3FZRQ.js +23 -0
  91. package/dist/chunk-AQT3FZRQ.js.map +1 -0
  92. package/dist/chunk-AZADSX4Z.js +85 -0
  93. package/dist/chunk-AZADSX4Z.js.map +1 -0
  94. package/dist/chunk-BPCH5LJ3.js +36 -0
  95. package/dist/chunk-BPCH5LJ3.js.map +1 -0
  96. package/dist/chunk-CDI7353B.js +40 -0
  97. package/dist/chunk-CDI7353B.js.map +1 -0
  98. package/dist/chunk-CKNWXYMA.js +53 -0
  99. package/dist/chunk-CKNWXYMA.js.map +1 -0
  100. package/dist/chunk-DNJI65VQ.js +22 -0
  101. package/dist/chunk-DNJI65VQ.js.map +1 -0
  102. package/dist/chunk-DOUDJU4P.js +63 -0
  103. package/dist/chunk-DOUDJU4P.js.map +1 -0
  104. package/dist/chunk-DRCMGIQ6.js +64 -0
  105. package/dist/chunk-DRCMGIQ6.js.map +1 -0
  106. package/dist/chunk-DZOBXK2S.js +28 -0
  107. package/dist/chunk-DZOBXK2S.js.map +1 -0
  108. package/dist/chunk-EN4OJCEF.js +54 -0
  109. package/dist/chunk-EN4OJCEF.js.map +1 -0
  110. package/dist/chunk-EVHZFYWX.js +33 -0
  111. package/dist/chunk-EVHZFYWX.js.map +1 -0
  112. package/dist/chunk-G2VKWNZA.js +53 -0
  113. package/dist/chunk-G2VKWNZA.js.map +1 -0
  114. package/dist/chunk-GTM2DE4C.js +156 -0
  115. package/dist/chunk-GTM2DE4C.js.map +1 -0
  116. package/dist/chunk-H3ZVGTJM.js +165 -0
  117. package/dist/chunk-H3ZVGTJM.js.map +1 -0
  118. package/dist/chunk-HWAWUEHC.js +28 -0
  119. package/dist/chunk-HWAWUEHC.js.map +1 -0
  120. package/dist/chunk-HWJVRTWO.js +36 -0
  121. package/dist/chunk-HWJVRTWO.js.map +1 -0
  122. package/dist/chunk-ILADNTUB.js +77 -0
  123. package/dist/chunk-ILADNTUB.js.map +1 -0
  124. package/dist/chunk-IUPVQWO5.js +31 -0
  125. package/dist/chunk-IUPVQWO5.js.map +1 -0
  126. package/dist/chunk-JFOW2DI5.js +43 -0
  127. package/dist/chunk-JFOW2DI5.js.map +1 -0
  128. package/dist/chunk-JRFSUVSO.js +66 -0
  129. package/dist/chunk-JRFSUVSO.js.map +1 -0
  130. package/dist/chunk-KI6OTVID.js +91 -0
  131. package/dist/chunk-KI6OTVID.js.map +1 -0
  132. package/dist/chunk-LUM2YJBH.js +73 -0
  133. package/dist/chunk-LUM2YJBH.js.map +1 -0
  134. package/dist/chunk-NHPISZWS.js +71 -0
  135. package/dist/chunk-NHPISZWS.js.map +1 -0
  136. package/dist/chunk-NOLWJJHT.js +52 -0
  137. package/dist/chunk-NOLWJJHT.js.map +1 -0
  138. package/dist/chunk-NPVINX3Q.js +20 -0
  139. package/dist/chunk-NPVINX3Q.js.map +1 -0
  140. package/dist/chunk-NSMU66ZX.js +47 -0
  141. package/dist/chunk-NSMU66ZX.js.map +1 -0
  142. package/dist/chunk-O5SWPHUQ.js +79 -0
  143. package/dist/chunk-O5SWPHUQ.js.map +1 -0
  144. package/dist/chunk-OGVSZ7NV.js +53 -0
  145. package/dist/chunk-OGVSZ7NV.js.map +1 -0
  146. package/dist/chunk-OLHMMFQ7.js +43 -0
  147. package/dist/chunk-OLHMMFQ7.js.map +1 -0
  148. package/dist/chunk-ONMTHBZ4.js +54 -0
  149. package/dist/chunk-ONMTHBZ4.js.map +1 -0
  150. package/dist/chunk-OVSIOZHJ.js +56 -0
  151. package/dist/chunk-OVSIOZHJ.js.map +1 -0
  152. package/dist/chunk-Q54CVE3W.js +154 -0
  153. package/dist/chunk-Q54CVE3W.js.map +1 -0
  154. package/dist/chunk-QEHTPQHL.js +35 -0
  155. package/dist/chunk-QEHTPQHL.js.map +1 -0
  156. package/dist/chunk-QEIEWGHA.js +62 -0
  157. package/dist/chunk-QEIEWGHA.js.map +1 -0
  158. package/dist/chunk-QQHBEACI.js +88 -0
  159. package/dist/chunk-QQHBEACI.js.map +1 -0
  160. package/dist/chunk-RJTDQOT2.js +73 -0
  161. package/dist/chunk-RJTDQOT2.js.map +1 -0
  162. package/dist/chunk-RQ3RXKAZ.js +203 -0
  163. package/dist/chunk-RQ3RXKAZ.js.map +1 -0
  164. package/dist/chunk-RZK2S2OO.js +126 -0
  165. package/dist/chunk-RZK2S2OO.js.map +1 -0
  166. package/dist/chunk-SAP7JSSO.js +106 -0
  167. package/dist/chunk-SAP7JSSO.js.map +1 -0
  168. package/dist/chunk-T3TQPOVM.js +79 -0
  169. package/dist/chunk-T3TQPOVM.js.map +1 -0
  170. package/dist/chunk-T3UQ7G4T.js +58 -0
  171. package/dist/chunk-T3UQ7G4T.js.map +1 -0
  172. package/dist/chunk-T56TTOI6.js +53 -0
  173. package/dist/chunk-T56TTOI6.js.map +1 -0
  174. package/dist/chunk-T7EFDE2L.js +36 -0
  175. package/dist/chunk-T7EFDE2L.js.map +1 -0
  176. package/dist/chunk-VFS3V3VY.js +91 -0
  177. package/dist/chunk-VFS3V3VY.js.map +1 -0
  178. package/dist/chunk-VOARBYVQ.js +44 -0
  179. package/dist/chunk-VOARBYVQ.js.map +1 -0
  180. package/dist/chunk-WDANALHD.js +95 -0
  181. package/dist/chunk-WDANALHD.js.map +1 -0
  182. package/dist/chunk-WSQNPRGN.js +12 -0
  183. package/dist/chunk-WSQNPRGN.js.map +1 -0
  184. package/dist/chunk-YPP7QHYT.js +393 -0
  185. package/dist/chunk-YPP7QHYT.js.map +1 -0
  186. package/dist/chunk-YTU7BRDW.js +72 -0
  187. package/dist/chunk-YTU7BRDW.js.map +1 -0
  188. package/dist/chunk-YYWODLER.js +111 -0
  189. package/dist/chunk-YYWODLER.js.map +1 -0
  190. package/dist/chunk-ZOXO3G3I.js +50 -0
  191. package/dist/chunk-ZOXO3G3I.js.map +1 -0
  192. package/dist/chunk-ZTFOR3AN.js +79 -0
  193. package/dist/chunk-ZTFOR3AN.js.map +1 -0
  194. package/dist/code-block.d.ts +14 -0
  195. package/dist/code-block.js +5 -0
  196. package/dist/code-block.js.map +1 -0
  197. package/dist/combobox.d.ts +26 -0
  198. package/dist/combobox.js +5 -0
  199. package/dist/combobox.js.map +1 -0
  200. package/dist/command-menu.d.ts +52 -0
  201. package/dist/command-menu.js +7 -0
  202. package/dist/command-menu.js.map +1 -0
  203. package/dist/container.d.ts +9 -0
  204. package/dist/container.js +5 -0
  205. package/dist/container.js.map +1 -0
  206. package/dist/cta-band.d.ts +12 -0
  207. package/dist/cta-band.js +5 -0
  208. package/dist/cta-band.js.map +1 -0
  209. package/dist/data-table.d.ts +58 -0
  210. package/dist/data-table.js +12 -0
  211. package/dist/data-table.js.map +1 -0
  212. package/dist/date-picker.d.ts +20 -0
  213. package/dist/date-picker.js +5 -0
  214. package/dist/date-picker.js.map +1 -0
  215. package/dist/dialog.d.ts +21 -0
  216. package/dist/dialog.js +5 -0
  217. package/dist/dialog.js.map +1 -0
  218. package/dist/divider.d.ts +12 -0
  219. package/dist/divider.js +5 -0
  220. package/dist/divider.js.map +1 -0
  221. package/dist/docker-stack-card.d.ts +21 -0
  222. package/dist/docker-stack-card.js +6 -0
  223. package/dist/docker-stack-card.js.map +1 -0
  224. package/dist/donut.d.ts +15 -0
  225. package/dist/donut.js +5 -0
  226. package/dist/donut.js.map +1 -0
  227. package/dist/dropdown-menu.d.ts +15 -0
  228. package/dist/dropdown-menu.js +5 -0
  229. package/dist/dropdown-menu.js.map +1 -0
  230. package/dist/empty.d.ts +12 -0
  231. package/dist/empty.js +5 -0
  232. package/dist/empty.js.map +1 -0
  233. package/dist/feature-card.d.ts +11 -0
  234. package/dist/feature-card.js +6 -0
  235. package/dist/feature-card.js.map +1 -0
  236. package/dist/file-upload.d.ts +20 -0
  237. package/dist/file-upload.js +5 -0
  238. package/dist/file-upload.js.map +1 -0
  239. package/dist/footer.d.ts +35 -0
  240. package/dist/footer.js +6 -0
  241. package/dist/footer.js.map +1 -0
  242. package/dist/form-row.d.ts +19 -0
  243. package/dist/form-row.js +5 -0
  244. package/dist/form-row.js.map +1 -0
  245. package/dist/glow-card.d.ts +14 -0
  246. package/dist/glow-card.js +5 -0
  247. package/dist/glow-card.js.map +1 -0
  248. package/dist/hero-block.d.ts +16 -0
  249. package/dist/hero-block.js +7 -0
  250. package/dist/hero-block.js.map +1 -0
  251. package/dist/host-card.d.ts +27 -0
  252. package/dist/host-card.js +6 -0
  253. package/dist/host-card.js.map +1 -0
  254. package/dist/incident-card.d.ts +23 -0
  255. package/dist/incident-card.js +5 -0
  256. package/dist/incident-card.js.map +1 -0
  257. package/dist/index.d.ts +77 -960
  258. package/dist/index.js +69 -3812
  259. package/dist/index.js.map +1 -1
  260. package/dist/input.d.ts +10 -0
  261. package/dist/input.js +5 -0
  262. package/dist/input.js.map +1 -0
  263. package/dist/kbd.d.ts +24 -0
  264. package/dist/kbd.js +5 -0
  265. package/dist/kbd.js.map +1 -0
  266. package/dist/log-viewer.d.ts +35 -0
  267. package/dist/log-viewer.js +5 -0
  268. package/dist/log-viewer.js.map +1 -0
  269. package/dist/meter.d.ts +23 -0
  270. package/dist/meter.js +5 -0
  271. package/dist/meter.js.map +1 -0
  272. package/dist/monogram.d.ts +20 -0
  273. package/dist/monogram.js +5 -0
  274. package/dist/monogram.js.map +1 -0
  275. package/dist/noir-glow-background.d.ts +56 -0
  276. package/dist/noir-glow-background.js +4 -0
  277. package/dist/noir-glow-background.js.map +1 -0
  278. package/dist/pagination.d.ts +16 -0
  279. package/dist/pagination.js +5 -0
  280. package/dist/pagination.js.map +1 -0
  281. package/dist/panel.d.ts +12 -0
  282. package/dist/panel.js +5 -0
  283. package/dist/panel.js.map +1 -0
  284. package/dist/password-input.d.ts +10 -0
  285. package/dist/password-input.js +5 -0
  286. package/dist/password-input.js.map +1 -0
  287. package/dist/pill.d.ts +17 -0
  288. package/dist/pill.js +5 -0
  289. package/dist/pill.js.map +1 -0
  290. package/dist/pricing-card.d.ts +20 -0
  291. package/dist/pricing-card.js +6 -0
  292. package/dist/pricing-card.js.map +1 -0
  293. package/dist/progress.d.ts +6 -0
  294. package/dist/progress.js +5 -0
  295. package/dist/progress.js.map +1 -0
  296. package/dist/radio-group.d.ts +18 -0
  297. package/dist/radio-group.js +5 -0
  298. package/dist/radio-group.js.map +1 -0
  299. package/dist/rollback-plan.d.ts +23 -0
  300. package/dist/rollback-plan.js +5 -0
  301. package/dist/rollback-plan.js.map +1 -0
  302. package/dist/segmented.d.ts +17 -0
  303. package/dist/segmented.js +5 -0
  304. package/dist/segmented.js.map +1 -0
  305. package/dist/select.d.ts +18 -0
  306. package/dist/select.js +5 -0
  307. package/dist/select.js.map +1 -0
  308. package/dist/service-health-card.d.ts +21 -0
  309. package/dist/service-health-card.js +6 -0
  310. package/dist/service-health-card.js.map +1 -0
  311. package/dist/sheet.d.ts +25 -0
  312. package/dist/sheet.js +5 -0
  313. package/dist/sheet.js.map +1 -0
  314. package/dist/skeleton.d.ts +13 -0
  315. package/dist/skeleton.js +5 -0
  316. package/dist/skeleton.js.map +1 -0
  317. package/dist/slider.d.ts +12 -0
  318. package/dist/slider.js +5 -0
  319. package/dist/slider.js.map +1 -0
  320. package/dist/sparkline.d.ts +16 -0
  321. package/dist/sparkline.js +5 -0
  322. package/dist/sparkline.js.map +1 -0
  323. package/dist/stat-card.d.ts +15 -0
  324. package/dist/stat-card.js +5 -0
  325. package/dist/stat-card.js.map +1 -0
  326. package/dist/status-dot.d.ts +13 -0
  327. package/dist/status-dot.js +5 -0
  328. package/dist/status-dot.js.map +1 -0
  329. package/dist/stepper.d.ts +16 -0
  330. package/dist/stepper.js +5 -0
  331. package/dist/stepper.js.map +1 -0
  332. package/dist/switch.d.ts +9 -0
  333. package/dist/switch.js +5 -0
  334. package/dist/switch.js.map +1 -0
  335. package/dist/tabs.d.ts +9 -0
  336. package/dist/tabs.js +5 -0
  337. package/dist/tabs.js.map +1 -0
  338. package/dist/tag-input.d.ts +20 -0
  339. package/dist/tag-input.js +5 -0
  340. package/dist/tag-input.js.map +1 -0
  341. package/dist/textarea.d.ts +10 -0
  342. package/dist/textarea.js +5 -0
  343. package/dist/textarea.js.map +1 -0
  344. package/dist/timeline.d.ts +30 -0
  345. package/dist/timeline.js +5 -0
  346. package/dist/timeline.js.map +1 -0
  347. package/dist/toaster.d.ts +10 -0
  348. package/dist/toaster.js +4 -0
  349. package/dist/toaster.js.map +1 -0
  350. package/dist/tooltip.d.ts +12 -0
  351. package/dist/tooltip.js +5 -0
  352. package/dist/tooltip.js.map +1 -0
  353. package/dist/utils.d.ts +5 -0
  354. package/dist/utils.js +4 -0
  355. package/dist/utils.js.map +1 -0
  356. package/globals-layers.css +1019 -0
  357. package/globals-v3.css +17 -0
  358. package/globals-v4.css +2 -0
  359. package/globals.css +12 -939
  360. package/package.json +85 -17
  361. package/registry.json +936 -0
  362. package/tailwind.css +9 -0
  363. package/tokens.css +20 -0
  364. package/tollerud-avatar-full.png +0 -0
  365. package/dist/index.cjs +0 -3938
  366. package/dist/index.cjs.map +0 -1
  367. package/dist/index.d.cts +0 -960
  368. /package/{tia-full-figure.svg → tollerud-avatar-full.svg} +0 -0
@@ -0,0 +1,94 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef, useState, useMemo } from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var diffStyles = {
7
+ add: "bg-tollerud-success/[0.06] text-tollerud-success hover:bg-tollerud-success/[0.10]",
8
+ remove: "bg-tollerud-error/[0.06] text-tollerud-error hover:bg-tollerud-error/[0.10]",
9
+ context: "text-tollerud-noir-300"
10
+ };
11
+ var diffPrefix = {
12
+ add: "+",
13
+ remove: "-",
14
+ context: " "
15
+ };
16
+ var ActionDiff = forwardRef(
17
+ ({ className, lines, label, view: _view = "unified", loading, ...props }, ref) => {
18
+ const [showContext, setShowContext] = useState(true);
19
+ const stats = useMemo(() => {
20
+ const adds = lines.filter((l) => l.type === "add").length;
21
+ const rems = lines.filter((l) => l.type === "remove").length;
22
+ return { adds, rems };
23
+ }, [lines]);
24
+ const displayLines = showContext ? lines : lines.filter((l) => l.type !== "context");
25
+ const hasContext = lines.some((l) => l.type === "context");
26
+ return /* @__PURE__ */ jsxs(
27
+ "div",
28
+ {
29
+ ref,
30
+ className: cn(
31
+ "rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden",
32
+ loading && "animate-pulse",
33
+ className
34
+ ),
35
+ ...props,
36
+ children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-tollerud-border bg-tollerud-noir-900", children: [
38
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 min-w-0", children: label && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-tollerud-foreground font-mono truncate", children: label }) }),
39
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px]", children: [
40
+ /* @__PURE__ */ jsxs("span", { className: "text-tollerud-success", children: [
41
+ "+",
42
+ stats.adds
43
+ ] }),
44
+ /* @__PURE__ */ jsxs("span", { className: "text-tollerud-error", children: [
45
+ "-",
46
+ stats.rems
47
+ ] }),
48
+ hasContext && /* @__PURE__ */ jsx(
49
+ "button",
50
+ {
51
+ type: "button",
52
+ onClick: () => setShowContext(!showContext),
53
+ className: "text-tollerud-text-muted hover:text-tollerud-foreground transition-colors",
54
+ children: showContext ? "Hide context" : "Show context"
55
+ }
56
+ )
57
+ ] })
58
+ ] }),
59
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto font-mono text-xs leading-relaxed", children: /* @__PURE__ */ jsx("table", { className: "w-full border-collapse", children: /* @__PURE__ */ jsx("tbody", { children: displayLines.map((line, i) => /* @__PURE__ */ jsxs(
60
+ "tr",
61
+ {
62
+ className: cn(
63
+ "transition-colors duration-[100ms]",
64
+ diffStyles[line.type]
65
+ ),
66
+ children: [
67
+ /* @__PURE__ */ jsx("td", { className: cn(
68
+ "w-10 text-right px-2 py-px select-none",
69
+ "text-tollerud-noir-500 border-r border-tollerud-border/30",
70
+ "text-[10px] align-top"
71
+ ), children: line.oldLine ?? "" }),
72
+ /* @__PURE__ */ jsx("td", { className: cn(
73
+ "w-10 text-right px-2 py-px select-none",
74
+ "text-tollerud-noir-500 border-r border-tollerud-border/30",
75
+ "text-[10px] align-top"
76
+ ), children: line.newLine ?? "" }),
77
+ /* @__PURE__ */ jsxs("td", { className: "px-2 py-px whitespace-pre-wrap", children: [
78
+ /* @__PURE__ */ jsx("span", { className: "select-none opacity-50 mr-2", children: diffPrefix[line.type] }),
79
+ line.text
80
+ ] })
81
+ ]
82
+ },
83
+ i
84
+ )) }) }) })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ );
90
+ ActionDiff.displayName = "ActionDiff";
91
+
92
+ export { ActionDiff };
93
+ //# sourceMappingURL=chunk-3XTZPDNV.js.map
94
+ //# sourceMappingURL=chunk-3XTZPDNV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/ActionDiff.tsx"],"names":[],"mappings":"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","file":"chunk-3XTZPDNV.js","sourcesContent":["'use client'\n\nimport { type HTMLAttributes, forwardRef, useMemo, useState } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface DiffLine {\n /** Diff content */\n text: string\n /** Change type */\n type: 'add' | 'remove' | 'context'\n /** Line number in original */\n oldLine?: number\n /** Line number in new */\n newLine?: number\n}\n\nexport interface ActionDiffProps extends HTMLAttributes<HTMLDivElement> {\n /** Diff lines */\n lines: DiffLine[]\n /** File/label name */\n label?: string\n /** View mode */\n view?: 'unified' | 'side-by-side'\n /** Whether the diff is loading */\n loading?: boolean\n}\n\nconst diffStyles = {\n add: 'bg-tollerud-success/[0.06] text-tollerud-success hover:bg-tollerud-success/[0.10]',\n remove: 'bg-tollerud-error/[0.06] text-tollerud-error hover:bg-tollerud-error/[0.10]',\n context: 'text-tollerud-noir-300',\n}\n\nconst diffPrefix = {\n add: '+',\n remove: '-',\n context: ' ',\n}\n\nconst ActionDiff = forwardRef<HTMLDivElement, ActionDiffProps>(\n ({ className, lines, label, view: _view = 'unified', loading, ...props }, ref) => {\n const [showContext, setShowContext] = useState(true)\n\n const stats = useMemo(() => {\n const adds = lines.filter((l) => l.type === 'add').length\n const rems = lines.filter((l) => l.type === 'remove').length\n return { adds, rems }\n }, [lines])\n\n // Filter context lines if collapsed\n const displayLines = showContext ? lines : lines.filter((l) => l.type !== 'context')\n const hasContext = lines.some((l) => l.type === 'context')\n\n return (\n <div\n ref={ref}\n className={cn(\n 'rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden',\n loading && 'animate-pulse',\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-2.5 border-b border-tollerud-border bg-tollerud-noir-900\">\n <div className=\"flex items-center gap-2 min-w-0\">\n {label && (\n <span className=\"text-xs font-medium text-tollerud-foreground font-mono truncate\">{label}</span>\n )}\n </div>\n <div className=\"flex items-center gap-3 text-[11px]\">\n <span className=\"text-tollerud-success\">+{stats.adds}</span>\n <span className=\"text-tollerud-error\">-{stats.rems}</span>\n {hasContext && (\n <button\n type=\"button\"\n onClick={() => setShowContext(!showContext)}\n className=\"text-tollerud-text-muted hover:text-tollerud-foreground transition-colors\"\n >\n {showContext ? 'Hide context' : 'Show context'}\n </button>\n )}\n </div>\n </div>\n\n {/* Diff content */}\n <div className=\"overflow-x-auto font-mono text-xs leading-relaxed\">\n <table className=\"w-full border-collapse\">\n <tbody>\n {displayLines.map((line, i) => (\n <tr\n key={i}\n className={cn(\n 'transition-colors duration-[100ms]',\n diffStyles[line.type]\n )}\n >\n {/* Old line number */}\n <td className={cn(\n 'w-10 text-right px-2 py-px select-none',\n 'text-tollerud-noir-500 border-r border-tollerud-border/30',\n 'text-[10px] align-top'\n )}>\n {line.oldLine ?? ''}\n </td>\n {/* New line number */}\n <td className={cn(\n 'w-10 text-right px-2 py-px select-none',\n 'text-tollerud-noir-500 border-r border-tollerud-border/30',\n 'text-[10px] align-top'\n )}>\n {line.newLine ?? ''}\n </td>\n {/* Prefix + content */}\n <td className=\"px-2 py-px whitespace-pre-wrap\">\n <span className=\"select-none opacity-50 mr-2\">{diffPrefix[line.type]}</span>\n {line.text}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )\n }\n)\nActionDiff.displayName = 'ActionDiff'\n\nexport { ActionDiff }"]}
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
4
+ import { forwardRef } from 'react';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ var DropdownMenu = DropdownMenuPrimitive.Root;
8
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
9
+ var DropdownMenuContent = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
10
+ DropdownMenuPrimitive.Content,
11
+ {
12
+ ref,
13
+ sideOffset,
14
+ className: cn(
15
+ "z-50 min-w-[9rem] overflow-hidden rounded-lg border p-1 shadow-md",
16
+ "bg-tollerud-noir-850 border-tollerud-border/30 text-tollerud-text-primary",
17
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
18
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
19
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
20
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
21
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
22
+ className
23
+ ),
24
+ ...props
25
+ }
26
+ ) }));
27
+ DropdownMenuContent.displayName = "DropdownMenuContent";
28
+ var DropdownMenuItem = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
29
+ DropdownMenuPrimitive.Item,
30
+ {
31
+ ref,
32
+ className: cn(
33
+ "relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none",
34
+ "text-tollerud-text-secondary data-[highlighted]:text-tollerud-text-primary",
35
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
36
+ "data-[highlighted]:bg-tollerud-surface-raised",
37
+ inset && "pl-8",
38
+ className
39
+ ),
40
+ ...props
41
+ }
42
+ ));
43
+ DropdownMenuItem.displayName = "DropdownMenuItem";
44
+ var DropdownMenuSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
45
+ DropdownMenuPrimitive.Separator,
46
+ {
47
+ ref,
48
+ className: cn("-mx-1 my-1 h-px bg-tollerud-border/30", className),
49
+ ...props
50
+ }
51
+ ));
52
+ DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
53
+ var DropdownMenuLabel = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
54
+ DropdownMenuPrimitive.Label,
55
+ {
56
+ ref,
57
+ className: cn("px-2 py-1.5 text-xs font-semibold text-tollerud-text-muted", inset && "pl-8", className),
58
+ ...props
59
+ }
60
+ ));
61
+ DropdownMenuLabel.displayName = "DropdownMenuLabel";
62
+
63
+ export { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger };
64
+ //# sourceMappingURL=chunk-435JHF7G.js.map
65
+ //# sourceMappingURL=chunk-435JHF7G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/DropdownMenu.tsx"],"names":[],"mappings":";;;;;AAQA,IAAM,YAAA,GAAqC,qBAAA,CAAA;AAC3C,IAAM,mBAAA,GAA4C,qBAAA,CAAA;AAElD,IAAM,mBAAA,GAAsB,UAAA,CAG1B,CAAC,EAAE,SAAA,EAAW,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1C,GAAA,CAAuB,8BAAtB,EACC,QAAA,kBAAA,GAAA;AAAA,EAAuB,qBAAA,CAAA,OAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,mEAAA;AAAA,MACA,2EAAA;AAAA,MACA,8DAAA;AAAA,MACA,4DAAA;AAAA,MACA,8DAAA;AAAA,MACA,+EAAA;AAAA,MACA,+EAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CAAA,EACF,CACD;AACD,mBAAA,CAAoB,WAAA,GAAc,qBAAA;AAElC,IAAM,gBAAA,GAAmB,WAKvB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAuB,qBAAA,CAAA,IAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,mGAAA;AAAA,MACA,4EAAA;AAAA,MACA,gEAAA;AAAA,MACA,+CAAA;AAAA,MACA,KAAA,IAAS,MAAA;AAAA,MACT;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,gBAAA,CAAiB,WAAA,GAAc,kBAAA;AAE/B,IAAM,qBAAA,GAAwB,WAG5B,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAuB,qBAAA,CAAA,SAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,uCAAA,EAAyC,SAAS,CAAA;AAAA,IAC/D,GAAG;AAAA;AACN,CACD;AACD,qBAAA,CAAsB,WAAA,GAAc,uBAAA;AAEpC,IAAM,iBAAA,GAAoB,WAKxB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAuB,qBAAA,CAAA,KAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,4DAAA,EAA8D,KAAA,IAAS,QAAQ,SAAS,CAAA;AAAA,IACrG,GAAG;AAAA;AACN,CACD;AACD,iBAAA,CAAkB,WAAA,GAAc,mBAAA","file":"chunk-435JHF7G.js","sourcesContent":["'use client'\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\n/* ──────────────────── DropdownMenu ──────────────────── */\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuContent = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[9rem] overflow-hidden rounded-lg border p-1 shadow-md',\n 'bg-tollerud-noir-850 border-tollerud-border/30 text-tollerud-text-primary',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = 'DropdownMenuContent'\n\nconst DropdownMenuItem = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none',\n 'text-tollerud-text-secondary data-[highlighted]:text-tollerud-text-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n 'data-[highlighted]:bg-tollerud-surface-raised',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuItem.displayName = 'DropdownMenuItem'\n\nconst DropdownMenuSeparator = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-tollerud-border/30', className)}\n {...props}\n />\n))\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator'\n\nconst DropdownMenuLabel = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-xs font-semibold text-tollerud-text-muted', inset && 'pl-8', className)}\n {...props}\n />\n))\nDropdownMenuLabel.displayName = 'DropdownMenuLabel'\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n}"]}
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef } from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var BarChart = forwardRef(
7
+ ({ className, data, height = 180, ...props }, ref) => {
8
+ const max = Math.max(...data.map((d) => d.value), 1);
9
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), ...props, children: [
10
+ /* @__PURE__ */ jsx(
11
+ "div",
12
+ {
13
+ className: "flex items-end gap-2.5 px-1",
14
+ style: { height, borderBottom: "1px solid var(--chart-grid)" },
15
+ children: data.map((d, i) => /* @__PURE__ */ jsxs(
16
+ "div",
17
+ {
18
+ className: "flex flex-1 flex-col items-center justify-end h-full",
19
+ children: [
20
+ /* @__PURE__ */ jsx("span", { className: "mb-1.5 font-mono text-[11px] text-tollerud-text-secondary", children: d.value }),
21
+ /* @__PURE__ */ jsx(
22
+ "div",
23
+ {
24
+ className: cn(
25
+ "w-full max-w-[38px] rounded-t-[3px] transition-[height] duration-500 ease-out",
26
+ d.accent ? "bg-tollerud-yellow" : "bg-tollerud-noir-600"
27
+ ),
28
+ style: { height: `${d.value / max * 100}%` }
29
+ }
30
+ )
31
+ ]
32
+ },
33
+ i
34
+ ))
35
+ }
36
+ ),
37
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2.5 px-1 pt-2", children: data.map((d, i) => /* @__PURE__ */ jsx(
38
+ "div",
39
+ {
40
+ className: "flex-1 text-center text-[11px] text-tollerud-text-muted",
41
+ children: d.label
42
+ },
43
+ i
44
+ )) })
45
+ ] });
46
+ }
47
+ );
48
+ BarChart.displayName = "BarChart";
49
+
50
+ export { BarChart };
51
+ //# sourceMappingURL=chunk-4PA2ACNF.js.map
52
+ //# sourceMappingURL=chunk-4PA2ACNF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/BarChart.tsx"],"names":[],"mappings":";;;;AAcA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,CAAC,EAAE,SAAA,EAAW,IAAA,EAAM,SAAS,GAAA,EAAK,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACpD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA,EAAG,CAAC,CAAA;AAEnD,IAAA,uBACE,IAAA,CAAC,SAAI,GAAA,EAAU,SAAA,EAAW,GAAG,QAAA,EAAU,SAAS,CAAA,EAAI,GAAG,KAAA,EACrD,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,6BAAA;AAAA,UACV,KAAA,EAAO,EAAE,MAAA,EAAQ,YAAA,EAAc,6BAAA,EAA8B;AAAA,UAE5D,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBACZ,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cAEC,SAAA,EAAU,sDAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2DAAA,EACb,QAAA,EAAA,CAAA,CAAE,KAAA,EACL,CAAA;AAAA,gCACA,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,+EAAA;AAAA,sBACA,CAAA,CAAE,SAAS,oBAAA,GAAuB;AAAA,qBACpC;AAAA,oBACA,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAI,EAAE,KAAA,GAAQ,GAAA,GAAO,GAAG,CAAA,CAAA,CAAA;AAAI;AAAA;AAC/C;AAAA,aAAA;AAAA,YAZK;AAAA,WAcR;AAAA;AAAA,OACH;AAAA,sBACA,GAAA,CAAC,SAAI,SAAA,EAAU,wBAAA,EACZ,eAAK,GAAA,CAAI,CAAC,GAAG,CAAA,qBACZ,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,yDAAA;AAAA,UAET,QAAA,EAAA,CAAA,CAAE;AAAA,SAAA;AAAA,QAHE;AAAA,OAKR,CAAA,EACH;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-4PA2ACNF.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface BarChartDatum {\n label: string\n value: number\n accent?: boolean\n}\n\nexport interface BarChartProps extends HTMLAttributes<HTMLDivElement> {\n data: BarChartDatum[]\n height?: number\n}\n\nconst BarChart = forwardRef<HTMLDivElement, BarChartProps>(\n ({ className, data, height = 180, ...props }, ref) => {\n const max = Math.max(...data.map((d) => d.value), 1)\n\n return (\n <div ref={ref} className={cn('w-full', className)} {...props}>\n <div\n className=\"flex items-end gap-2.5 px-1\"\n style={{ height, borderBottom: '1px solid var(--chart-grid)' }}\n >\n {data.map((d, i) => (\n <div\n key={i}\n className=\"flex flex-1 flex-col items-center justify-end h-full\"\n >\n <span className=\"mb-1.5 font-mono text-[11px] text-tollerud-text-secondary\">\n {d.value}\n </span>\n <div\n className={cn(\n 'w-full max-w-[38px] rounded-t-[3px] transition-[height] duration-500 ease-out',\n d.accent ? 'bg-tollerud-yellow' : 'bg-tollerud-noir-600'\n )}\n style={{ height: `${(d.value / max) * 100}%` }}\n />\n </div>\n ))}\n </div>\n <div className=\"flex gap-2.5 px-1 pt-2\">\n {data.map((d, i) => (\n <div\n key={i}\n className=\"flex-1 text-center text-[11px] text-tollerud-text-muted\"\n >\n {d.label}\n </div>\n ))}\n </div>\n </div>\n )\n }\n)\nBarChart.displayName = 'BarChart'\n\nexport { BarChart }\n"]}
@@ -0,0 +1,29 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import * as React from 'react';
4
+ import * as ProgressPrimitive from '@radix-ui/react-progress';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ var Progress = React.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(
8
+ ProgressPrimitive.Root,
9
+ {
10
+ ref,
11
+ className: cn(
12
+ "relative h-2 w-full overflow-hidden rounded-full bg-tollerud-noir-800",
13
+ className
14
+ ),
15
+ ...props,
16
+ children: /* @__PURE__ */ jsx(
17
+ ProgressPrimitive.Indicator,
18
+ {
19
+ className: "h-full w-full flex-1 rounded-full bg-tollerud-yellow transition-all duration-300 ease-in-out",
20
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
21
+ }
22
+ )
23
+ }
24
+ ));
25
+ Progress.displayName = "Progress";
26
+
27
+ export { Progress };
28
+ //# sourceMappingURL=chunk-5GWHUJ5D.js.map
29
+ //# sourceMappingURL=chunk-5GWHUJ5D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Progress.tsx"],"names":[],"mappings":";;;;;AAMA,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAmB,iBAAA,CAAA,IAAA;AAAA,EAAlB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,uEAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,QAAA,kBAAA,GAAA;AAAA,MAAmB,iBAAA,CAAA,SAAA;AAAA,MAAlB;AAAA,QACC,SAAA,EAAU,8FAAA;AAAA,QACV,OAAO,EAAE,SAAA,EAAW,eAAe,GAAA,IAAO,KAAA,IAAS,EAAE,CAAA,EAAA,CAAA;AAAK;AAAA;AAC5D;AACF,CACD;AACD,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-5GWHUJ5D.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as ProgressPrimitive from '@radix-ui/react-progress'\nimport { cn } from '@/lib/utils'\n\nconst Progress = React.forwardRef<\n React.ComponentRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-tollerud-noir-800',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 rounded-full bg-tollerud-yellow transition-all duration-300 ease-in-out\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n))\nProgress.displayName = 'Progress'\n\nexport { Progress }"]}
@@ -0,0 +1,123 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { useId, useRef, useState } from 'react';
4
+ import { Upload, File, X } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function formatBytes(bytes) {
8
+ if (bytes < 1024) return `${bytes} B`;
9
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
10
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
11
+ }
12
+ function FileUpload({
13
+ label,
14
+ description,
15
+ error,
16
+ accept,
17
+ multiple,
18
+ onFilesChange,
19
+ className,
20
+ disabled
21
+ }) {
22
+ const id = useId();
23
+ const inputRef = useRef(null);
24
+ const [files, setFiles] = useState([]);
25
+ const [dragging, setDragging] = useState(false);
26
+ const setAndNotify = (next) => {
27
+ setFiles(next);
28
+ onFilesChange?.(next);
29
+ };
30
+ const addFiles = (incoming) => {
31
+ if (!incoming || incoming.length === 0) return;
32
+ const incomingArr = Array.from(incoming);
33
+ setAndNotify(multiple ? [...files, ...incomingArr] : [incomingArr[0]]);
34
+ };
35
+ const removeAt = (index) => {
36
+ setAndNotify(files.filter((_, i) => i !== index));
37
+ };
38
+ const onDrop = (e) => {
39
+ e.preventDefault();
40
+ setDragging(false);
41
+ if (disabled) return;
42
+ addFiles(e.dataTransfer.files);
43
+ };
44
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
45
+ label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
46
+ /* @__PURE__ */ jsxs(
47
+ "div",
48
+ {
49
+ role: "button",
50
+ tabIndex: disabled ? -1 : 0,
51
+ "aria-disabled": disabled,
52
+ onClick: () => !disabled && inputRef.current?.click(),
53
+ onKeyDown: (e) => {
54
+ if (!disabled && (e.key === "Enter" || e.key === " ")) {
55
+ e.preventDefault();
56
+ inputRef.current?.click();
57
+ }
58
+ },
59
+ onDragOver: (e) => {
60
+ e.preventDefault();
61
+ if (!disabled) setDragging(true);
62
+ },
63
+ onDragLeave: () => setDragging(false),
64
+ onDrop,
65
+ className: cn(
66
+ "flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed px-6 py-8 text-center cursor-pointer transition-colors duration-[150ms]",
67
+ dragging ? "border-tollerud-yellow bg-tollerud-yellow/[0.06]" : "border-tollerud-border bg-tollerud-surface-raised hover:border-tollerud-text-secondary",
68
+ error && "border-tollerud-error",
69
+ disabled && "opacity-50 pointer-events-none"
70
+ ),
71
+ children: [
72
+ /* @__PURE__ */ jsx(Upload, { size: 20, className: "text-tollerud-text-muted" }),
73
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-tollerud-text-secondary", children: [
74
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-tollerud-yellow", children: "Click to upload" }),
75
+ " or drag and drop"
76
+ ] }),
77
+ description && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-text-muted", children: description }),
78
+ /* @__PURE__ */ jsx(
79
+ "input",
80
+ {
81
+ ref: inputRef,
82
+ id,
83
+ type: "file",
84
+ accept,
85
+ multiple,
86
+ disabled,
87
+ onChange: (e) => addFiles(e.target.files),
88
+ className: "sr-only"
89
+ }
90
+ )
91
+ ]
92
+ }
93
+ ),
94
+ files.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: files.map((file, i) => /* @__PURE__ */ jsxs(
95
+ "li",
96
+ {
97
+ className: "flex items-center gap-2.5 rounded-md border border-tollerud-border bg-tollerud-surface-raised px-3 py-2 text-sm",
98
+ children: [
99
+ /* @__PURE__ */ jsx(File, { size: 15, className: "shrink-0 text-tollerud-text-muted" }),
100
+ /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-tollerud-text-primary", children: file.name }),
101
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-tollerud-text-muted", children: formatBytes(file.size) }),
102
+ /* @__PURE__ */ jsx(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ "aria-label": `Remove ${file.name}`,
107
+ onClick: () => removeAt(i),
108
+ className: "shrink-0 text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]",
109
+ children: /* @__PURE__ */ jsx(X, { size: 14 })
110
+ }
111
+ )
112
+ ]
113
+ },
114
+ `${file.name}-${i}`
115
+ )) }),
116
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error", children: error })
117
+ ] });
118
+ }
119
+ FileUpload.displayName = "FileUpload";
120
+
121
+ export { FileUpload };
122
+ //# sourceMappingURL=chunk-6FUKJD3W.js.map
123
+ //# sourceMappingURL=chunk-6FUKJD3W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/FileUpload.tsx"],"names":["FileIcon"],"mappings":"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","file":"chunk-6FUKJD3W.js","sourcesContent":["'use client'\n\nimport { type DragEvent, useId, useRef, useState } from 'react'\nimport { Upload, X, File as FileIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface FileUploadProps {\n label?: string\n description?: React.ReactNode\n error?: string\n /** Forwarded to the underlying `<input accept>` */\n accept?: string\n multiple?: boolean\n /** Called whenever the selected file list changes */\n onFilesChange?: (files: File[]) => void\n className?: string\n disabled?: boolean\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction FileUpload({\n label,\n description,\n error,\n accept,\n multiple,\n onFilesChange,\n className,\n disabled,\n}: FileUploadProps) {\n const id = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n const [files, setFiles] = useState<File[]>([])\n const [dragging, setDragging] = useState(false)\n\n const setAndNotify = (next: File[]) => {\n setFiles(next)\n onFilesChange?.(next)\n }\n\n const addFiles = (incoming: FileList | null) => {\n if (!incoming || incoming.length === 0) return\n const incomingArr = Array.from(incoming)\n setAndNotify(multiple ? [...files, ...incomingArr] : [incomingArr[0]!])\n }\n\n const removeAt = (index: number) => {\n setAndNotify(files.filter((_, i) => i !== index))\n }\n\n const onDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n setDragging(false)\n if (disabled) return\n addFiles(e.dataTransfer.files)\n }\n\n return (\n <div className={cn('flex flex-col gap-1.5', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n onClick={() => !disabled && inputRef.current?.click()}\n onKeyDown={(e) => {\n if (!disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n inputRef.current?.click()\n }\n }}\n onDragOver={(e) => {\n e.preventDefault()\n if (!disabled) setDragging(true)\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={onDrop}\n className={cn(\n 'flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed px-6 py-8 text-center cursor-pointer transition-colors duration-[150ms]',\n dragging\n ? 'border-tollerud-yellow bg-tollerud-yellow/[0.06]'\n : 'border-tollerud-border bg-tollerud-surface-raised hover:border-tollerud-text-secondary',\n error && 'border-tollerud-error',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <Upload size={20} className=\"text-tollerud-text-muted\" />\n <div className=\"text-sm text-tollerud-text-secondary\">\n <span className=\"font-medium text-tollerud-yellow\">Click to upload</span> or drag and drop\n </div>\n {description && <p className=\"text-xs text-tollerud-text-muted\">{description}</p>}\n <input\n ref={inputRef}\n id={id}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n onChange={(e) => addFiles(e.target.files)}\n className=\"sr-only\"\n />\n </div>\n\n {files.length > 0 && (\n <ul className=\"flex flex-col gap-1.5\">\n {files.map((file, i) => (\n <li\n key={`${file.name}-${i}`}\n className=\"flex items-center gap-2.5 rounded-md border border-tollerud-border bg-tollerud-surface-raised px-3 py-2 text-sm\"\n >\n <FileIcon size={15} className=\"shrink-0 text-tollerud-text-muted\" />\n <span className=\"flex-1 truncate text-tollerud-text-primary\">{file.name}</span>\n <span className=\"shrink-0 text-xs text-tollerud-text-muted\">{formatBytes(file.size)}</span>\n <button\n type=\"button\"\n aria-label={`Remove ${file.name}`}\n onClick={() => removeAt(i)}\n className=\"shrink-0 text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]\"\n >\n <X size={14} />\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {error && <p className=\"text-xs text-tollerud-error\">{error}</p>}\n </div>\n )\n}\nFileUpload.displayName = 'FileUpload'\n\nexport { FileUpload }\n"]}
@@ -0,0 +1,106 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { useId, useState } from 'react';
4
+ import { X } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function TagInput({
8
+ value: valueProp,
9
+ defaultValue = [],
10
+ onChange,
11
+ label,
12
+ error,
13
+ placeholder = "Add a tag\u2026",
14
+ max,
15
+ className,
16
+ disabled
17
+ }) {
18
+ const id = useId();
19
+ const isControlled = valueProp !== void 0;
20
+ const [internalTags, setInternalTags] = useState(defaultValue);
21
+ const tags = isControlled ? valueProp : internalTags;
22
+ const [draft, setDraft] = useState("");
23
+ const setAndNotify = (next) => {
24
+ if (!isControlled) setInternalTags(next);
25
+ onChange?.(next);
26
+ };
27
+ const addTag = (raw) => {
28
+ const tag = raw.trim();
29
+ if (!tag || tags.includes(tag)) return;
30
+ if (max && tags.length >= max) return;
31
+ setAndNotify([...tags, tag]);
32
+ setDraft("");
33
+ };
34
+ const removeTag = (index) => {
35
+ setAndNotify(tags.filter((_, i) => i !== index));
36
+ };
37
+ const onKeyDown = (e) => {
38
+ if (e.key === "Enter" || e.key === ",") {
39
+ e.preventDefault();
40
+ addTag(draft);
41
+ } else if (e.key === "Backspace" && draft === "" && tags.length > 0) {
42
+ removeTag(tags.length - 1);
43
+ }
44
+ };
45
+ const atMax = max ? tags.length >= max : false;
46
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
47
+ label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
48
+ /* @__PURE__ */ jsxs(
49
+ "div",
50
+ {
51
+ className: cn(
52
+ "flex flex-wrap items-center gap-1.5 rounded px-2.5 py-1.5",
53
+ "bg-tollerud-surface-raised border",
54
+ "transition-[border-color] duration-[150ms]",
55
+ "focus-within:border-tollerud-yellow focus-within:shadow-[0_0_0_1px_#E8D500]",
56
+ error ? "border-tollerud-error" : "border-tollerud-border",
57
+ disabled && "opacity-50 pointer-events-none"
58
+ ),
59
+ children: [
60
+ tags.map((tag, i) => /* @__PURE__ */ jsxs(
61
+ "span",
62
+ {
63
+ className: "inline-flex items-center gap-1 rounded-full bg-tollerud-surface-hover px-2.5 py-0.5 text-xs font-medium text-tollerud-text-primary",
64
+ children: [
65
+ tag,
66
+ /* @__PURE__ */ jsx(
67
+ "button",
68
+ {
69
+ type: "button",
70
+ "aria-label": `Remove ${tag}`,
71
+ onClick: () => removeTag(i),
72
+ className: "text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]",
73
+ children: /* @__PURE__ */ jsx(X, { size: 12 })
74
+ }
75
+ )
76
+ ]
77
+ },
78
+ `${tag}-${i}`
79
+ )),
80
+ /* @__PURE__ */ jsx(
81
+ "input",
82
+ {
83
+ id,
84
+ value: draft,
85
+ disabled: disabled || atMax,
86
+ onChange: (e) => setDraft(e.target.value),
87
+ onKeyDown,
88
+ onBlur: () => addTag(draft),
89
+ placeholder: atMax ? "" : placeholder,
90
+ className: cn(
91
+ "min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-tollerud-text-primary",
92
+ "placeholder:text-tollerud-text-muted focus:outline-none"
93
+ )
94
+ }
95
+ )
96
+ ]
97
+ }
98
+ ),
99
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
100
+ ] });
101
+ }
102
+ TagInput.displayName = "TagInput";
103
+
104
+ export { TagInput };
105
+ //# sourceMappingURL=chunk-6IS2AYYG.js.map
106
+ //# sourceMappingURL=chunk-6IS2AYYG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/TagInput.tsx"],"names":[],"mappings":"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","file":"chunk-6IS2AYYG.js","sourcesContent":["'use client'\n\nimport { type KeyboardEvent, useId, useState } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface TagInputProps {\n value?: string[]\n defaultValue?: string[]\n onChange?: (tags: string[]) => void\n label?: string\n error?: string\n placeholder?: string\n /** Maximum number of tags allowed */\n max?: number\n className?: string\n disabled?: boolean\n}\n\nfunction TagInput({\n value: valueProp,\n defaultValue = [],\n onChange,\n label,\n error,\n placeholder = 'Add a tag…',\n max,\n className,\n disabled,\n}: TagInputProps) {\n const id = useId()\n const isControlled = valueProp !== undefined\n const [internalTags, setInternalTags] = useState<string[]>(defaultValue)\n const tags = isControlled ? valueProp : internalTags\n const [draft, setDraft] = useState('')\n\n const setAndNotify = (next: string[]) => {\n if (!isControlled) setInternalTags(next)\n onChange?.(next)\n }\n\n const addTag = (raw: string) => {\n const tag = raw.trim()\n if (!tag || tags.includes(tag)) return\n if (max && tags.length >= max) return\n setAndNotify([...tags, tag])\n setDraft('')\n }\n\n const removeTag = (index: number) => {\n setAndNotify(tags.filter((_, i) => i !== index))\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault()\n addTag(draft)\n } else if (e.key === 'Backspace' && draft === '' && tags.length > 0) {\n removeTag(tags.length - 1)\n }\n }\n\n const atMax = max ? tags.length >= max : false\n\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n <div\n className={cn(\n 'flex flex-wrap items-center gap-1.5 rounded px-2.5 py-1.5',\n 'bg-tollerud-surface-raised border',\n 'transition-[border-color] duration-[150ms]',\n 'focus-within:border-tollerud-yellow focus-within:shadow-[0_0_0_1px_#E8D500]',\n error ? 'border-tollerud-error' : 'border-tollerud-border',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n {tags.map((tag, i) => (\n <span\n key={`${tag}-${i}`}\n className=\"inline-flex items-center gap-1 rounded-full bg-tollerud-surface-hover px-2.5 py-0.5 text-xs font-medium text-tollerud-text-primary\"\n >\n {tag}\n <button\n type=\"button\"\n aria-label={`Remove ${tag}`}\n onClick={() => removeTag(i)}\n className=\"text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]\"\n >\n <X size={12} />\n </button>\n </span>\n ))}\n <input\n id={id}\n value={draft}\n disabled={disabled || atMax}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n onBlur={() => addTag(draft)}\n placeholder={atMax ? '' : placeholder}\n className={cn(\n 'min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-tollerud-text-primary',\n 'placeholder:text-tollerud-text-muted focus:outline-none'\n )}\n />\n </div>\n {error && <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>}\n </div>\n )\n}\nTagInput.displayName = 'TagInput'\n\nexport { TagInput }\n"]}
@@ -0,0 +1,78 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef, useId } from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ var AreaChart = forwardRef(
7
+ ({ className, data, height = 180, ...props }, ref) => {
8
+ const gradientId = useId().replace(/:/g, "");
9
+ const w = 520;
10
+ const h = height;
11
+ const pad = 8;
12
+ const max = Math.max(...data) * 1.1;
13
+ const min = Math.min(...data, 0);
14
+ const span = Math.max(data.length - 1, 1);
15
+ const x = (i) => pad + i / span * (w - pad * 2);
16
+ const y = (v) => h - pad - (v - min) / (max - min || 1) * (h - pad * 2);
17
+ const line = data.map((v, i) => `${x(i)},${y(v)}`).join(" ");
18
+ const area = `${pad},${h - pad} ${line} ${w - pad},${h - pad}`;
19
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxs(
20
+ "svg",
21
+ {
22
+ viewBox: `0 0 ${w} ${h}`,
23
+ className: "w-full",
24
+ style: { height },
25
+ preserveAspectRatio: "none",
26
+ role: "img",
27
+ "aria-hidden": "true",
28
+ children: [
29
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
30
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#E8D500", stopOpacity: "0.30" }),
31
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#E8D500", stopOpacity: "0" })
32
+ ] }) }),
33
+ [0.25, 0.5, 0.75].map((g, i) => /* @__PURE__ */ jsx(
34
+ "line",
35
+ {
36
+ x1: pad,
37
+ x2: w - pad,
38
+ y1: h * g,
39
+ y2: h * g,
40
+ stroke: "var(--chart-grid)",
41
+ strokeWidth: "1"
42
+ },
43
+ i
44
+ )),
45
+ /* @__PURE__ */ jsx("polygon", { points: area, fill: `url(#${gradientId})` }),
46
+ /* @__PURE__ */ jsx(
47
+ "polyline",
48
+ {
49
+ points: line,
50
+ fill: "none",
51
+ stroke: "#E8D500",
52
+ strokeWidth: "2",
53
+ strokeLinecap: "round",
54
+ strokeLinejoin: "round"
55
+ }
56
+ ),
57
+ data.map((v, i) => /* @__PURE__ */ jsx(
58
+ "circle",
59
+ {
60
+ cx: x(i),
61
+ cy: y(v),
62
+ r: "2.5",
63
+ fill: "var(--card)",
64
+ stroke: "#E8D500",
65
+ strokeWidth: "1.5"
66
+ },
67
+ i
68
+ ))
69
+ ]
70
+ }
71
+ ) });
72
+ }
73
+ );
74
+ AreaChart.displayName = "AreaChart";
75
+
76
+ export { AreaChart };
77
+ //# sourceMappingURL=chunk-6PZKU6ZL.js.map
78
+ //# sourceMappingURL=chunk-6PZKU6ZL.js.map