@tollerud/ui 1.1.5 → 3.0.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 (360) hide show
  1. package/AGENTS.md +34 -11
  2. package/CHANGELOG.md +376 -0
  3. package/COMPONENTS.md +951 -0
  4. package/GETTING_STARTED.md +159 -0
  5. package/README.md +51 -43
  6. package/SKILL.md +55 -21
  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 +27 -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 +5 -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-3TGMGBKM.js +393 -0
  59. package/dist/chunk-3TGMGBKM.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-7TOT5ME3.js +53 -0
  83. package/dist/chunk-7TOT5ME3.js.map +1 -0
  84. package/dist/chunk-A6L5C3IJ.js +47 -0
  85. package/dist/chunk-A6L5C3IJ.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-AZADSX4Z.js +85 -0
  91. package/dist/chunk-AZADSX4Z.js.map +1 -0
  92. package/dist/chunk-BPCH5LJ3.js +36 -0
  93. package/dist/chunk-BPCH5LJ3.js.map +1 -0
  94. package/dist/chunk-CBQ63EBL.js +85 -0
  95. package/dist/chunk-CBQ63EBL.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-DFM7UUKB.js +79 -0
  101. package/dist/chunk-DFM7UUKB.js.map +1 -0
  102. package/dist/chunk-DGCRHVWW.js +84 -0
  103. package/dist/chunk-DGCRHVWW.js.map +1 -0
  104. package/dist/chunk-DNJI65VQ.js +22 -0
  105. package/dist/chunk-DNJI65VQ.js.map +1 -0
  106. package/dist/chunk-DOUDJU4P.js +63 -0
  107. package/dist/chunk-DOUDJU4P.js.map +1 -0
  108. package/dist/chunk-DRCMGIQ6.js +64 -0
  109. package/dist/chunk-DRCMGIQ6.js.map +1 -0
  110. package/dist/chunk-DZOBXK2S.js +28 -0
  111. package/dist/chunk-DZOBXK2S.js.map +1 -0
  112. package/dist/chunk-EN4OJCEF.js +54 -0
  113. package/dist/chunk-EN4OJCEF.js.map +1 -0
  114. package/dist/chunk-EVHZFYWX.js +33 -0
  115. package/dist/chunk-EVHZFYWX.js.map +1 -0
  116. package/dist/chunk-FGXOV2QH.js +23 -0
  117. package/dist/chunk-FGXOV2QH.js.map +1 -0
  118. package/dist/chunk-G2VKWNZA.js +53 -0
  119. package/dist/chunk-G2VKWNZA.js.map +1 -0
  120. package/dist/chunk-GTM2DE4C.js +156 -0
  121. package/dist/chunk-GTM2DE4C.js.map +1 -0
  122. package/dist/chunk-H3ZVGTJM.js +165 -0
  123. package/dist/chunk-H3ZVGTJM.js.map +1 -0
  124. package/dist/chunk-HWAWUEHC.js +28 -0
  125. package/dist/chunk-HWAWUEHC.js.map +1 -0
  126. package/dist/chunk-HWJVRTWO.js +36 -0
  127. package/dist/chunk-HWJVRTWO.js.map +1 -0
  128. package/dist/chunk-HYQGOC2E.js +79 -0
  129. package/dist/chunk-HYQGOC2E.js.map +1 -0
  130. package/dist/chunk-ILADNTUB.js +77 -0
  131. package/dist/chunk-ILADNTUB.js.map +1 -0
  132. package/dist/chunk-ISHZ6ZPJ.js +31 -0
  133. package/dist/chunk-ISHZ6ZPJ.js.map +1 -0
  134. package/dist/chunk-JRFSUVSO.js +66 -0
  135. package/dist/chunk-JRFSUVSO.js.map +1 -0
  136. package/dist/chunk-KI6OTVID.js +91 -0
  137. package/dist/chunk-KI6OTVID.js.map +1 -0
  138. package/dist/chunk-LUM2YJBH.js +73 -0
  139. package/dist/chunk-LUM2YJBH.js.map +1 -0
  140. package/dist/chunk-NHPISZWS.js +71 -0
  141. package/dist/chunk-NHPISZWS.js.map +1 -0
  142. package/dist/chunk-NOLWJJHT.js +52 -0
  143. package/dist/chunk-NOLWJJHT.js.map +1 -0
  144. package/dist/chunk-NPVINX3Q.js +20 -0
  145. package/dist/chunk-NPVINX3Q.js.map +1 -0
  146. package/dist/chunk-NSMU66ZX.js +47 -0
  147. package/dist/chunk-NSMU66ZX.js.map +1 -0
  148. package/dist/chunk-O57QMLNI.js +68 -0
  149. package/dist/chunk-O57QMLNI.js.map +1 -0
  150. package/dist/chunk-O5SWPHUQ.js +79 -0
  151. package/dist/chunk-O5SWPHUQ.js.map +1 -0
  152. package/dist/chunk-OGVSZ7NV.js +53 -0
  153. package/dist/chunk-OGVSZ7NV.js.map +1 -0
  154. package/dist/chunk-OONIUDST.js +48 -0
  155. package/dist/chunk-OONIUDST.js.map +1 -0
  156. package/dist/chunk-PLF3BBQI.js +139 -0
  157. package/dist/chunk-PLF3BBQI.js.map +1 -0
  158. package/dist/chunk-Q74VRQEX.js +26 -0
  159. package/dist/chunk-Q74VRQEX.js.map +1 -0
  160. package/dist/chunk-QEHTPQHL.js +35 -0
  161. package/dist/chunk-QEHTPQHL.js.map +1 -0
  162. package/dist/chunk-RJTDQOT2.js +73 -0
  163. package/dist/chunk-RJTDQOT2.js.map +1 -0
  164. package/dist/chunk-RQ3RXKAZ.js +203 -0
  165. package/dist/chunk-RQ3RXKAZ.js.map +1 -0
  166. package/dist/chunk-RWJELAS6.js +46 -0
  167. package/dist/chunk-RWJELAS6.js.map +1 -0
  168. package/dist/chunk-RZK2S2OO.js +126 -0
  169. package/dist/chunk-RZK2S2OO.js.map +1 -0
  170. package/dist/chunk-SAP7JSSO.js +106 -0
  171. package/dist/chunk-SAP7JSSO.js.map +1 -0
  172. package/dist/chunk-T3TQPOVM.js +79 -0
  173. package/dist/chunk-T3TQPOVM.js.map +1 -0
  174. package/dist/chunk-T56TTOI6.js +53 -0
  175. package/dist/chunk-T56TTOI6.js.map +1 -0
  176. package/dist/chunk-T7EFDE2L.js +36 -0
  177. package/dist/chunk-T7EFDE2L.js.map +1 -0
  178. package/dist/chunk-V3P5QLLX.js +154 -0
  179. package/dist/chunk-V3P5QLLX.js.map +1 -0
  180. package/dist/chunk-VTRUUT5K.js +31 -0
  181. package/dist/chunk-VTRUUT5K.js.map +1 -0
  182. package/dist/chunk-WDANALHD.js +95 -0
  183. package/dist/chunk-WDANALHD.js.map +1 -0
  184. package/dist/chunk-WSQNPRGN.js +12 -0
  185. package/dist/chunk-WSQNPRGN.js.map +1 -0
  186. package/dist/chunk-XR5QBVEV.js +56 -0
  187. package/dist/chunk-XR5QBVEV.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/code-block.d.ts +14 -0
  193. package/dist/code-block.js +5 -0
  194. package/dist/code-block.js.map +1 -0
  195. package/dist/combobox.d.ts +26 -0
  196. package/dist/combobox.js +5 -0
  197. package/dist/combobox.js.map +1 -0
  198. package/dist/command-menu.d.ts +52 -0
  199. package/dist/command-menu.js +7 -0
  200. package/dist/command-menu.js.map +1 -0
  201. package/dist/container.d.ts +9 -0
  202. package/dist/container.js +5 -0
  203. package/dist/container.js.map +1 -0
  204. package/dist/cta-band.d.ts +12 -0
  205. package/dist/cta-band.js +5 -0
  206. package/dist/cta-band.js.map +1 -0
  207. package/dist/data-table.d.ts +58 -0
  208. package/dist/data-table.js +12 -0
  209. package/dist/data-table.js.map +1 -0
  210. package/dist/date-picker.d.ts +20 -0
  211. package/dist/date-picker.js +5 -0
  212. package/dist/date-picker.js.map +1 -0
  213. package/dist/dialog.d.ts +21 -0
  214. package/dist/dialog.js +5 -0
  215. package/dist/dialog.js.map +1 -0
  216. package/dist/divider.d.ts +12 -0
  217. package/dist/divider.js +5 -0
  218. package/dist/divider.js.map +1 -0
  219. package/dist/docker-stack-card.d.ts +21 -0
  220. package/dist/docker-stack-card.js +6 -0
  221. package/dist/docker-stack-card.js.map +1 -0
  222. package/dist/donut.d.ts +15 -0
  223. package/dist/donut.js +5 -0
  224. package/dist/donut.js.map +1 -0
  225. package/dist/dropdown-menu.d.ts +15 -0
  226. package/dist/dropdown-menu.js +5 -0
  227. package/dist/dropdown-menu.js.map +1 -0
  228. package/dist/empty.d.ts +12 -0
  229. package/dist/empty.js +5 -0
  230. package/dist/empty.js.map +1 -0
  231. package/dist/feature-card.d.ts +11 -0
  232. package/dist/feature-card.js +6 -0
  233. package/dist/feature-card.js.map +1 -0
  234. package/dist/file-upload.d.ts +20 -0
  235. package/dist/file-upload.js +5 -0
  236. package/dist/file-upload.js.map +1 -0
  237. package/dist/footer.d.ts +35 -0
  238. package/dist/footer.js +5 -0
  239. package/dist/footer.js.map +1 -0
  240. package/dist/form-row.d.ts +15 -0
  241. package/dist/form-row.js +5 -0
  242. package/dist/form-row.js.map +1 -0
  243. package/dist/glow-card.d.ts +14 -0
  244. package/dist/glow-card.js +5 -0
  245. package/dist/glow-card.js.map +1 -0
  246. package/dist/hero-block.d.ts +16 -0
  247. package/dist/hero-block.js +7 -0
  248. package/dist/hero-block.js.map +1 -0
  249. package/dist/host-card.d.ts +27 -0
  250. package/dist/host-card.js +6 -0
  251. package/dist/host-card.js.map +1 -0
  252. package/dist/incident-card.d.ts +23 -0
  253. package/dist/incident-card.js +5 -0
  254. package/dist/incident-card.js.map +1 -0
  255. package/dist/index.d.ts +76 -960
  256. package/dist/index.js +68 -3812
  257. package/dist/index.js.map +1 -1
  258. package/dist/input.d.ts +10 -0
  259. package/dist/input.js +5 -0
  260. package/dist/input.js.map +1 -0
  261. package/dist/kbd.d.ts +24 -0
  262. package/dist/kbd.js +5 -0
  263. package/dist/kbd.js.map +1 -0
  264. package/dist/log-viewer.d.ts +35 -0
  265. package/dist/log-viewer.js +5 -0
  266. package/dist/log-viewer.js.map +1 -0
  267. package/dist/meter.d.ts +23 -0
  268. package/dist/meter.js +5 -0
  269. package/dist/meter.js.map +1 -0
  270. package/dist/noir-glow-background.d.ts +50 -0
  271. package/dist/noir-glow-background.js +4 -0
  272. package/dist/noir-glow-background.js.map +1 -0
  273. package/dist/pagination.d.ts +16 -0
  274. package/dist/pagination.js +5 -0
  275. package/dist/pagination.js.map +1 -0
  276. package/dist/panel.d.ts +12 -0
  277. package/dist/panel.js +5 -0
  278. package/dist/panel.js.map +1 -0
  279. package/dist/password-input.d.ts +10 -0
  280. package/dist/password-input.js +5 -0
  281. package/dist/password-input.js.map +1 -0
  282. package/dist/pill.d.ts +14 -0
  283. package/dist/pill.js +5 -0
  284. package/dist/pill.js.map +1 -0
  285. package/dist/pricing-card.d.ts +20 -0
  286. package/dist/pricing-card.js +6 -0
  287. package/dist/pricing-card.js.map +1 -0
  288. package/dist/progress.d.ts +6 -0
  289. package/dist/progress.js +5 -0
  290. package/dist/progress.js.map +1 -0
  291. package/dist/radio-group.d.ts +18 -0
  292. package/dist/radio-group.js +5 -0
  293. package/dist/radio-group.js.map +1 -0
  294. package/dist/rollback-plan.d.ts +23 -0
  295. package/dist/rollback-plan.js +5 -0
  296. package/dist/rollback-plan.js.map +1 -0
  297. package/dist/segmented.d.ts +17 -0
  298. package/dist/segmented.js +5 -0
  299. package/dist/segmented.js.map +1 -0
  300. package/dist/select.d.ts +18 -0
  301. package/dist/select.js +5 -0
  302. package/dist/select.js.map +1 -0
  303. package/dist/service-health-card.d.ts +21 -0
  304. package/dist/service-health-card.js +6 -0
  305. package/dist/service-health-card.js.map +1 -0
  306. package/dist/sheet.d.ts +25 -0
  307. package/dist/sheet.js +5 -0
  308. package/dist/sheet.js.map +1 -0
  309. package/dist/skeleton.d.ts +5 -0
  310. package/dist/skeleton.js +5 -0
  311. package/dist/skeleton.js.map +1 -0
  312. package/dist/slider.d.ts +12 -0
  313. package/dist/slider.js +5 -0
  314. package/dist/slider.js.map +1 -0
  315. package/dist/sparkline.d.ts +16 -0
  316. package/dist/sparkline.js +5 -0
  317. package/dist/sparkline.js.map +1 -0
  318. package/dist/stat-card.d.ts +15 -0
  319. package/dist/stat-card.js +5 -0
  320. package/dist/stat-card.js.map +1 -0
  321. package/dist/status-dot.d.ts +13 -0
  322. package/dist/status-dot.js +5 -0
  323. package/dist/status-dot.js.map +1 -0
  324. package/dist/stepper.d.ts +16 -0
  325. package/dist/stepper.js +5 -0
  326. package/dist/stepper.js.map +1 -0
  327. package/dist/switch.d.ts +9 -0
  328. package/dist/switch.js +5 -0
  329. package/dist/switch.js.map +1 -0
  330. package/dist/tabs.d.ts +9 -0
  331. package/dist/tabs.js +5 -0
  332. package/dist/tabs.js.map +1 -0
  333. package/dist/tag-input.d.ts +20 -0
  334. package/dist/tag-input.js +5 -0
  335. package/dist/tag-input.js.map +1 -0
  336. package/dist/textarea.d.ts +10 -0
  337. package/dist/textarea.js +5 -0
  338. package/dist/textarea.js.map +1 -0
  339. package/dist/timeline.d.ts +30 -0
  340. package/dist/timeline.js +5 -0
  341. package/dist/timeline.js.map +1 -0
  342. package/dist/toaster.d.ts +10 -0
  343. package/dist/toaster.js +4 -0
  344. package/dist/toaster.js.map +1 -0
  345. package/dist/tooltip.d.ts +12 -0
  346. package/dist/tooltip.js +5 -0
  347. package/dist/tooltip.js.map +1 -0
  348. package/dist/utils.d.ts +5 -0
  349. package/dist/utils.js +4 -0
  350. package/dist/utils.js.map +1 -0
  351. package/globals-layers.css +935 -0
  352. package/globals-v3.css +17 -0
  353. package/globals-v4.css +2 -0
  354. package/globals.css +12 -939
  355. package/package.json +82 -16
  356. package/registry.json +920 -0
  357. package/tailwind.css +9 -0
  358. package/dist/index.cjs +0 -3938
  359. package/dist/index.cjs.map +0 -1
  360. package/dist/index.d.cts +0 -960
@@ -0,0 +1,52 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef, useState } from 'react';
4
+ import { EyeOff, Eye } from 'lucide-react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var PasswordInput = forwardRef(
8
+ ({ className, label, error, id, ...props }, ref) => {
9
+ const [visible, setVisible] = useState(false);
10
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
11
+ label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
12
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
13
+ /* @__PURE__ */ jsx(
14
+ "input",
15
+ {
16
+ ref,
17
+ id,
18
+ type: visible ? "text" : "password",
19
+ className: cn(
20
+ "w-full font-sans text-base px-3 py-2 pr-10 rounded",
21
+ "bg-tollerud-surface-raised border",
22
+ "text-tollerud-text-primary",
23
+ "placeholder:text-tollerud-text-muted",
24
+ "transition-[border-color] duration-[150ms]",
25
+ "focus:outline-none focus:border-tollerud-yellow focus:shadow-[0_0_0_1px_#E8D500]",
26
+ error ? "border-tollerud-error" : "border-tollerud-border",
27
+ className
28
+ ),
29
+ ...props
30
+ }
31
+ ),
32
+ /* @__PURE__ */ jsx(
33
+ "button",
34
+ {
35
+ type: "button",
36
+ onClick: () => setVisible((v) => !v),
37
+ "aria-label": visible ? "Hide password" : "Show password",
38
+ "aria-pressed": visible,
39
+ className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-tollerud-text-muted hover:text-tollerud-text-secondary transition-colors duration-[150ms]",
40
+ children: visible ? /* @__PURE__ */ jsx(EyeOff, { size: 16 }) : /* @__PURE__ */ jsx(Eye, { size: 16 })
41
+ }
42
+ )
43
+ ] }),
44
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
45
+ ] });
46
+ }
47
+ );
48
+ PasswordInput.displayName = "PasswordInput";
49
+
50
+ export { PasswordInput };
51
+ //# sourceMappingURL=chunk-NOLWJJHT.js.map
52
+ //# sourceMappingURL=chunk-NOLWJJHT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/PasswordInput.tsx"],"names":[],"mappings":";;;;;AAWA,IAAM,aAAA,GAAgB,UAAA;AAAA,EACpB,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,EAAA,EAAI,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAClD,IAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAE5C,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,MAAA,KAAA,wBACE,OAAA,EAAA,EAAM,OAAA,EAAS,EAAA,EAAI,SAAA,EAAU,gDAC3B,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,sBAEF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,UAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,GAAA;AAAA,YACA,EAAA;AAAA,YACA,IAAA,EAAM,UAAU,MAAA,GAAS,UAAA;AAAA,YACzB,SAAA,EAAW,EAAA;AAAA,cACT,oDAAA;AAAA,cACA,mCAAA;AAAA,cACA,4BAAA;AAAA,cACA,sCAAA;AAAA,cACA,4CAAA;AAAA,cACA,kFAAA;AAAA,cACA,QAAQ,uBAAA,GAA0B,wBAAA;AAAA,cAClC;AAAA,aACF;AAAA,YACC,GAAG;AAAA;AAAA,SACN;AAAA,wBACA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,SAAS,MAAM,UAAA,CAAW,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,YACnC,YAAA,EAAY,UAAU,eAAA,GAAkB,eAAA;AAAA,YACxC,cAAA,EAAc,OAAA;AAAA,YACd,SAAA,EAAU,4IAAA;AAAA,YAET,QAAA,EAAA,OAAA,uBAAW,MAAA,EAAA,EAAO,IAAA,EAAM,IAAI,CAAA,mBAAK,GAAA,CAAC,GAAA,EAAA,EAAI,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA;AACnD,OAAA,EACF,CAAA;AAAA,MACC,KAAA,oBAAS,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sCAAsC,QAAA,EAAA,KAAA,EAAM;AAAA,KAAA,EACrE,CAAA;AAAA,EAEJ;AACF;AACA,aAAA,CAAc,WAAA,GAAc,eAAA","file":"chunk-NOLWJJHT.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useState } from 'react'\nimport { Eye, EyeOff } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface PasswordInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n error?: string\n}\n\nconst PasswordInput = forwardRef<HTMLInputElement, PasswordInputProps>(\n ({ className, label, error, id, ...props }, ref) => {\n const [visible, setVisible] = useState(false)\n\n return (\n <div className=\"flex flex-col gap-1\">\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n <div className=\"relative\">\n <input\n ref={ref}\n id={id}\n type={visible ? 'text' : 'password'}\n className={cn(\n 'w-full font-sans text-base px-3 py-2 pr-10 rounded',\n 'bg-tollerud-surface-raised border',\n 'text-tollerud-text-primary',\n 'placeholder:text-tollerud-text-muted',\n 'transition-[border-color] duration-[150ms]',\n 'focus:outline-none focus:border-tollerud-yellow focus:shadow-[0_0_0_1px_#E8D500]',\n error ? 'border-tollerud-error' : 'border-tollerud-border',\n className\n )}\n {...props}\n />\n <button\n type=\"button\"\n onClick={() => setVisible((v) => !v)}\n aria-label={visible ? 'Hide password' : 'Show password'}\n aria-pressed={visible}\n className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-tollerud-text-muted hover:text-tollerud-text-secondary transition-colors duration-[150ms]\"\n >\n {visible ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {error && <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>}\n </div>\n )\n }\n)\nPasswordInput.displayName = 'PasswordInput'\n\nexport { PasswordInput }\n"]}
@@ -0,0 +1,20 @@
1
+ 'use client';
2
+ import { Card } from './chunk-DZOBXK2S.js';
3
+ import { cn } from './chunk-WSQNPRGN.js';
4
+ import { forwardRef } from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var FeatureCard = forwardRef(
8
+ ({ className, icon, title, description, ...props }, ref) => {
9
+ return /* @__PURE__ */ jsxs(Card, { ref, className: cn("p-5", className), ...props, children: [
10
+ icon && /* @__PURE__ */ jsx("span", { className: "mb-3.5 inline-flex h-[38px] w-[38px] items-center justify-center rounded-[9px] bg-tollerud-yellow/12 text-tollerud-yellow", children: icon }),
11
+ /* @__PURE__ */ jsx("div", { className: "mb-1.5 text-base font-semibold text-tollerud-text-primary", children: title }),
12
+ /* @__PURE__ */ jsx("p", { className: "m-0 text-[13.5px] leading-snug text-tollerud-text-secondary", children: description })
13
+ ] });
14
+ }
15
+ );
16
+ FeatureCard.displayName = "FeatureCard";
17
+
18
+ export { FeatureCard };
19
+ //# sourceMappingURL=chunk-NPVINX3Q.js.map
20
+ //# sourceMappingURL=chunk-NPVINX3Q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/FeatureCard.tsx"],"names":[],"mappings":";;;;;AAUA,IAAM,WAAA,GAAc,UAAA;AAAA,EAClB,CAAC,EAAE,SAAA,EAAW,IAAA,EAAM,OAAO,WAAA,EAAa,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC1D,IAAA,uBACE,IAAA,CAAC,QAAK,GAAA,EAAU,SAAA,EAAW,GAAG,KAAA,EAAO,SAAS,CAAA,EAAI,GAAG,KAAA,EAClD,QAAA,EAAA;AAAA,MAAA,IAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2HAAA,EACb,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,sBAEF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2DAAA,EAA6D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBAClF,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,6DAAA,EACV,QAAA,EAAA,WAAA,EACH;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-NPVINX3Q.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Card } from './Card'\n\nexport interface FeatureCardProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n icon?: React.ReactNode\n title: React.ReactNode\n description: React.ReactNode\n}\n\nconst FeatureCard = forwardRef<HTMLDivElement, FeatureCardProps>(\n ({ className, icon, title, description, ...props }, ref) => {\n return (\n <Card ref={ref} className={cn('p-5', className)} {...props}>\n {icon && (\n <span className=\"mb-3.5 inline-flex h-[38px] w-[38px] items-center justify-center rounded-[9px] bg-tollerud-yellow/12 text-tollerud-yellow\">\n {icon}\n </span>\n )}\n <div className=\"mb-1.5 text-base font-semibold text-tollerud-text-primary\">{title}</div>\n <p className=\"m-0 text-[13.5px] leading-snug text-tollerud-text-secondary\">\n {description}\n </p>\n </Card>\n )\n }\n)\nFeatureCard.displayName = 'FeatureCard'\n\nexport { FeatureCard }\n"]}
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var Segmented = forwardRef(
7
+ ({ className, options, value, onChange, size = "md", ...props }, ref) => {
8
+ return /* @__PURE__ */ jsx(
9
+ "div",
10
+ {
11
+ ref,
12
+ role: "radiogroup",
13
+ className: cn(
14
+ "inline-flex items-center gap-0.5 rounded-lg p-1 bg-tollerud-surface-raised border border-tollerud-border",
15
+ className
16
+ ),
17
+ ...props,
18
+ children: options.map((opt) => {
19
+ const active = opt.value === value;
20
+ return /* @__PURE__ */ jsx(
21
+ "button",
22
+ {
23
+ type: "button",
24
+ role: "radio",
25
+ "aria-checked": active,
26
+ disabled: opt.disabled,
27
+ onClick: () => !opt.disabled && onChange(opt.value),
28
+ className: cn(
29
+ "rounded-md font-medium transition-colors duration-[150ms]",
30
+ size === "sm" ? "px-2.5 py-1 text-xs" : "px-3.5 py-1.5 text-sm",
31
+ active ? "bg-tollerud-yellow text-tollerud-noir-black" : "text-tollerud-text-secondary hover:text-tollerud-text-primary",
32
+ opt.disabled && "opacity-40 pointer-events-none"
33
+ ),
34
+ children: opt.label
35
+ },
36
+ opt.value
37
+ );
38
+ })
39
+ }
40
+ );
41
+ }
42
+ );
43
+ Segmented.displayName = "Segmented";
44
+
45
+ export { Segmented };
46
+ //# sourceMappingURL=chunk-NSMU66ZX.js.map
47
+ //# sourceMappingURL=chunk-NSMU66ZX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Segmented.tsx"],"names":[],"mappings":";;;;AAgBA,IAAM,SAAA,GAAY,UAAA;AAAA,EAChB,CAAC,EAAE,SAAA,EAAW,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,IAAA,GAAO,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACvE,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA,EAAK,YAAA;AAAA,QACL,SAAA,EAAW,EAAA;AAAA,UACT,0GAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAC,GAAA,KAAQ;AACpB,UAAA,MAAM,MAAA,GAAS,IAAI,KAAA,KAAU,KAAA;AAC7B,UAAA,uBACE,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEC,IAAA,EAAK,QAAA;AAAA,cACL,IAAA,EAAK,OAAA;AAAA,cACL,cAAA,EAAc,MAAA;AAAA,cACd,UAAU,GAAA,CAAI,QAAA;AAAA,cACd,SAAS,MAAM,CAAC,IAAI,QAAA,IAAY,QAAA,CAAS,IAAI,KAAK,CAAA;AAAA,cAClD,SAAA,EAAW,EAAA;AAAA,gBACT,2DAAA;AAAA,gBACA,IAAA,KAAS,OAAO,qBAAA,GAAwB,uBAAA;AAAA,gBACxC,SACI,6CAAA,GACA,+DAAA;AAAA,gBACJ,IAAI,QAAA,IAAY;AAAA,eAClB;AAAA,cAEC,QAAA,EAAA,GAAA,CAAI;AAAA,aAAA;AAAA,YAfA,GAAA,CAAI;AAAA,WAgBX;AAAA,QAEJ,CAAC;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;AACA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"chunk-NSMU66ZX.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface SegmentedOption {\n value: string\n label: React.ReactNode\n disabled?: boolean\n}\n\nexport interface SegmentedProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n options: SegmentedOption[]\n value: string\n onChange: (value: string) => void\n size?: 'sm' | 'md'\n}\n\nconst Segmented = forwardRef<HTMLDivElement, SegmentedProps>(\n ({ className, options, value, onChange, size = 'md', ...props }, ref) => {\n return (\n <div\n ref={ref}\n role=\"radiogroup\"\n className={cn(\n 'inline-flex items-center gap-0.5 rounded-lg p-1 bg-tollerud-surface-raised border border-tollerud-border',\n className\n )}\n {...props}\n >\n {options.map((opt) => {\n const active = opt.value === value\n return (\n <button\n key={opt.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n disabled={opt.disabled}\n onClick={() => !opt.disabled && onChange(opt.value)}\n className={cn(\n 'rounded-md font-medium transition-colors duration-[150ms]',\n size === 'sm' ? 'px-2.5 py-1 text-xs' : 'px-3.5 py-1.5 text-sm',\n active\n ? 'bg-tollerud-yellow text-tollerud-noir-black'\n : 'text-tollerud-text-secondary hover:text-tollerud-text-primary',\n opt.disabled && 'opacity-40 pointer-events-none'\n )}\n >\n {opt.label}\n </button>\n )\n })}\n </div>\n )\n }\n)\nSegmented.displayName = 'Segmented'\n\nexport { Segmented }\n"]}
@@ -0,0 +1,68 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef, useId } from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var Switch = forwardRef(
7
+ ({ className, label, id: idProp, checked, ...props }, ref) => {
8
+ const autoId = useId();
9
+ const id = idProp ?? autoId;
10
+ return /* @__PURE__ */ jsxs(
11
+ "label",
12
+ {
13
+ htmlFor: id,
14
+ className: cn(
15
+ "inline-flex items-center gap-2.5 cursor-pointer select-none group",
16
+ "text-sm text-tollerud-text-primary",
17
+ props.disabled && "opacity-40 pointer-events-none cursor-not-allowed",
18
+ className
19
+ ),
20
+ children: [
21
+ /* @__PURE__ */ jsxs(
22
+ "span",
23
+ {
24
+ className: cn(
25
+ "relative inline-flex items-center h-5 w-9 flex-shrink-0 rounded-full",
26
+ "transition-colors duration-200 ease-out",
27
+ checked ? "bg-tollerud-yellow" : "bg-tollerud-noir-600",
28
+ "group-hover:bg-tollerud-noir-500",
29
+ checked && "group-hover:bg-tollerud-yellow-warm",
30
+ "peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow peer-focus-visible:outline-offset-2"
31
+ ),
32
+ children: [
33
+ /* @__PURE__ */ jsx(
34
+ "input",
35
+ {
36
+ ref,
37
+ id,
38
+ type: "checkbox",
39
+ role: "switch",
40
+ checked,
41
+ className: "peer absolute inset-0 opacity-0 w-full h-full cursor-pointer z-10",
42
+ ...props
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsx(
46
+ "span",
47
+ {
48
+ className: cn(
49
+ "block h-3.5 w-3.5 rounded-full shadow-sm",
50
+ "transition-all duration-200 ease-out",
51
+ checked ? "translate-x-[18px] bg-tollerud-black" : "translate-x-[3px] bg-tollerud-white"
52
+ )
53
+ }
54
+ )
55
+ ]
56
+ }
57
+ ),
58
+ label && /* @__PURE__ */ jsx("span", { children: label })
59
+ ]
60
+ }
61
+ );
62
+ }
63
+ );
64
+ Switch.displayName = "Switch";
65
+
66
+ export { Switch };
67
+ //# sourceMappingURL=chunk-O57QMLNI.js.map
68
+ //# sourceMappingURL=chunk-O57QMLNI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Switch.tsx"],"names":[],"mappings":";;;;AASA,IAAM,MAAA,GAAS,UAAA;AAAA,EACb,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,EAAA,EAAI,QAAQ,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC5D,IAAA,MAAM,SAAS,KAAA,EAAM;AACrB,IAAA,MAAM,KAAK,MAAA,IAAU,MAAA;AAErB,IAAA,uBACE,IAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAS,EAAA;AAAA,QACT,SAAA,EAAW,EAAA;AAAA,UACT,mEAAA;AAAA,UACA,oCAAA;AAAA,UACA,MAAM,QAAA,IAAY,mDAAA;AAAA,UAClB;AAAA,SACF;AAAA,QAGA,QAAA,EAAA;AAAA,0BAAA,IAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,EAAA;AAAA,gBACT,sEAAA;AAAA,gBACA,yCAAA;AAAA,gBACA,UAAU,oBAAA,GAAuB,sBAAA;AAAA,gBACjC,kCAAA;AAAA,gBACA,OAAA,IAAW,qCAAA;AAAA,gBACX;AAAA,eACF;AAAA,cAGA,QAAA,EAAA;AAAA,gCAAA,GAAA;AAAA,kBAAC,OAAA;AAAA,kBAAA;AAAA,oBACC,GAAA;AAAA,oBACA,EAAA;AAAA,oBACA,IAAA,EAAK,UAAA;AAAA,oBACL,IAAA,EAAK,QAAA;AAAA,oBACL,OAAA;AAAA,oBACA,SAAA,EAAU,mEAAA;AAAA,oBACT,GAAG;AAAA;AAAA,iBACN;AAAA,gCAEA,GAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,0CAAA;AAAA,sBACA,sCAAA;AAAA,sBACA,UACI,sCAAA,GACA;AAAA;AACN;AAAA;AACF;AAAA;AAAA,WACF;AAAA,UACC,KAAA,oBAAS,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,KACzB;AAAA,EAEJ;AACF;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-O57QMLNI.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n}\n\nconst Switch = forwardRef<HTMLInputElement, SwitchProps>(\n ({ className, label, id: idProp, checked, ...props }, ref) => {\n const autoId = useId()\n const id = idProp ?? autoId\n\n return (\n <label\n htmlFor={id}\n className={cn(\n 'inline-flex items-center gap-2.5 cursor-pointer select-none group',\n 'text-sm text-tollerud-text-primary',\n props.disabled && 'opacity-40 pointer-events-none cursor-not-allowed',\n className\n )}\n >\n {/* Track */}\n <span\n className={cn(\n 'relative inline-flex items-center h-5 w-9 flex-shrink-0 rounded-full',\n 'transition-colors duration-200 ease-out',\n checked ? 'bg-tollerud-yellow' : 'bg-tollerud-noir-600',\n 'group-hover:bg-tollerud-noir-500',\n checked && 'group-hover:bg-tollerud-yellow-warm',\n 'peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow peer-focus-visible:outline-offset-2'\n )}\n >\n {/* Hidden input (peer) */}\n <input\n ref={ref}\n id={id}\n type=\"checkbox\"\n role=\"switch\"\n checked={checked}\n className=\"peer absolute inset-0 opacity-0 w-full h-full cursor-pointer z-10\"\n {...props}\n />\n {/* Thumb */}\n <span\n className={cn(\n 'block h-3.5 w-3.5 rounded-full shadow-sm',\n 'transition-all duration-200 ease-out',\n checked\n ? 'translate-x-[18px] bg-tollerud-black'\n : 'translate-x-[3px] bg-tollerud-white'\n )}\n />\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nSwitch.displayName = 'Switch'\n\nexport { Switch }"]}
@@ -0,0 +1,79 @@
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 Donut = forwardRef(
7
+ ({ className, segments, size = 160, ...props }, ref) => {
8
+ const total = segments.reduce((a, s) => a + s.value, 0) || 1;
9
+ const r = size / 2 - 14;
10
+ const c = 2 * Math.PI * r;
11
+ let offset = 0;
12
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex items-center gap-6", className), ...props, children: [
13
+ /* @__PURE__ */ jsxs(
14
+ "svg",
15
+ {
16
+ width: size,
17
+ height: size,
18
+ viewBox: `0 0 ${size} ${size}`,
19
+ className: "-rotate-90",
20
+ role: "img",
21
+ "aria-hidden": "true",
22
+ children: [
23
+ /* @__PURE__ */ jsx(
24
+ "circle",
25
+ {
26
+ cx: size / 2,
27
+ cy: size / 2,
28
+ r,
29
+ fill: "none",
30
+ stroke: "var(--muted)",
31
+ strokeWidth: "14"
32
+ }
33
+ ),
34
+ segments.map((s, i) => {
35
+ const len = s.value / total * c;
36
+ const gap = len > 10 ? 4 : 0;
37
+ const el = /* @__PURE__ */ jsx(
38
+ "circle",
39
+ {
40
+ cx: size / 2,
41
+ cy: size / 2,
42
+ r,
43
+ fill: "none",
44
+ stroke: s.color,
45
+ strokeWidth: "14",
46
+ strokeDasharray: `${Math.max(0.1, len - gap)} ${c - (len - gap)}`,
47
+ strokeDashoffset: -offset,
48
+ strokeLinecap: "butt"
49
+ },
50
+ i
51
+ );
52
+ offset += len;
53
+ return el;
54
+ })
55
+ ]
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: segments.map((s, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-[13px]", children: [
59
+ /* @__PURE__ */ jsx(
60
+ "span",
61
+ {
62
+ className: "h-2.5 w-2.5 shrink-0 rounded-[3px]",
63
+ style: { background: s.color }
64
+ }
65
+ ),
66
+ /* @__PURE__ */ jsx("span", { className: "min-w-[70px] text-tollerud-text-primary", children: s.label }),
67
+ /* @__PURE__ */ jsxs("span", { className: "font-mono text-tollerud-text-muted", children: [
68
+ Math.round(s.value / total * 100),
69
+ "%"
70
+ ] })
71
+ ] }, i)) })
72
+ ] });
73
+ }
74
+ );
75
+ Donut.displayName = "Donut";
76
+
77
+ export { Donut };
78
+ //# sourceMappingURL=chunk-O5SWPHUQ.js.map
79
+ //# sourceMappingURL=chunk-O5SWPHUQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Donut.tsx"],"names":[],"mappings":"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","file":"chunk-O5SWPHUQ.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface DonutSegment {\n label: string\n value: number\n color: string\n}\n\nexport interface DonutProps extends HTMLAttributes<HTMLDivElement> {\n segments: DonutSegment[]\n size?: number\n}\n\nconst Donut = forwardRef<HTMLDivElement, DonutProps>(\n ({ className, segments, size = 160, ...props }, ref) => {\n const total = segments.reduce((a, s) => a + s.value, 0) || 1\n const r = size / 2 - 14\n const c = 2 * Math.PI * r\n let offset = 0\n\n return (\n <div ref={ref} className={cn('flex items-center gap-6', className)} {...props}>\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n className=\"-rotate-90\"\n role=\"img\"\n aria-hidden=\"true\"\n >\n <circle\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke=\"var(--muted)\"\n strokeWidth=\"14\"\n />\n {segments.map((s, i) => {\n const len = (s.value / total) * c\n const gap = len > 10 ? 4 : 0\n const el = (\n <circle\n key={i}\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke={s.color}\n strokeWidth=\"14\"\n strokeDasharray={`${Math.max(0.1, len - gap)} ${c - (len - gap)}`}\n strokeDashoffset={-offset}\n strokeLinecap=\"butt\"\n />\n )\n offset += len\n return el\n })}\n </svg>\n <div className=\"flex flex-col gap-2\">\n {segments.map((s, i) => (\n <div key={i} className=\"flex items-center gap-2 text-[13px]\">\n <span\n className=\"h-2.5 w-2.5 shrink-0 rounded-[3px]\"\n style={{ background: s.color }}\n />\n <span className=\"min-w-[70px] text-tollerud-text-primary\">{s.label}</span>\n <span className=\"font-mono text-tollerud-text-muted\">\n {Math.round((s.value / total) * 100)}%\n </span>\n </div>\n ))}\n </div>\n </div>\n )\n }\n)\nDonut.displayName = 'Donut'\n\nexport { Donut }\n"]}
@@ -0,0 +1,53 @@
1
+ 'use client';
2
+ import { Kbd } from './chunk-HWAWUEHC.js';
3
+ import { cn } from './chunk-WSQNPRGN.js';
4
+ import { forwardRef } from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ var ActionRow = forwardRef(
8
+ ({
9
+ action,
10
+ highlighted = false,
11
+ showShortcut = true,
12
+ className,
13
+ disabled,
14
+ onClick,
15
+ ...props
16
+ }, ref) => {
17
+ return /* @__PURE__ */ jsxs(
18
+ "button",
19
+ {
20
+ ref,
21
+ type: "button",
22
+ disabled: disabled ?? action.disabled,
23
+ onClick: (e) => {
24
+ onClick?.(e);
25
+ action.onSelect?.();
26
+ },
27
+ className: cn(
28
+ "tollerud-action-row",
29
+ highlighted && "tollerud-action-row--highlighted",
30
+ (disabled ?? action.disabled) && "tollerud-action-row--disabled",
31
+ className
32
+ ),
33
+ role: "option",
34
+ "aria-selected": highlighted,
35
+ "aria-disabled": disabled ?? action.disabled,
36
+ ...props,
37
+ children: [
38
+ action.icon && /* @__PURE__ */ jsx("span", { className: "tollerud-action-row__icon", children: action.icon }),
39
+ /* @__PURE__ */ jsxs("span", { className: "tollerud-action-row__content", children: [
40
+ /* @__PURE__ */ jsx("span", { className: "tollerud-action-row__label", children: action.label }),
41
+ action.description && /* @__PURE__ */ jsx("span", { className: "tollerud-action-row__description", children: action.description })
42
+ ] }),
43
+ showShortcut && action.shortcut && /* @__PURE__ */ jsx("span", { className: "tollerud-action-row__shortcut", children: /* @__PURE__ */ jsx(Kbd, { keys: action.shortcut, size: "sm" }) })
44
+ ]
45
+ }
46
+ );
47
+ }
48
+ );
49
+ ActionRow.displayName = "ActionRow";
50
+
51
+ export { ActionRow };
52
+ //# sourceMappingURL=chunk-OGVSZ7NV.js.map
53
+ //# sourceMappingURL=chunk-OGVSZ7NV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/ActionRow.tsx"],"names":[],"mappings":";;;;;AAuCA,IAAM,SAAA,GAAY,UAAA;AAAA,EAChB,CACE;AAAA,IACE,MAAA;AAAA,IACA,WAAA,GAAc,KAAA;AAAA,IACd,YAAA,GAAe,IAAA;AAAA,IACf,SAAA;AAAA,IACA,QAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,uBACE,IAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,IAAA,EAAK,QAAA;AAAA,QACL,QAAA,EAAU,YAAY,MAAA,CAAO,QAAA;AAAA,QAC7B,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,UAAA,OAAA,GAAU,CAAC,CAAA;AACX,UAAA,MAAA,CAAO,QAAA,IAAW;AAAA,QACpB,CAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,qBAAA;AAAA,UACA,WAAA,IAAe,kCAAA;AAAA,UAAA,CACd,QAAA,IAAY,OAAO,QAAA,KAAa,+BAAA;AAAA,UACjC;AAAA,SACF;AAAA,QACA,IAAA,EAAK,QAAA;AAAA,QACL,eAAA,EAAe,WAAA;AAAA,QACf,eAAA,EAAe,YAAY,MAAA,CAAO,QAAA;AAAA,QACjC,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA;AAAA,UAAA,MAAA,CAAO,wBACN,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2BAAA,EAA6B,iBAAO,IAAA,EAAK,CAAA;AAAA,0BAG3D,IAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,8BAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,4BAAA,EAA8B,QAAA,EAAA,MAAA,CAAO,KAAA,EAAM,CAAA;AAAA,YAC1D,OAAO,WAAA,oBACN,GAAA,CAAC,UAAK,SAAA,EAAU,kCAAA,EACb,iBAAO,WAAA,EACV;AAAA,WAAA,EAEJ,CAAA;AAAA,UAEC,YAAA,IAAgB,MAAA,CAAO,QAAA,oBACtB,GAAA,CAAC,UAAK,SAAA,EAAU,+BAAA,EACd,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAI,IAAA,EAAM,MAAA,CAAO,QAAA,EAAU,IAAA,EAAK,MAAK,CAAA,EACxC;AAAA;AAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AACA,SAAA,CAAU,WAAA,GAAc,WAAA","file":"chunk-OGVSZ7NV.js","sourcesContent":["\"use client\"\n\nimport { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport { Kbd } from './Kbd'\n\nexport interface ActionItem {\n /** Unique ID */\n id: string\n /** Label text */\n label: string\n /** Subtitle / description */\n description?: string\n /** Optional icon element */\n icon?: React.ReactNode\n /** Keyboard shortcut */\n shortcut?: string | string[]\n /** Group this item belongs to */\n group?: string\n /** When true, item is disabled */\n disabled?: boolean\n /** Selection callback */\n onSelect?: () => void\n}\n\nexport interface ActionRowProps\n extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onSelect'> {\n /** Action data */\n action: ActionItem\n /** Whether this row is currently highlighted (keyboard navigation) */\n highlighted?: boolean\n /** Whether to show the shortcut */\n showShortcut?: boolean\n}\n\n/**\n * Action row — a single command/action item in a list or command menu.\n * Inspired by Raycast's compact action layout.\n */\nconst ActionRow = forwardRef<HTMLButtonElement, ActionRowProps>(\n (\n {\n action,\n highlighted = false,\n showShortcut = true,\n className,\n disabled,\n onClick,\n ...props\n },\n ref\n ) => {\n return (\n <button\n ref={ref}\n type=\"button\"\n disabled={disabled ?? action.disabled}\n onClick={(e) => {\n onClick?.(e)\n action.onSelect?.()\n }}\n className={cn(\n 'tollerud-action-row',\n highlighted && 'tollerud-action-row--highlighted',\n (disabled ?? action.disabled) && 'tollerud-action-row--disabled',\n className\n )}\n role=\"option\"\n aria-selected={highlighted}\n aria-disabled={disabled ?? action.disabled}\n {...props}\n >\n {action.icon && (\n <span className=\"tollerud-action-row__icon\">{action.icon}</span>\n )}\n\n <span className=\"tollerud-action-row__content\">\n <span className=\"tollerud-action-row__label\">{action.label}</span>\n {action.description && (\n <span className=\"tollerud-action-row__description\">\n {action.description}\n </span>\n )}\n </span>\n\n {showShortcut && action.shortcut && (\n <span className=\"tollerud-action-row__shortcut\">\n <Kbd keys={action.shortcut} size=\"sm\" />\n </span>\n )}\n </button>\n )\n }\n)\nActionRow.displayName = 'ActionRow'\n\nexport { ActionRow }"]}
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { forwardRef, useId } from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ var Slider = forwardRef(
7
+ ({ className, label, showValue, id: idProp, value, defaultValue, min = 0, max = 100, onChange, ...props }, ref) => {
8
+ const autoId = useId();
9
+ const id = idProp ?? autoId;
10
+ const current = value ?? defaultValue ?? min;
11
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
12
+ (label || showValue) && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-xs", children: [
13
+ label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "font-medium text-tollerud-text-muted", children: label }),
14
+ showValue && /* @__PURE__ */ jsx("span", { className: "text-tollerud-text-secondary tabular-nums", children: current })
15
+ ] }),
16
+ /* @__PURE__ */ jsx(
17
+ "input",
18
+ {
19
+ ref,
20
+ id,
21
+ type: "range",
22
+ min,
23
+ max,
24
+ value,
25
+ defaultValue,
26
+ onChange: (e) => onChange?.(Number(e.target.value)),
27
+ className: cn(
28
+ "h-1.5 w-full cursor-pointer appearance-none rounded-full bg-tollerud-surface-raised accent-tollerud-yellow",
29
+ "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4",
30
+ "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-tollerud-yellow [&::-webkit-slider-thumb]:cursor-pointer",
31
+ "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-tollerud-noir-black",
32
+ "[&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full",
33
+ "[&::-moz-range-thumb]:bg-tollerud-yellow [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-tollerud-noir-black [&::-moz-range-thumb]:cursor-pointer",
34
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tollerud-yellow/50",
35
+ "disabled:opacity-40 disabled:pointer-events-none",
36
+ className
37
+ ),
38
+ ...props
39
+ }
40
+ )
41
+ ] });
42
+ }
43
+ );
44
+ Slider.displayName = "Slider";
45
+
46
+ export { Slider };
47
+ //# sourceMappingURL=chunk-OONIUDST.js.map
48
+ //# sourceMappingURL=chunk-OONIUDST.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/Slider.tsx"],"names":[],"mappings":";;;;AAYA,IAAM,MAAA,GAAS,UAAA;AAAA,EACb,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,SAAA,EAAW,IAAI,MAAA,EAAQ,KAAA,EAAO,YAAA,EAAc,GAAA,GAAM,GAAG,GAAA,GAAM,GAAA,EAAK,UAAU,GAAG,KAAA,IAAS,GAAA,KAAQ;AACjH,IAAA,MAAM,SAAS,KAAA,EAAM;AACrB,IAAA,MAAM,KAAK,MAAA,IAAU,MAAA;AACrB,IAAA,MAAM,OAAA,GAAU,SAAS,YAAA,IAAgB,GAAA;AAEzC,IAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EACX,QAAA,EAAA;AAAA,MAAA,CAAA,KAAA,IAAS,SAAA,qBACT,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2CAAA,EACZ,QAAA,EAAA;AAAA,QAAA,KAAA,wBACE,OAAA,EAAA,EAAM,OAAA,EAAS,EAAA,EAAI,SAAA,EAAU,wCAC3B,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,QAED,SAAA,oBAAa,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,6CAA6C,QAAA,EAAA,OAAA,EAAQ;AAAA,OAAA,EACrF,CAAA;AAAA,sBAEF,GAAA;AAAA,QAAC,OAAA;AAAA,QAAA;AAAA,UACC,GAAA;AAAA,UACA,EAAA;AAAA,UACA,IAAA,EAAK,OAAA;AAAA,UACL,GAAA;AAAA,UACA,GAAA;AAAA,UACA,KAAA;AAAA,UACA,YAAA;AAAA,UACA,QAAA,EAAU,CAAC,CAAA,KAAM,QAAA,GAAW,OAAO,CAAA,CAAE,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,UAClD,SAAA,EAAW,EAAA;AAAA,YACT,4GAAA;AAAA,YACA,uGAAA;AAAA,YACA,8HAAA;AAAA,YACA,yFAAA;AAAA,YACA,wFAAA;AAAA,YACA,+JAAA;AAAA,YACA,uFAAA;AAAA,YACA,kDAAA;AAAA,YACA;AAAA,WACF;AAAA,UACC,GAAG;AAAA;AAAA;AACN,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-OONIUDST.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'onChange'> {\n label?: string\n /** Show the current numeric value next to the label */\n showValue?: boolean\n onChange?: (value: number) => void\n}\n\nconst Slider = forwardRef<HTMLInputElement, SliderProps>(\n ({ className, label, showValue, id: idProp, value, defaultValue, min = 0, max = 100, onChange, ...props }, ref) => {\n const autoId = useId()\n const id = idProp ?? autoId\n const current = value ?? defaultValue ?? min\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n {(label || showValue) && (\n <div className=\"flex items-center justify-between text-xs\">\n {label && (\n <label htmlFor={id} className=\"font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n {showValue && <span className=\"text-tollerud-text-secondary tabular-nums\">{current}</span>}\n </div>\n )}\n <input\n ref={ref}\n id={id}\n type=\"range\"\n min={min}\n max={max}\n value={value}\n defaultValue={defaultValue}\n onChange={(e) => onChange?.(Number(e.target.value))}\n className={cn(\n 'h-1.5 w-full cursor-pointer appearance-none rounded-full bg-tollerud-surface-raised accent-tollerud-yellow',\n '[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:h-4 [&::-webkit-slider-thumb]:w-4',\n '[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-tollerud-yellow [&::-webkit-slider-thumb]:cursor-pointer',\n '[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-tollerud-noir-black',\n '[&::-moz-range-thumb]:h-4 [&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:rounded-full',\n '[&::-moz-range-thumb]:bg-tollerud-yellow [&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-tollerud-noir-black [&::-moz-range-thumb]:cursor-pointer',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tollerud-yellow/50',\n 'disabled:opacity-40 disabled:pointer-events-none',\n className\n )}\n {...props}\n />\n </div>\n )\n }\n)\nSlider.displayName = 'Slider'\n\nexport { Slider }\n"]}
@@ -0,0 +1,139 @@
1
+ 'use client';
2
+ import { cn } from './chunk-WSQNPRGN.js';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ function BentoDashboard({
6
+ title,
7
+ hosts = [],
8
+ metrics = [],
9
+ services = [],
10
+ incidents = [],
11
+ className
12
+ }) {
13
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
14
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { children: [
15
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-tollerud-text-primary", children: title }),
16
+ /* @__PURE__ */ jsxs("p", { className: "text-xs text-tollerud-text-muted", children: [
17
+ hosts.length,
18
+ " hosts \xB7 ",
19
+ services.length,
20
+ " services",
21
+ incidents.length > 0 && ` \xB7 ${incidents.length} active incident${incidents.length > 1 ? "s" : ""}`
22
+ ] })
23
+ ] }) }),
24
+ hosts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
25
+ /* @__PURE__ */ jsx("div", { className: "md:col-span-2 lg:col-span-1", children: /* @__PURE__ */ jsx(HostCardComponent, { host: hosts[0] }) }),
26
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-3 md:col-span-2 lg:col-span-1", children: hosts.slice(1).map((h, i) => /* @__PURE__ */ jsx(HostCardComponent, { host: h }, h.hostname ?? i)) })
27
+ ] }),
28
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-3", children: [
29
+ metrics.length > 0 && /* @__PURE__ */ jsxs("div", { className: "lg:col-span-2", children: [
30
+ /* @__PURE__ */ jsx(SectionLabel, { children: "Metrics" }),
31
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-2", children: metrics.map((m, i) => /* @__PURE__ */ jsx(StatCardComponent, { stat: m }, m.label ?? i)) })
32
+ ] }),
33
+ services.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
34
+ /* @__PURE__ */ jsx(SectionLabel, { children: "Services" }),
35
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: services.slice(0, 4).map((s, i) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3", children: [
36
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
37
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-tollerud-text-primary", children: s.service }),
38
+ /* @__PURE__ */ jsx("span", { className: cn(
39
+ "text-xs px-1.5 py-0.5 rounded-full font-medium",
40
+ s.status === "online" && "text-tollerud-accent bg-tollerud-accent/10",
41
+ s.status === "warning" && "text-tollerud-warning bg-tollerud-warning/10",
42
+ s.status === "offline" && "text-tollerud-error bg-tollerud-error/10",
43
+ s.status === "idle" && "text-tollerud-text-muted bg-tollerud-noir-800"
44
+ ), children: s.status })
45
+ ] }),
46
+ s.responseTime && /* @__PURE__ */ jsxs("p", { className: "text-xs text-tollerud-text-muted mt-1", children: [
47
+ s.responseTime,
48
+ " response"
49
+ ] })
50
+ ] }, s.service ?? i)) })
51
+ ] })
52
+ ] }),
53
+ incidents.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
54
+ /* @__PURE__ */ jsx(SectionLabel, { children: "Recent Incidents" }),
55
+ /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: incidents.slice(0, 4).map((inc, i) => /* @__PURE__ */ jsx(IncidentCardItem, { incident: inc }, inc.title + i)) })
56
+ ] })
57
+ ] });
58
+ }
59
+ function SectionLabel({ children }) {
60
+ return /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider mb-2", children });
61
+ }
62
+ function HostCardComponent({ host }) {
63
+ return /* @__PURE__ */ jsxs("div", { className: cn(
64
+ "rounded-xl border p-4",
65
+ host.status === "online" ? "border-tollerud-border/30 bg-tollerud-surface" : host.status === "warning" ? "border-tollerud-warning/30 bg-tollerud-warning/5" : "border-tollerud-border/20 bg-tollerud-surface opacity-70"
66
+ ), children: [
67
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
68
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
69
+ /* @__PURE__ */ jsx(StatusDotComp, { status: host.status }),
70
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-tollerud-text-primary", children: host.hostname })
71
+ ] }),
72
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-tollerud-text-muted font-mono", children: host.ip })
73
+ ] }),
74
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 text-xs", children: [
75
+ host.cpu && /* @__PURE__ */ jsx(MetricBadge, { label: "CPU", value: host.cpu }),
76
+ host.memory && /* @__PURE__ */ jsx(MetricBadge, { label: "Mem", value: host.memory }),
77
+ host.disk && /* @__PURE__ */ jsx(MetricBadge, { label: "Disk", value: host.disk }),
78
+ host.uptime && /* @__PURE__ */ jsx(MetricBadge, { label: "Up", value: host.uptime })
79
+ ] })
80
+ ] });
81
+ }
82
+ function StatCardComponent({ stat }) {
83
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3", children: [
84
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-text-muted", children: stat.label }),
85
+ /* @__PURE__ */ jsx("p", { className: "text-lg font-semibold text-tollerud-text-primary mt-0.5", children: stat.value }),
86
+ stat.change && /* @__PURE__ */ jsx("span", { className: cn(
87
+ "text-xs font-medium",
88
+ stat.change.direction === "up" ? "text-tollerud-accent" : "text-tollerud-error"
89
+ ), children: stat.change.value })
90
+ ] });
91
+ }
92
+ function IncidentCardItem({ incident }) {
93
+ return /* @__PURE__ */ jsxs("div", { className: cn(
94
+ "flex items-start gap-3 rounded-lg border p-3",
95
+ incident.acknowledged ? "border-tollerud-border/10 bg-tollerud-noir-900/50 opacity-60" : "border-tollerud-border/20 bg-tollerud-surface"
96
+ ), children: [
97
+ /* @__PURE__ */ jsx(SeverityDot, { severity: incident.severity }),
98
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
99
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
100
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-tollerud-text-primary truncate", children: incident.title }),
101
+ incident.acknowledged && /* @__PURE__ */ jsx("span", { className: "text-xs text-tollerud-text-muted", children: "(acknowledged)" })
102
+ ] }),
103
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-tollerud-text-muted mt-0.5", children: [
104
+ /* @__PURE__ */ jsx("span", { children: incident.service }),
105
+ /* @__PURE__ */ jsx("span", { children: "\xB7" }),
106
+ /* @__PURE__ */ jsx("span", { children: incident.timestamp })
107
+ ] }),
108
+ incident.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-text-secondary mt-1", children: incident.description })
109
+ ] })
110
+ ] });
111
+ }
112
+ function StatusDotComp({ status }) {
113
+ return /* @__PURE__ */ jsx("span", { className: cn(
114
+ "inline-block w-2 h-2 rounded-full",
115
+ status === "online" && "bg-tollerud-accent shadow-[0_0_4px_var(--tollerud-accent)]",
116
+ status === "warning" && "bg-tollerud-warning",
117
+ status === "offline" && "bg-tollerud-error"
118
+ ) });
119
+ }
120
+ function SeverityDot({ severity }) {
121
+ return /* @__PURE__ */ jsx("span", { className: cn(
122
+ "inline-block w-2 h-2 rounded-full mt-1 shrink-0",
123
+ severity === "critical" && "bg-tollerud-error shadow-[0_0_4px_var(--tollerud-error)]",
124
+ severity === "high" && "bg-tollerud-warning",
125
+ severity === "medium" && "bg-tollerud-accent",
126
+ severity === "low" && "bg-tollerud-text-muted",
127
+ severity === "info" && "bg-tollerud-info"
128
+ ) });
129
+ }
130
+ function MetricBadge({ label, value }) {
131
+ return /* @__PURE__ */ jsxs("div", { className: "rounded bg-tollerud-noir-800 px-2 py-1.5", children: [
132
+ /* @__PURE__ */ jsx("span", { className: "text-tollerud-text-muted", children: label }),
133
+ /* @__PURE__ */ jsx("span", { className: "float-right text-tollerud-text-primary font-mono", children: value })
134
+ ] });
135
+ }
136
+
137
+ export { BentoDashboard };
138
+ //# sourceMappingURL=chunk-PLF3BBQI.js.map
139
+ //# sourceMappingURL=chunk-PLF3BBQI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../components/BentoDashboard.tsx"],"names":[],"mappings":"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","file":"chunk-PLF3BBQI.js","sourcesContent":["'use client'\n\nimport { type ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\nimport type { HostCardProps } from './HostCard'\nimport type { StatCardProps } from './StatCard'\nimport type { ServiceHealthCardProps } from './ServiceHealthCard'\nimport type { IncidentSeverity } from './IncidentCard'\nimport type { BackupJob } from './BackupStatusPanel'\n\n/* ──────────────────── Bento Grid Dashboard Template ──────────────────── */\n\nexport interface BentoDashboardProps {\n title: string\n hosts?: HostCardProps[]\n metrics?: StatCardProps[]\n services?: ServiceHealthCardProps[]\n incidents?: { title: string; severity: IncidentSeverity; timestamp: string; service: string; description?: string; acknowledged?: boolean }[]\n backupJobs?: BackupJob[]\n className?: string\n /** Render the incident list footer */\n renderIncidentFooter?: () => ReactNode\n}\n\nexport function BentoDashboard({\n title,\n hosts = [],\n metrics = [],\n services = [],\n incidents = [],\n className,\n}: BentoDashboardProps) {\n return (\n <div className={cn('space-y-4', className)}>\n {/* Title bar */}\n <div className=\"flex items-center justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-tollerud-text-primary\">{title}</h2>\n <p className=\"text-xs text-tollerud-text-muted\">\n {hosts.length} hosts · {services.length} services\n {incidents.length > 0 && ` · ${incidents.length} active incident${incidents.length > 1 ? 's' : ''}`}\n </p>\n </div>\n </div>\n\n {/* Row 1: Host cards — bento asymmetric */}\n {hosts.length > 0 && (\n <div className=\"grid grid-cols-1 md:grid-cols-2 gap-3\">\n {/* First host spans wider */}\n <div className=\"md:col-span-2 lg:col-span-1\">\n <HostCardComponent host={hosts[0]} />\n </div>\n {/* Remaining hosts in the second column area */}\n <div className=\"grid grid-cols-1 gap-3 md:col-span-2 lg:col-span-1\">\n {hosts.slice(1).map((h, i) => (\n <HostCardComponent key={h.hostname ?? i} host={h} />\n ))}\n </div>\n </div>\n )}\n\n {/* Row 2: Metrics + Services — side by side */}\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-3\">\n {/* Metrics grid — 2 columns within */}\n {metrics.length > 0 && (\n <div className=\"lg:col-span-2\">\n <SectionLabel>Metrics</SectionLabel>\n <div className=\"grid grid-cols-2 sm:grid-cols-4 gap-2\">\n {metrics.map((m, i) => (\n <StatCardComponent key={m.label ?? i} stat={m} />\n ))}\n </div>\n </div>\n )}\n\n {/* Services list */}\n {services.length > 0 && (\n <div>\n <SectionLabel>Services</SectionLabel>\n <div className=\"space-y-2\">\n {services.slice(0, 4).map((s, i) => (\n <div key={s.service ?? i} className=\"rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium text-tollerud-text-primary\">{s.service}</span>\n <span className={cn(\n 'text-xs px-1.5 py-0.5 rounded-full font-medium',\n s.status === 'online' && 'text-tollerud-accent bg-tollerud-accent/10',\n s.status === 'warning' && 'text-tollerud-warning bg-tollerud-warning/10',\n s.status === 'offline' && 'text-tollerud-error bg-tollerud-error/10',\n s.status === 'idle' && 'text-tollerud-text-muted bg-tollerud-noir-800',\n )}>\n {s.status}\n </span>\n </div>\n {s.responseTime && (\n <p className=\"text-xs text-tollerud-text-muted mt-1\">{s.responseTime} response</p>\n )}\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n\n {/* Row 3: Incidents — full width */}\n {incidents.length > 0 && (\n <div>\n <SectionLabel>Recent Incidents</SectionLabel>\n <div className=\"space-y-1.5\">\n {incidents.slice(0, 4).map((inc, i) => (\n <IncidentCardItem key={inc.title + i} incident={inc} />\n ))}\n </div>\n </div>\n )}\n </div>\n )\n}\n\n/* ────────── Internal sub-components for rendering ────────── */\n\nfunction SectionLabel({ children }: { children: ReactNode }) {\n return (\n <p className=\"text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider mb-2\">{children}</p>\n )\n}\n\nfunction HostCardComponent({ host }: { host: HostCardProps }) {\n return (\n <div className={cn(\n 'rounded-xl border p-4',\n host.status === 'online' ? 'border-tollerud-border/30 bg-tollerud-surface' :\n host.status === 'warning' ? 'border-tollerud-warning/30 bg-tollerud-warning/5' :\n 'border-tollerud-border/20 bg-tollerud-surface opacity-70'\n )}>\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-2\">\n <StatusDotComp status={host.status as 'online' | 'offline' | 'warning'} />\n <span className=\"text-sm font-semibold text-tollerud-text-primary\">{host.hostname}</span>\n </div>\n <span className=\"text-xs text-tollerud-text-muted font-mono\">{host.ip}</span>\n </div>\n <div className=\"grid grid-cols-2 gap-2 text-xs\">\n {host.cpu && <MetricBadge label=\"CPU\" value={host.cpu} />}\n {host.memory && <MetricBadge label=\"Mem\" value={host.memory} />}\n {host.disk && <MetricBadge label=\"Disk\" value={host.disk} />}\n {host.uptime && <MetricBadge label=\"Up\" value={host.uptime} />}\n </div>\n </div>\n )\n}\n\nfunction StatCardComponent({ stat }: { stat: StatCardProps }) {\n return (\n <div className=\"rounded-lg border border-tollerud-border/20 bg-tollerud-surface p-3\">\n <p className=\"text-xs text-tollerud-text-muted\">{stat.label}</p>\n <p className=\"text-lg font-semibold text-tollerud-text-primary mt-0.5\">{stat.value}</p>\n {stat.change && (\n <span className={cn(\n 'text-xs font-medium',\n stat.change.direction === 'up' ? 'text-tollerud-accent' : 'text-tollerud-error'\n )}>\n {stat.change.value}\n </span>\n )}\n </div>\n )\n}\n\nfunction IncidentCardItem({ incident }: { incident: { title: string; severity: IncidentSeverity; timestamp: string; service: string; description?: string; acknowledged?: boolean } }) {\n return (\n <div className={cn(\n 'flex items-start gap-3 rounded-lg border p-3',\n incident.acknowledged ? 'border-tollerud-border/10 bg-tollerud-noir-900/50 opacity-60' : 'border-tollerud-border/20 bg-tollerud-surface'\n )}>\n <SeverityDot severity={incident.severity} />\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-medium text-tollerud-text-primary truncate\">{incident.title}</span>\n {incident.acknowledged && (\n <span className=\"text-xs text-tollerud-text-muted\">(acknowledged)</span>\n )}\n </div>\n <div className=\"flex items-center gap-2 text-xs text-tollerud-text-muted mt-0.5\">\n <span>{incident.service}</span>\n <span>·</span>\n <span>{incident.timestamp}</span>\n </div>\n {incident.description && (\n <p className=\"text-xs text-tollerud-text-secondary mt-1\">{incident.description}</p>\n )}\n </div>\n </div>\n )\n}\n\nfunction StatusDotComp({ status }: { status: 'online' | 'offline' | 'warning' }) {\n return (\n <span className={cn(\n 'inline-block w-2 h-2 rounded-full',\n status === 'online' && 'bg-tollerud-accent shadow-[0_0_4px_var(--tollerud-accent)]',\n status === 'warning' && 'bg-tollerud-warning',\n status === 'offline' && 'bg-tollerud-error',\n )} />\n )\n}\n\nfunction SeverityDot({ severity }: { severity: IncidentSeverity }) {\n return (\n <span className={cn(\n 'inline-block w-2 h-2 rounded-full mt-1 shrink-0',\n severity === 'critical' && 'bg-tollerud-error shadow-[0_0_4px_var(--tollerud-error)]',\n severity === 'high' && 'bg-tollerud-warning',\n severity === 'medium' && 'bg-tollerud-accent',\n severity === 'low' && 'bg-tollerud-text-muted',\n severity === 'info' && 'bg-tollerud-info',\n )} />\n )\n}\n\nfunction MetricBadge({ label, value }: { label: string; value: string }) {\n return (\n <div className=\"rounded bg-tollerud-noir-800 px-2 py-1.5\">\n <span className=\"text-tollerud-text-muted\">{label}</span>\n <span className=\"float-right text-tollerud-text-primary font-mono\">{value}</span>\n </div>\n )\n}\n\nexport default BentoDashboard"]}