@tollerud/ui 3.0.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/AGENTS.md +5 -3
  2. package/CHANGELOG.md +67 -0
  3. package/COMPONENTS.md +13 -1
  4. package/README.md +1 -0
  5. package/SKILL.md +8 -5
  6. package/components.json +1 -1
  7. package/dist/avatar.d.ts +3 -2
  8. package/dist/avatar.js +1 -1
  9. package/dist/bento-dashboard.js +6 -1
  10. package/dist/button.d.ts +3 -3
  11. package/dist/button.js +1 -1
  12. package/dist/checkbox.js +1 -1
  13. package/dist/{chunk-7TOT5ME3.js → chunk-3LTW224O.js} +6 -6
  14. package/dist/chunk-3LTW224O.js.map +1 -0
  15. package/dist/chunk-AQT3FZRQ.js +23 -0
  16. package/dist/chunk-AQT3FZRQ.js.map +1 -0
  17. package/dist/{chunk-RWJELAS6.js → chunk-BQWF5MP7.js} +14 -6
  18. package/dist/chunk-BQWF5MP7.js.map +1 -0
  19. package/dist/{chunk-VTRUUT5K.js → chunk-FPFLOYIJ.js} +6 -6
  20. package/dist/chunk-FPFLOYIJ.js.map +1 -0
  21. package/dist/{chunk-6SKTH45H.js → chunk-J2Z4ZFVX.js} +29 -18
  22. package/dist/chunk-J2Z4ZFVX.js.map +1 -0
  23. package/dist/{chunk-ISHZ6ZPJ.js → chunk-JFOW2DI5.js} +17 -5
  24. package/dist/chunk-JFOW2DI5.js.map +1 -0
  25. package/dist/{chunk-3TGMGBKM.js → chunk-K4ALNUZI.js} +6 -6
  26. package/dist/{chunk-3TGMGBKM.js.map → chunk-K4ALNUZI.js.map} +1 -1
  27. package/dist/chunk-LGVXEWNB.js +54 -0
  28. package/dist/chunk-LGVXEWNB.js.map +1 -0
  29. package/dist/{chunk-OONIUDST.js → chunk-OLHMMFQ7.js} +3 -8
  30. package/dist/chunk-OLHMMFQ7.js.map +1 -0
  31. package/dist/{chunk-V3P5QLLX.js → chunk-Q54CVE3W.js} +3 -3
  32. package/dist/{chunk-V3P5QLLX.js.map → chunk-Q54CVE3W.js.map} +1 -1
  33. package/dist/chunk-QEIEWGHA.js +62 -0
  34. package/dist/chunk-QEIEWGHA.js.map +1 -0
  35. package/dist/{chunk-CBQ63EBL.js → chunk-QQHBEACI.js} +9 -6
  36. package/dist/chunk-QQHBEACI.js.map +1 -0
  37. package/dist/{chunk-XR5QBVEV.js → chunk-SNNMZ444.js} +3 -3
  38. package/dist/{chunk-XR5QBVEV.js.map → chunk-SNNMZ444.js.map} +1 -1
  39. package/dist/chunk-T3UQ7G4T.js +58 -0
  40. package/dist/chunk-T3UQ7G4T.js.map +1 -0
  41. package/dist/{chunk-T3TQPOVM.js → chunk-TLEKK53J.js} +5 -8
  42. package/dist/chunk-TLEKK53J.js.map +1 -0
  43. package/dist/{chunk-DGCRHVWW.js → chunk-VFS3V3VY.js} +12 -5
  44. package/dist/chunk-VFS3V3VY.js.map +1 -0
  45. package/dist/chunk-VOARBYVQ.js +44 -0
  46. package/dist/chunk-VOARBYVQ.js.map +1 -0
  47. package/dist/{chunk-O57QMLNI.js → chunk-YTU7BRDW.js} +16 -12
  48. package/dist/chunk-YTU7BRDW.js.map +1 -0
  49. package/dist/{chunk-DFM7UUKB.js → chunk-ZTFOR3AN.js} +4 -4
  50. package/dist/{chunk-DFM7UUKB.js.map → chunk-ZTFOR3AN.js.map} +1 -1
  51. package/dist/cta-band.js +1 -1
  52. package/dist/data-table.js +4 -4
  53. package/dist/date-picker.js +1 -1
  54. package/dist/footer.js +2 -1
  55. package/dist/form-row.d.ts +4 -0
  56. package/dist/form-row.js +1 -1
  57. package/dist/hero-block.js +3 -3
  58. package/dist/index.d.ts +1 -0
  59. package/dist/index.js +24 -23
  60. package/dist/monogram.d.ts +20 -0
  61. package/dist/monogram.js +5 -0
  62. package/dist/monogram.js.map +1 -0
  63. package/dist/noir-glow-background.d.ts +7 -1
  64. package/dist/noir-glow-background.js +1 -1
  65. package/dist/pill.d.ts +5 -2
  66. package/dist/pill.js +1 -1
  67. package/dist/pricing-card.js +2 -2
  68. package/dist/radio-group.d.ts +6 -0
  69. package/dist/radio-group.js +1 -1
  70. package/dist/skeleton.d.ts +10 -2
  71. package/dist/skeleton.js +1 -1
  72. package/dist/slider.js +1 -1
  73. package/dist/switch.js +1 -1
  74. package/dist/timeline.js +1 -1
  75. package/globals-layers.css +111 -1
  76. package/package.json +5 -3
  77. package/registry.json +30 -9
  78. package/tokens.css +49 -5
  79. package/tollerud-avatar-full.png +0 -0
  80. package/dist/chunk-6SKTH45H.js.map +0 -1
  81. package/dist/chunk-7TOT5ME3.js.map +0 -1
  82. package/dist/chunk-CBQ63EBL.js.map +0 -1
  83. package/dist/chunk-DGCRHVWW.js.map +0 -1
  84. package/dist/chunk-FGXOV2QH.js +0 -23
  85. package/dist/chunk-FGXOV2QH.js.map +0 -1
  86. package/dist/chunk-HYQGOC2E.js +0 -79
  87. package/dist/chunk-HYQGOC2E.js.map +0 -1
  88. package/dist/chunk-ISHZ6ZPJ.js.map +0 -1
  89. package/dist/chunk-O57QMLNI.js.map +0 -1
  90. package/dist/chunk-OONIUDST.js.map +0 -1
  91. package/dist/chunk-PLF3BBQI.js +0 -139
  92. package/dist/chunk-PLF3BBQI.js.map +0 -1
  93. package/dist/chunk-Q74VRQEX.js +0 -26
  94. package/dist/chunk-Q74VRQEX.js.map +0 -1
  95. package/dist/chunk-RWJELAS6.js.map +0 -1
  96. package/dist/chunk-T3TQPOVM.js.map +0 -1
  97. package/dist/chunk-VTRUUT5K.js.map +0 -1
  98. /package/{tia-full-figure.svg → tollerud-avatar-full.svg} +0 -0
package/dist/skeleton.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Skeleton } from './chunk-FGXOV2QH.js';
2
+ export { Skeleton } from './chunk-AQT3FZRQ.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=skeleton.js.map
5
5
  //# sourceMappingURL=skeleton.js.map
package/dist/slider.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Slider } from './chunk-OONIUDST.js';
2
+ export { Slider } from './chunk-OLHMMFQ7.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=slider.js.map
5
5
  //# sourceMappingURL=slider.js.map
package/dist/switch.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Switch } from './chunk-O57QMLNI.js';
2
+ export { Switch } from './chunk-YTU7BRDW.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=switch.js.map
5
5
  //# sourceMappingURL=switch.js.map
package/dist/timeline.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { Timeline } from './chunk-7TOT5ME3.js';
2
+ export { Timeline } from './chunk-3LTW224O.js';
3
3
  import './chunk-WSQNPRGN.js';
4
4
  //# sourceMappingURL=timeline.js.map
5
5
  //# sourceMappingURL=timeline.js.map
@@ -141,6 +141,7 @@
141
141
  rgba(232, 213, 0, 0.8),
142
142
  rgba(255, 184, 0, 0.4)
143
143
  );
144
+ --tollerud-shimmer-highlight: #FFFDE6;
144
145
 
145
146
  /* ═══ Transition ═══ */
146
147
  --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
@@ -193,6 +194,13 @@
193
194
  transition-duration: 0.01ms !important;
194
195
  scroll-behavior: auto !important;
195
196
  }
197
+ .tollerud-display-shimmer {
198
+ animation: none !important;
199
+ background: none;
200
+ -webkit-background-clip: initial;
201
+ background-clip: initial;
202
+ color: var(--primary);
203
+ }
196
204
  }
197
205
  }
198
206
 
@@ -236,7 +244,7 @@
236
244
  box-shadow: var(--shadow-glow, 0 0 15px rgba(255,255,0,0.3));
237
245
  }
238
246
  .tollerud-btn--secondary {
239
- background: transparent;
247
+ background: var(--surface-raised);
240
248
  color: var(--foreground);
241
249
  border-color: var(--border);
242
250
  }
@@ -390,6 +398,76 @@
390
398
  background: var(--gradient-yellow);
391
399
  margin: 3rem 0;
392
400
  }
401
+ .tollerud-accent-bar--inline {
402
+ margin: 0;
403
+ }
404
+
405
+ /* ═══ Range slider ═══ */
406
+ .tollerud-slider {
407
+ -webkit-appearance: none;
408
+ appearance: none;
409
+ width: 100%;
410
+ height: 6px;
411
+ border-radius: 999px;
412
+ background: var(--muted);
413
+ outline: none;
414
+ }
415
+ .tollerud-slider::-webkit-slider-thumb {
416
+ -webkit-appearance: none;
417
+ appearance: none;
418
+ width: 16px;
419
+ height: 16px;
420
+ border-radius: 50%;
421
+ background: var(--tollerud-yellow);
422
+ border: 2px solid var(--card);
423
+ cursor: pointer;
424
+ box-shadow: 0 0 0 1px var(--border);
425
+ }
426
+ .tollerud-slider::-moz-range-thumb {
427
+ width: 16px;
428
+ height: 16px;
429
+ border-radius: 50%;
430
+ background: var(--tollerud-yellow);
431
+ border: 2px solid var(--card);
432
+ cursor: pointer;
433
+ }
434
+
435
+ /* ═══ Form row (settings layout) ═══ */
436
+ .tollerud-formrow {
437
+ display: grid;
438
+ grid-template-columns: 1fr auto;
439
+ gap: 16px;
440
+ align-items: center;
441
+ padding: 16px 0;
442
+ border-bottom: 1px solid var(--border);
443
+ }
444
+ .tollerud-formrow:last-child {
445
+ border-bottom: none;
446
+ }
447
+ .tollerud-formrow__title {
448
+ font-size: 14px;
449
+ font-weight: 500;
450
+ color: var(--foreground);
451
+ }
452
+ .tollerud-formrow__hint {
453
+ font-size: 12.5px;
454
+ color: var(--text-muted);
455
+ margin-top: 3px;
456
+ line-height: 1.45;
457
+ max-width: 46ch;
458
+ }
459
+ .tollerud-formrow__control {
460
+ justify-self: end;
461
+ }
462
+ @media (max-width: 560px) {
463
+ .tollerud-formrow {
464
+ grid-template-columns: 1fr;
465
+ gap: 10px;
466
+ }
467
+ .tollerud-formrow__control {
468
+ justify-self: start;
469
+ }
470
+ }
393
471
 
394
472
  /* ═══ Gradient Text ═══ */
395
473
  .tollerud-gradient-text {
@@ -527,6 +605,24 @@
527
605
  line-height: 1.1;
528
606
  }
529
607
 
608
+ /* Animated yellow sweep clipped to text — pair with .tollerud-display on dark surfaces */
609
+ .tollerud-display-shimmer {
610
+ background: linear-gradient(
611
+ 100deg,
612
+ var(--tollerud-yellow) 32%,
613
+ var(--tollerud-shimmer-highlight) 50%,
614
+ var(--tollerud-yellow) 68%
615
+ );
616
+ background-size: 220% 100%;
617
+ -webkit-background-clip: text;
618
+ background-clip: text;
619
+ color: transparent;
620
+ animation: tollerud-display-shimmer 5s linear infinite;
621
+ }
622
+ @keyframes tollerud-display-shimmer {
623
+ to { background-position: -220% 0; }
624
+ }
625
+
530
626
  /* ═══ Status Indicator ═══ */
531
627
  .tollerud-status {
532
628
  display: inline-flex;
@@ -623,6 +719,20 @@
623
719
  .tollerud-timeline__dot--active {
624
720
  animation: tollerud-timeline-pulse 2s infinite;
625
721
  }
722
+ .tollerud-timeline__dot--online {
723
+ background: var(--success);
724
+ box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
725
+ }
726
+ .tollerud-timeline__dot--warning {
727
+ background: var(--tollerud-yellow);
728
+ box-shadow: 0 0 6px rgba(232, 213, 0, 0.5);
729
+ }
730
+ .tollerud-timeline__dot--offline {
731
+ background: var(--destructive);
732
+ }
733
+ .tollerud-timeline__dot--idle {
734
+ background: var(--tollerud-noir-400);
735
+ }
626
736
  @keyframes tollerud-timeline-pulse {
627
737
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,0,0.4); }
628
738
  50% { box-shadow: 0 0 0 6px rgba(255,255,0,0); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tollerud/ui",
3
- "version": "3.0.0",
3
+ "version": "3.1.1",
4
4
  "description": "Tollerud User Interface — dark, monochrome + yellow accent. Noir aesthetic meets modern utility.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -40,7 +40,8 @@
40
40
  "./tollerud-logo.svg": "./tollerud-logo.svg",
41
41
  "./tollerud-avatar.svg": "./tollerud-avatar.svg",
42
42
  "./tollerud-avatar.png": "./tollerud-avatar.png",
43
- "./tia-full-figure.svg": "./tia-full-figure.svg",
43
+ "./tollerud-avatar-full.svg": "./tollerud-avatar-full.svg",
44
+ "./tollerud-avatar-full.png": "./tollerud-avatar-full.png",
44
45
  "./registry.json": "./registry.json",
45
46
  "./*": {
46
47
  "import": {
@@ -66,7 +67,8 @@
66
67
  "tollerud-logo.svg",
67
68
  "tollerud-avatar.svg",
68
69
  "tollerud-avatar.png",
69
- "tia-full-figure.svg",
70
+ "tollerud-avatar-full.svg",
71
+ "tollerud-avatar-full.png",
70
72
  "AGENTS.md",
71
73
  "SKILL.md"
72
74
  ],
package/registry.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
- "name": "tollerud-noir",
3
- "version": "3.0.0",
4
- "description": "Tollerud Design System \u2014 dark, cinematic, keyboard-first infrastructure UI",
2
+ "name": "Tollerud User Interface",
3
+ "version": "3.1.1",
4
+ "description": "Dark, monochrome React components with a single yellow accent — built for dashboards, tools, and homelab UIs.",
5
5
  "components": {
6
6
  "button": {
7
7
  "name": "Button",
8
- "description": "Primary action button with terminal, ghost, and variant styles",
8
+ "description": "Five variants and three sizes — primary, secondary, ghost, destructive, and terminal. Supports asChild, icons, and loading state",
9
9
  "files": [
10
10
  "components/Button.tsx"
11
11
  ],
@@ -213,7 +213,7 @@
213
213
  },
214
214
  "incident-card": {
215
215
  "name": "IncidentCard",
216
- "description": "Severity-graded incident/alert card (critical \u2192 info)",
216
+ "description": "Severity-graded incident/alert card (critical info)",
217
217
  "files": [
218
218
  "components/IncidentCard.tsx"
219
219
  ],
@@ -394,6 +394,22 @@
394
394
  "clsx",
395
395
  "tailwind-merge"
396
396
  ],
397
+ "registryDependencies": [
398
+ "monogram"
399
+ ],
400
+ "type": "components:ui"
401
+ },
402
+ "monogram": {
403
+ "name": "Monogram",
404
+ "description": "Tollerud monogram SVG with yellow, black, or white fill",
405
+ "files": [
406
+ "components/Monogram.tsx",
407
+ "components/monogram-geometry.ts"
408
+ ],
409
+ "dependencies": [
410
+ "clsx",
411
+ "tailwind-merge"
412
+ ],
397
413
  "registryDependencies": [],
398
414
  "type": "components:ui"
399
415
  },
@@ -439,7 +455,7 @@
439
455
  },
440
456
  "bento-dashboard": {
441
457
  "name": "BentoDashboard",
442
- "description": "Composable bento-grid dashboard layout for hosts, metrics, services, and incidents",
458
+ "description": "Homelab mission-control bento grid host cards, metrics, services, and recent incidents",
443
459
  "files": [
444
460
  "components/BentoDashboard.tsx"
445
461
  ],
@@ -447,7 +463,12 @@
447
463
  "clsx",
448
464
  "tailwind-merge"
449
465
  ],
450
- "registryDependencies": [],
466
+ "registryDependencies": [
467
+ "host-card",
468
+ "stat-card",
469
+ "service-health-card",
470
+ "incident-card"
471
+ ],
451
472
  "type": "components:ui"
452
473
  },
453
474
  "breadcrumb": {
@@ -874,7 +895,7 @@
874
895
  },
875
896
  "hero-block": {
876
897
  "name": "HeroBlock",
877
- "description": "Landing hero on noir glow background with optional shader intensity",
898
+ "description": "Landing hero with noir glow background. Pass intense for live WebGL shader; optional media slot for two-column layout",
878
899
  "files": [
879
900
  "components/HeroBlock.tsx"
880
901
  ],
@@ -905,7 +926,7 @@
905
926
  },
906
927
  "cta-band": {
907
928
  "name": "CTABand",
908
- "description": "Closing call-to-action band with optional yellow accent bar",
929
+ "description": "Centered closing call-to-action with title, description, action row, and optional yellow accent bar",
909
930
  "files": [
910
931
  "components/CTABand.tsx"
911
932
  ],
package/tokens.css CHANGED
@@ -42,6 +42,7 @@
42
42
  --tollerud-border: #333333;
43
43
  --tollerud-border-subtle: #252525;
44
44
  --tollerud-border-accent: #FFFF00;
45
+ --tollerud-shimmer-highlight: #FFFDE6;
45
46
 
46
47
  /* ── States ── */
47
48
  --tollerud-success: #22C55E;
@@ -222,13 +223,13 @@ code, pre {
222
223
  }
223
224
 
224
225
  .tollerud-btn--secondary {
225
- background: transparent;
226
- color: var(--tollerud-text-primary);
227
- border-color: var(--tollerud-border);
226
+ background: var(--surface-raised, var(--tollerud-surface-raised));
227
+ color: var(--foreground, var(--tollerud-text-primary));
228
+ border-color: var(--border, var(--tollerud-border));
228
229
  }
229
230
  .tollerud-btn--secondary:hover {
230
- border-color: var(--tollerud-text-secondary);
231
- background: var(--tollerud-surface-hover);
231
+ border-color: var(--text-secondary, var(--tollerud-text-secondary));
232
+ background: var(--surface-hover, var(--tollerud-surface-hover));
232
233
  }
233
234
 
234
235
  .tollerud-btn--ghost {
@@ -351,6 +352,13 @@ code, pre {
351
352
  @media (prefers-reduced-motion: reduce) {
352
353
  .tollerud-noir-glow-bg,
353
354
  .tollerud-noir-noise { animation: none !important; }
355
+ .tollerud-display-shimmer {
356
+ animation: none !important;
357
+ background: none;
358
+ -webkit-background-clip: initial;
359
+ background-clip: initial;
360
+ color: var(--tollerud-yellow);
361
+ }
354
362
  }
355
363
 
356
364
  /* ── Background Grid ── */
@@ -411,6 +419,16 @@ code, pre {
411
419
  color: rgba(232, 213, 0, 0.55);
412
420
  border-color: rgba(232, 213, 0, 0.15);
413
421
  }
422
+ .tollerud-pill--success {
423
+ background: rgba(34, 197, 94, 0.06);
424
+ color: var(--success);
425
+ border-color: rgba(34, 197, 94, 0.35);
426
+ }
427
+ .tollerud-pill--error {
428
+ background: rgba(239, 68, 68, 0.06);
429
+ color: var(--destructive);
430
+ border-color: rgba(239, 68, 68, 0.35);
431
+ }
414
432
 
415
433
  /* ── Gradient Accent Bar ── */
416
434
  .tollerud-accent-bar {
@@ -442,6 +460,22 @@ code, pre {
442
460
  line-height: 0.95;
443
461
  color: white;
444
462
  }
463
+ .tollerud-display-shimmer {
464
+ background: linear-gradient(
465
+ 100deg,
466
+ var(--tollerud-yellow) 32%,
467
+ var(--tollerud-shimmer-highlight) 50%,
468
+ var(--tollerud-yellow) 68%
469
+ );
470
+ background-size: 220% 100%;
471
+ -webkit-background-clip: text;
472
+ background-clip: text;
473
+ color: transparent;
474
+ animation: tollerud-display-shimmer 5s linear infinite;
475
+ }
476
+ @keyframes tollerud-display-shimmer {
477
+ to { background-position: -220% 0; }
478
+ }
445
479
 
446
480
  /* ── Kbd (Keyboard Shortcut Chip) ── */
447
481
  .tollerud-kbd { display: inline-flex; align-items: center; gap: 2px; }
@@ -512,6 +546,16 @@ code, pre {
512
546
  .tollerud-timeline__dot-group { display: flex; flex-direction: column; align-items: center; }
513
547
  .tollerud-timeline__dot { width: 10px; height: 10px; border-radius: 50%; background: var(--tollerud-noir-500); flex-shrink: 0; }
514
548
  .tollerud-timeline__dot--active { animation: tollerud-timeline-pulse 2s infinite; }
549
+ .tollerud-timeline__dot--online {
550
+ background: var(--success);
551
+ box-shadow: 0 0 6px rgba(34, 197, 94, 0.5);
552
+ }
553
+ .tollerud-timeline__dot--warning {
554
+ background: var(--tollerud-yellow);
555
+ box-shadow: 0 0 6px rgba(232, 213, 0, 0.5);
556
+ }
557
+ .tollerud-timeline__dot--offline { background: var(--destructive); }
558
+ .tollerud-timeline__dot--idle { background: var(--tollerud-noir-400); }
515
559
  @keyframes tollerud-timeline-pulse {
516
560
  0%, 100% { box-shadow: 0 0 0 0 rgba(255,255,0,.4); }
517
561
  50% { box-shadow: 0 0 0 6px rgba(255,255,0,0); }
Binary file
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/RadioGroup.tsx"],"names":[],"mappings":";;;;AAcA,IAAM,UAAA,GAAa,UAAA;AAAA,EACjB,CAAC,EAAE,KAAA,EAAO,OAAO,QAAA,EAAU,SAAA,IAAa,GAAA,KAAQ;AAC9C,IAAA,4BACG,UAAA,EAAA,EAAS,GAAA,EAAU,WAAW,EAAA,CAAG,qBAAA,EAAuB,SAAS,CAAA,EAC/D,QAAA,EAAA;AAAA,MAAA,KAAA,oBACC,GAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,mDAAA,EACf,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,sBAEF,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAA,EAAuB,QAAA,EAAS,CAAA;AAAA,MAC9C,KAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,sCAAsC,QAAA,EAAA,KAAA,EAAM;AAAA,KAAA,EAE7D,CAAA;AAAA,EAEJ;AACF;AACA,UAAA,CAAW,WAAA,GAAc,YAAA;AAMzB,IAAM,KAAA,GAAQ,UAAA;AAAA,EACZ,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,IAAI,MAAA,EAAQ,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACnD,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,iEAAA;AAAA,UACA,oCAAA;AAAA,UACA,MAAM,QAAA,IAAY,gCAAA;AAAA,UAClB;AAAA,SACF;AAAA,QAEA,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,MAAA,EAAA,EAAK,WAAU,2CAAA,EACd,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,GAAA;AAAA,gBACA,EAAA;AAAA,gBACA,IAAA,EAAK,OAAA;AAAA,gBACL,SAAA,EAAU,cAAA;AAAA,gBACT,GAAG;AAAA;AAAA,aACN;AAAA,4BAEA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,EAAA;AAAA,kBACT,6DAAA;AAAA,kBACA,mDAAA;AAAA,kBACA,yEAAA;AAAA,kBACA,qCAAA;AAAA,kBACA,4CAAA;AAAA,kBACA;AAAA,iBACF;AAAA,gBAGA,QAAA,kBAAA,GAAA;AAAA,kBAAC,MAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,6EAAA;AAAA,sBACA,KAAA,CAAM,UAAU,aAAA,GAAgB;AAAA;AAClC;AAAA;AACF;AAAA;AACF,WAAA,EACF,CAAA;AAAA,UACC,KAAA,oBAAS,GAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA;AAAA,KACzB;AAAA,EAEJ;AACF;AACA,KAAA,CAAM,WAAA,GAAc,OAAA","file":"chunk-6SKTH45H.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface RadioGroupProps {\n /** Group label */\n label?: string\n /** Error message */\n error?: string\n children?: React.ReactNode\n className?: string\n}\n\nconst RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(\n ({ label, error, children, className }, ref) => {\n return (\n <fieldset ref={ref} className={cn('flex flex-col gap-1', className)}>\n {label && (\n <legend className=\"text-xs font-medium text-tollerud-text-muted mb-1\">\n {label}\n </legend>\n )}\n <div className=\"flex flex-col gap-2\">{children}</div>\n {error && (\n <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>\n )}\n </fieldset>\n )\n }\n)\nRadioGroup.displayName = 'RadioGroup'\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n}\n\nconst Radio = forwardRef<HTMLInputElement, RadioProps>(\n ({ className, label, id: idProp, ...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 cursor-pointer select-none group',\n 'text-sm text-tollerud-text-primary',\n props.disabled && 'opacity-50 pointer-events-none',\n className\n )}\n >\n <span className=\"relative flex items-center justify-center\">\n <input\n ref={ref}\n id={id}\n type=\"radio\"\n className=\"peer sr-only\"\n {...props}\n />\n {/* Custom radio circle */}\n <span\n className={cn(\n 'h-4 w-4 rounded-full border transition-all duration-[150ms]',\n 'bg-tollerud-surface-raised border-tollerud-border',\n 'peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow',\n 'peer-checked:border-tollerud-yellow',\n 'group-hover:border-tollerud-text-secondary',\n 'flex items-center justify-center'\n )}\n >\n {/* Inner dot */}\n <span\n className={cn(\n 'h-2 w-2 rounded-full bg-tollerud-yellow transition-opacity duration-[150ms]',\n props.checked ? 'opacity-100' : 'opacity-0'\n )}\n />\n </span>\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nRadio.displayName = 'Radio'\n\nexport { RadioGroup, Radio }"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Timeline.tsx"],"names":[],"mappings":";;;;AA6BA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,QAAQ,OAAA,EAAS,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACxD,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA,CAAG,mBAAA,EAAqB,OAAA,IAAW,iBAAiB,SAAS,CAAA;AAAA,QACxE,IAAA,EAAK,MAAA;AAAA,QACL,YAAA,EAAW,mBAAA;AAAA,QACV,GAAG,KAAA;AAAA,QAEH,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,KAAM;AACtB,UAAA,MAAM,MAAA,GAAS,CAAA,KAAM,KAAA,CAAM,MAAA,GAAS,CAAA;AAEpC,UAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAkB,SAAA,EAAU,yBAAA,EAA0B,MAAK,UAAA,EAE1D,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,SAAI,SAAA,EAAU,2BAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,8BAAA,EACZ,QAAA,EAAA;AAAA,cAAA,IAAA,CAAK,uBACJ,GAAA,CAAC,MAAA,EAAA,EAAK,WAAU,yBAAA,EAA2B,QAAA,EAAA,IAAA,CAAK,MAAK,CAAA,mBAErD,GAAA;AAAA,gBAAC,MAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EAAW,EAAA;AAAA,oBACT,wBAAA;AAAA,oBACA,MAAA,IAAU,gCAAA;AAAA,oBACV,IAAA,CAAK,WAAW,QAAA,IAAY,0DAAA;AAAA,oBAC5B,IAAA,CAAK,WAAW,SAAA,IAAa,mBAAA;AAAA,oBAC7B,IAAA,CAAK,WAAW,SAAA,IAAa,yDAAA;AAAA,oBAC7B,CAAC,KAAK,MAAA,IAAU;AAAA;AAClB;AAAA,eACF;AAAA,cAED,CAAC,MAAA,oBAAU,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yBAAA,EAA0B;AAAA,aAAA,EACvD,CAAA,EACF,CAAA;AAAA,4BAGA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EACb,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,wCAAA,EACb,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,IAAA,CAAK,KAAA,EAAM,CAAA;AAAA,gCACvD,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAA,EAA2B,eAAK,IAAA,EAAK;AAAA,eAAA,EACvD,CAAA;AAAA,cACC,KAAK,WAAA,oBACJ,GAAA,CAAC,OAAE,SAAA,EAAU,gCAAA,EAAkC,eAAK,WAAA,EAAY,CAAA;AAAA,cAEjE,IAAA,CAAK,QAAQ,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,oBAC/B,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,6BAAA,EACZ,QAAA,EAAA,IAAA,CAAK,KAAK,GAAA,CAAI,CAAC,sBACd,GAAA,CAAC,MAAA,EAAA,EAAa,WAAU,yBAAA,EAA2B,QAAA,EAAA,CAAA,EAAA,EAAxC,CAA0C,CACtD,CAAA,EACH;AAAA,aAAA,EAEJ;AAAA,WAAA,EAAA,EAtCQ,KAAK,EAuCf,CAAA;AAAA,QAEJ,CAAC;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-7TOT5ME3.js","sourcesContent":["import { type HTMLAttributes, type ReactNode, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\nimport type { Status } from './StatusDot'\n\nexport interface TimelineItemData {\n id: string\n /** Timestamp label */\n time: string\n /** Title/headline of the event */\n title: string\n /** Description */\n description?: string\n /** Status indicator dot */\n status?: Status\n /** Optional icon to replace dot */\n icon?: ReactNode\n /** Optional metadata badges */\n meta?: string[]\n}\n\nexport interface TimelineProps extends HTMLAttributes<HTMLDivElement> {\n /** Timeline events */\n items: TimelineItemData[]\n /** Whether items are active (show animated dot pulse) */\n active?: boolean\n /** Whether the timeline is loading */\n loading?: boolean\n}\n\nconst Timeline = forwardRef<HTMLDivElement, TimelineProps>(\n ({ className, items, active, loading, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn('tollerud-timeline', loading && 'animate-pulse', className)}\n role=\"list\"\n aria-label=\"Activity timeline\"\n {...props}\n >\n {items.map((item, i) => {\n const isLast = i === items.length - 1\n\n return (\n <div key={item.id} className=\"tollerud-timeline__item\" role=\"listitem\">\n {/* Dot column */}\n <div className=\"tollerud-timeline__marker\">\n <div className=\"tollerud-timeline__dot-group\">\n {item.icon ? (\n <span className=\"tollerud-timeline__icon\">{item.icon}</span>\n ) : (\n <span\n className={cn(\n 'tollerud-timeline__dot',\n active && 'tollerud-timeline__dot--active',\n item.status === 'online' && 'bg-tollerud-success shadow-[0_0_6px_rgba(34,197,94,0.5)]',\n item.status === 'offline' && 'bg-tollerud-error',\n item.status === 'warning' && 'bg-tollerud-yellow shadow-[0_0_6px_rgba(232,213,0,0.5)]',\n !item.status && 'bg-tollerud-noir-500'\n )}\n />\n )}\n {!isLast && <div className=\"tollerud-timeline__line\" />}\n </div>\n </div>\n\n {/* Content */}\n <div className=\"tollerud-timeline__content\">\n <div className=\"flex items-start justify-between gap-2\">\n <span className=\"tollerud-timeline__title\">{item.title}</span>\n <span className=\"tollerud-timeline__time\">{item.time}</span>\n </div>\n {item.description && (\n <p className=\"tollerud-timeline__description\">{item.description}</p>\n )}\n {item.meta && item.meta.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5 mt-1\">\n {item.meta.map((m) => (\n <span key={m} className=\"tollerud-timeline__meta\">{m}</span>\n ))}\n </div>\n )}\n </div>\n </div>\n )\n })}\n </div>\n )\n }\n)\nTimeline.displayName = 'Timeline'\n\nexport { Timeline }"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/NoirGlowBackground.tsx"],"names":[],"mappings":"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","file":"chunk-CBQ63EBL.js","sourcesContent":["\"use client\"\n\nimport { lazy, Suspense, type CSSProperties } from \"react\"\n\nconst GrainGradient = lazy(() =>\n import(\"@paper-design/shaders-react\").then((module) => ({\n default: module.GrainGradient,\n }))\n)\n\ntype ShaderShape = \"corners\" | \"wave\" | \"dots\" | \"truchet\" | \"ripple\" | \"blob\" | \"sphere\"\ntype Intensity = \"subtle\" | \"medium\" | \"loud\"\ntype Speed = \"still\" | \"slow\" | \"medium\" | \"fast\"\ntype Grain = \"none\" | \"soft\" | \"high\"\n\nexport interface NoirGlowBackgroundProps {\n /** Extra class names for the outer positioning wrapper. */\n className?: string\n /** Inline style for the outer positioning wrapper. */\n style?: CSSProperties\n /** Canvas/WebGL shape. `corners` matches Tollerud.no. */\n shape?: ShaderShape\n /** Visual strength of the yellow glow. */\n intensity?: Intensity\n /** Ambient animation speed. */\n speed?: Speed\n /** Shader grain/noise amount. */\n grain?: Grain\n /** Softness/falloff of the glow blooms. */\n softness?: number\n /** Background color behind the glow. */\n colorBack?: string\n /** Glow colors. Defaults to the Tollerud/Tia yellow ramp. */\n colors?: string[]\n /** Whether to render a readable center vignette on top of the shader. */\n preserveCenter?: boolean\n /** Add the grain/noise CSS overlay. */\n noiseOverlay?: boolean\n /** Prefer the CSS fallback even if shaders are available. Useful for docs/static contexts. */\n forceCssFallback?: boolean\n /** Disable pointer events so content above remains clickable. */\n inert?: boolean\n}\n\nconst intensityMap: Record<Intensity, number> = {\n subtle: 0.24,\n medium: 0.45,\n loud: 0.68,\n}\n\nconst speedMap: Record<Speed, number> = {\n still: 0,\n slow: 0.45,\n medium: 1,\n fast: 1.8,\n}\n\nconst grainMap: Record<Grain, number> = {\n none: 0,\n soft: 0.12,\n high: 0.28,\n}\n\nfunction cx(...classes: Array<string | false | null | undefined>) {\n return classes.filter(Boolean).join(\" \")\n}\n\nfunction CssFallback({ preserveCenter = true, noiseOverlay = true }: Pick<NoirGlowBackgroundProps, \"preserveCenter\" | \"noiseOverlay\">) {\n return (\n <>\n <div className=\"tollerud-noir-glow-bg\" aria-hidden=\"true\" />\n {preserveCenter && <div className=\"tollerud-noir-glow-vignette\" aria-hidden=\"true\" />}\n {noiseOverlay && <div className=\"tollerud-noir-noise\" aria-hidden=\"true\" />}\n </>\n )\n}\n\n/**\n * NoirGlowBackground\n *\n * Tia/Tollerud signature background primitive. The defaults replicate\n * MathiasOki/tollerud-landing's `GradientBackground` component.\n *\n * Install dependency in consuming Next.js apps:\n * npm install @paper-design/shaders-react\n *\n * The CSS fallback classes live in `globals.css` and are used during Suspense,\n * reduced-motion contexts, or when `forceCssFallback` is true.\n */\nexport function NoirGlowBackground({\n className,\n style,\n shape = \"corners\",\n intensity = \"medium\",\n speed = \"medium\",\n grain = \"none\",\n softness = 0.76,\n colorBack = \"hsl(0, 0%, 0%)\",\n colors = [\"hsl(54, 85%, 66%)\", \"hsl(56, 100%, 80%)\", \"hsl(56, 100%, 50%)\"],\n preserveCenter = false,\n noiseOverlay = false,\n forceCssFallback = false,\n inert = true,\n}: NoirGlowBackgroundProps) {\n const wrapperClassName = cx(\n \"tollerud-noir-glow-root absolute inset-0 z-0 overflow-hidden\",\n inert && \"pointer-events-none\",\n className\n )\n\n if (forceCssFallback) {\n return (\n <div className={wrapperClassName} style={style} aria-hidden=\"true\">\n <CssFallback preserveCenter={preserveCenter} noiseOverlay={noiseOverlay} />\n </div>\n )\n }\n\n return (\n <div className={wrapperClassName} style={style} aria-hidden=\"true\">\n <Suspense fallback={<CssFallback preserveCenter={preserveCenter} noiseOverlay={noiseOverlay} />}>\n <GrainGradient\n style={{ height: \"100%\", width: \"100%\" }}\n colorBack={colorBack}\n softness={softness}\n intensity={intensityMap[intensity]}\n noise={grainMap[grain]}\n shape={shape}\n offsetX={0}\n offsetY={0}\n scale={1}\n rotation={0}\n speed={speedMap[speed]}\n colors={colors}\n />\n </Suspense>\n {preserveCenter && <div className=\"tollerud-noir-glow-vignette\" aria-hidden=\"true\" />}\n {noiseOverlay && <div className=\"tollerud-noir-noise\" aria-hidden=\"true\" />}\n </div>\n )\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Avatar.tsx"],"names":[],"mappings":"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","file":"chunk-DGCRHVWW.js","sourcesContent":["'use client'\n\nimport { type HTMLAttributes, forwardRef, useState } from 'react'\nimport { cn } from '@/lib/utils'\n\nconst avatarSizes = {\n sm: 'h-6 w-6 text-[10px]',\n md: 'h-8 w-8 text-xs',\n lg: 'h-11 w-11 text-sm',\n} as const\n\nfunction initialsFrom(name: string) {\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n if (parts.length === 0) return ''\n if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase()\n return (parts[0]![0] + parts[parts.length - 1]![0]).toUpperCase()\n}\n\nexport interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {\n /** Image source */\n src?: string\n /** Accessible name / used to derive initials fallback */\n name?: string\n /** Explicit fallback content (overrides derived initials) */\n fallback?: React.ReactNode\n size?: keyof typeof avatarSizes\n}\n\nconst Avatar = forwardRef<HTMLSpanElement, AvatarProps>(\n ({ className, src, name, fallback, size = 'md', ...props }, ref) => {\n const [errored, setErrored] = useState(false)\n const showImage = !!src && !errored\n\n return (\n <span\n ref={ref}\n className={cn(\n 'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full select-none',\n 'bg-tollerud-surface-raised text-tollerud-text-secondary font-medium',\n 'ring-1 ring-tollerud-border',\n avatarSizes[size],\n className\n )}\n {...props}\n >\n {showImage ? (\n <img\n src={src}\n alt={name ?? ''}\n className=\"h-full w-full object-cover\"\n onError={() => setErrored(true)}\n />\n ) : (\n <span aria-hidden={!!name}>{fallback ?? (name ? initialsFrom(name) : null)}</span>\n )}\n </span>\n )\n }\n)\nAvatar.displayName = 'Avatar'\n\nexport interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Maximum avatars to render before collapsing into a \"+N\" overflow indicator */\n max?: number\n size?: keyof typeof avatarSizes\n children: React.ReactNode\n}\n\nconst AvatarGroup = forwardRef<HTMLDivElement, AvatarGroupProps>(\n ({ className, max, size = 'md', children, ...props }, ref) => {\n const items = Array.isArray(children) ? children : [children]\n const visible = max ? items.slice(0, max) : items\n const overflow = max ? items.length - max : 0\n\n return (\n <div\n ref={ref}\n className={cn('flex items-center -space-x-2', className)}\n {...props}\n >\n {visible.map((child, i) => (\n <span key={i} className=\"ring-2 ring-tollerud-surface rounded-full\">\n {child}\n </span>\n ))}\n {overflow > 0 && (\n <span\n className={cn(\n 'relative inline-flex shrink-0 items-center justify-center rounded-full select-none',\n 'bg-tollerud-surface-raised text-tollerud-text-muted font-medium',\n 'ring-2 ring-tollerud-surface',\n avatarSizes[size]\n )}\n >\n +{overflow}\n </span>\n )}\n </div>\n )\n }\n)\nAvatarGroup.displayName = 'AvatarGroup'\n\nexport { Avatar, AvatarGroup }\n"]}
@@ -1,23 +0,0 @@
1
- 'use client';
2
- import { cn } from './chunk-WSQNPRGN.js';
3
- import { jsx } from 'react/jsx-runtime';
4
-
5
- function Skeleton({
6
- className,
7
- ...props
8
- }) {
9
- return /* @__PURE__ */ jsx(
10
- "div",
11
- {
12
- className: cn(
13
- "animate-pulse rounded-md bg-tollerud-noir-800",
14
- className
15
- ),
16
- ...props
17
- }
18
- );
19
- }
20
-
21
- export { Skeleton };
22
- //# sourceMappingURL=chunk-FGXOV2QH.js.map
23
- //# sourceMappingURL=chunk-FGXOV2QH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Skeleton.tsx"],"names":[],"mappings":";;;AAEA,SAAS,QAAA,CAAS;AAAA,EAChB,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAyC;AACvC,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,+CAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG;AAAA;AAAA,GACN;AAEJ","file":"chunk-FGXOV2QH.js","sourcesContent":["import { cn } from '@/lib/utils'\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\n 'animate-pulse rounded-md bg-tollerud-noir-800',\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Skeleton }"]}
@@ -1,79 +0,0 @@
1
- 'use client';
2
- import { cn } from './chunk-WSQNPRGN.js';
3
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
-
5
- var defaultLabels = {
6
- tollerudProject: "A Tollerud Project",
7
- allRightsReserved: "All rights reserved."
8
- };
9
- var MONOGRAM_PATH = "M82.4839273,140.272626 L95.1738252,140.272626 L95.1738252,143 L34.8114657,143 L34.8114657,140.272626 L47.5013636,140.272626 L47.5013636,28.2924381 C40.1277806,26.4177752 32.9252955,25.2241422 26.4088393,25.2241422 C12.1757856,25.2241422 4.11617359,34.5982703 4.11617359,39.8821508 C4.11617359,40.9049161 4.63028596,41.5867596 5.65932936,41.5867596 C7.20248513,41.5867596 7.37440169,40.3931266 8.06043062,38.8593855 C10.4615319,33.575505 15.6059302,31.5307881 20.4073141,31.5307881 C29.152955,31.5307881 35.1552988,38.5184637 35.1552988,47.2107482 C35.1552988,56.2447681 28.8107592,62.8907084 18.0070315,62.8907084 C7.5454996,62.891522 0,53.6882617 0,43.8023442 C0,30.8497582 11.3178401,21.986606 26.5799372,21.986606 C51.1026062,21.986606 84.1989996,39.2011209 104.948509,39.2011209 C118.495534,39.2011209 126.384048,31.7016558 126.384048,19.4300996 C126.384048,10.3968933 118.667451,4.60203698 115.580321,4.60203698 C114.552096,4.60203698 113.69415,5.1130128 113.69415,6.13577809 C113.69415,7.49946515 114.552096,7.6695192 115.409223,8.01044097 C115.752237,8.18049502 122.268693,10.5669474 122.268693,19.2592319 C122.268693,28.2924381 115.238125,34.0872945 107.177694,34.0872945 C97.7460244,34.0872945 91.0584702,26.4177752 91.0584702,17.8955448 C91.0584702,6.64675391 99.9760277,0 109.749893,0 C122.268693,0 129.642276,9.88510384 129.642276,19.6001536 C129.642276,34.2581622 119.181563,42.4386572 104.947691,42.4386572 C98.0890388,42.4386572 90.5443579,40.9049161 82.4839273,38.6901451 L82.4839273,140.272626 Z";
10
- function Footer({
11
- labels,
12
- layout = "responsive",
13
- className,
14
- style,
15
- unstyled = false,
16
- accent = false,
17
- classNameInner,
18
- classNameLogo,
19
- classNameText,
20
- classNameLink
21
- }) {
22
- const t = { ...defaultLabels, ...labels };
23
- const attribution = t.attribution?.trim();
24
- const footerSurface = unstyled ? "" : accent ? "border-t border-tollerud-yellow/20 bg-tollerud-yellow/5" : "border-t border-tollerud-border bg-tollerud-noir-900/80";
25
- const innerLayoutClasses = layout === "row" ? "max-w-7xl mx-auto px-8 flex flex-row items-center justify-between gap-4" : "max-w-7xl mx-auto px-8 flex flex-col md:flex-row items-center justify-center md:justify-between gap-4 md:gap-0";
26
- const logoColor = unstyled ? "" : accent ? "text-tollerud-yellow" : "text-tollerud-text-muted";
27
- const textWrapperClasses = layout === "row" ? "flex-1 text-right ml-4" : "flex-1 text-center md:text-right md:ml-4";
28
- const textLayoutClasses = layout === "row" ? "text-sm text-tollerud-text-secondary inline-flex flex-row items-center justify-end text-right gap-0" : "text-sm text-tollerud-text-secondary flex flex-col md:flex-row md:inline gap-0";
29
- return /* @__PURE__ */ jsx("footer", { className: cn("w-full pt-4 pb-4", footerSurface, className), style, children: /* @__PURE__ */ jsxs("div", { className: cn(innerLayoutClasses, classNameInner), children: [
30
- /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 md:flex-shrink-0", children: /* @__PURE__ */ jsxs(
31
- "svg",
32
- {
33
- width: "24",
34
- height: "24",
35
- viewBox: "0 0 130 143",
36
- version: "1.1",
37
- xmlns: "http://www.w3.org/2000/svg",
38
- xmlnsXlink: "http://www.w3.org/1999/xlink",
39
- className: cn("h-5 w-5", logoColor, classNameLogo),
40
- role: "img",
41
- children: [
42
- /* @__PURE__ */ jsx("title", { children: "Tollerud Logo" }),
43
- /* @__PURE__ */ jsx("g", { id: "Page-1", stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd", children: /* @__PURE__ */ jsx("g", { id: "Tollerud-Monogram", transform: "translate(-86.000000, -109.000000)", fill: "currentColor", children: /* @__PURE__ */ jsx("g", { id: "Group-2", transform: "translate(32.000000, 55.000000)", children: /* @__PURE__ */ jsx("g", { id: "Group", transform: "translate(54.000000, 54.000000)", children: /* @__PURE__ */ jsx("path", { d: MONOGRAM_PATH, id: "Monogram" }) }) }) }) })
44
- ]
45
- }
46
- ) }),
47
- /* @__PURE__ */ jsx("div", { className: textWrapperClasses, children: /* @__PURE__ */ jsxs("p", { className: cn(textLayoutClasses, classNameText), children: [
48
- /* @__PURE__ */ jsxs("span", { children: [
49
- /* @__PURE__ */ jsx(
50
- "a",
51
- {
52
- href: "https://tollerud.no",
53
- target: "_blank",
54
- rel: "noopener noreferrer",
55
- className: cn(
56
- "underline decoration-tollerud-yellow decoration-[3px] underline-offset-[4px] hover:opacity-80 transition-opacity",
57
- classNameLink
58
- ),
59
- style: {
60
- textDecorationThickness: "3px",
61
- textUnderlineOffset: "4px"
62
- },
63
- children: t.tollerudProject
64
- }
65
- ),
66
- attribution ? /* @__PURE__ */ jsxs(Fragment, { children: [
67
- " ",
68
- /* @__PURE__ */ jsx("span", { children: attribution })
69
- ] }) : null,
70
- " "
71
- ] }),
72
- /* @__PURE__ */ jsx("span", { className: layout === "row" ? "ml-1" : "md:ml-1", children: t.allRightsReserved })
73
- ] }) })
74
- ] }) });
75
- }
76
-
77
- export { Footer };
78
- //# sourceMappingURL=chunk-HYQGOC2E.js.map
79
- //# sourceMappingURL=chunk-HYQGOC2E.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Footer.tsx"],"names":[],"mappings":";;;AAgBA,IAAM,aAAA,GAA8B;AAAA,EAClC,eAAA,EAAiB,oBAAA;AAAA,EACjB,iBAAA,EAAmB;AACrB,CAAA;AAuBA,IAAM,aAAA,GACJ,0+CAAA;AAEK,SAAS,MAAA,CAAO;AAAA,EACrB,MAAA;AAAA,EACA,MAAA,GAAS,YAAA;AAAA,EACT,SAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX,MAAA,GAAS,KAAA;AAAA,EACT,cAAA;AAAA,EACA,aAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,EAA8B;AAC5B,EAAA,MAAM,CAAA,GAAI,EAAE,GAAG,aAAA,EAAe,GAAG,MAAA,EAAO;AACxC,EAAA,MAAM,WAAA,GAAc,CAAA,CAAE,WAAA,EAAa,IAAA,EAAK;AAExC,EAAA,MAAM,aAAA,GAAgB,QAAA,GAClB,EAAA,GACA,MAAA,GACE,yDAAA,GACA,yDAAA;AAEN,EAAA,MAAM,kBAAA,GACJ,MAAA,KAAW,KAAA,GACP,yEAAA,GACA,gHAAA;AAEN,EAAA,MAAM,SAAA,GAAY,QAAA,GACd,EAAA,GACA,MAAA,GACE,sBAAA,GACA,0BAAA;AAEN,EAAA,MAAM,kBAAA,GACJ,MAAA,KAAW,KAAA,GAAQ,wBAAA,GAA2B,0CAAA;AAEhD,EAAA,MAAM,iBAAA,GACJ,MAAA,KAAW,KAAA,GACP,qGAAA,GACA,gFAAA;AAEN,EAAA,uBACE,GAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAW,EAAA,CAAG,oBAAoB,aAAA,EAAe,SAAS,CAAA,EAAG,KAAA,EACnE,+BAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,kBAAA,EAAoB,cAAc,CAAA,EACnD,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,gCAAA,EACb,QAAA,kBAAA,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAM,IAAA;AAAA,QACN,MAAA,EAAO,IAAA;AAAA,QACP,OAAA,EAAQ,aAAA;AAAA,QACR,OAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAM,4BAAA;AAAA,QACN,UAAA,EAAW,8BAAA;AAAA,QACX,SAAA,EAAW,EAAA,CAAG,SAAA,EAAW,SAAA,EAAW,aAAa,CAAA;AAAA,QACjD,IAAA,EAAK,KAAA;AAAA,QAEL,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,WAAM,QAAA,EAAA,eAAA,EAAa,CAAA;AAAA,8BACnB,GAAA,EAAA,EAAE,EAAA,EAAG,UAAS,MAAA,EAAO,MAAA,EAAO,aAAY,GAAA,EAAI,IAAA,EAAK,MAAA,EAAO,QAAA,EAAS,WAChE,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,IAAG,mBAAA,EAAoB,SAAA,EAAU,sCAAqC,IAAA,EAAK,cAAA,EAC5E,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,IAAG,SAAA,EAAU,SAAA,EAAU,mCACxB,QAAA,kBAAA,GAAA,CAAC,GAAA,EAAA,EAAE,IAAG,OAAA,EAAQ,SAAA,EAAU,mCACtB,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAG,aAAA,EAAe,EAAA,EAAG,YAAW,CAAA,EACxC,CAAA,EACF,GACF,CAAA,EACF;AAAA;AAAA;AAAA,KACF,EACF,CAAA;AAAA,oBAEA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,kBAAA,EACd,QAAA,kBAAA,IAAA,CAAC,OAAE,SAAA,EAAW,EAAA,CAAG,iBAAA,EAAmB,aAAa,CAAA,EAC/C,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,qBAAA;AAAA,YACL,MAAA,EAAO,QAAA;AAAA,YACP,GAAA,EAAI,qBAAA;AAAA,YACJ,SAAA,EAAW,EAAA;AAAA,cACT,kHAAA;AAAA,cACA;AAAA,aACF;AAAA,YACA,KAAA,EAAO;AAAA,cACL,uBAAA,EAAyB,KAAA;AAAA,cACzB,mBAAA,EAAqB;AAAA,aACvB;AAAA,YAEC,QAAA,EAAA,CAAA,CAAE;AAAA;AAAA,SACL;AAAA,QACC,8BACC,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,UAAA,GAAA;AAAA,0BACD,GAAA,CAAC,UAAM,QAAA,EAAA,WAAA,EAAY;AAAA,SAAA,EACrB,CAAA,GACE,IAAA;AAAA,QAAM;AAAA,OAAA,EACZ,CAAA;AAAA,sBACA,GAAA,CAAC,UAAK,SAAA,EAAW,MAAA,KAAW,QAAQ,MAAA,GAAS,SAAA,EAAY,YAAE,iBAAA,EAAkB;AAAA,KAAA,EAC/E,CAAA,EACF;AAAA,GAAA,EACF,CAAA,EACF,CAAA;AAEJ","file":"chunk-HYQGOC2E.js","sourcesContent":["'use client'\n\nimport type { CSSProperties, ReactElement } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport type FooterLabels = {\n /** Text for the tollerud.no link (e.g. \"A Tollerud Project\"). */\n tollerudProject: string\n /**\n * Optional middle segment after the link, before the rights line.\n * Example for Advania: `\"for Advania Norge AS.\"`\n */\n attribution?: string\n allRightsReserved: string\n}\n\nconst defaultLabels: FooterLabels = {\n tollerudProject: 'A Tollerud Project',\n allRightsReserved: 'All rights reserved.',\n}\n\nexport type FooterProps = {\n labels?: Partial<FooterLabels>\n /** Layout behavior: responsive keeps mobile-first stacking, row forces horizontal layout. */\n layout?: 'responsive' | 'row'\n /** Merged onto <footer>. Use for extra layout, padding, etc. */\n className?: string\n /** Merged onto <footer> (wins over conflicting backgroundColor from classes when needed). */\n style?: CSSProperties\n /**\n * When true, skips all default surface styling so className/style fully control the bar\n * (avoids fighting default background/border).\n */\n unstyled?: boolean\n /** When true, uses accent (yellow) surface instead of neutral dark. */\n accent?: boolean\n classNameInner?: string\n classNameLogo?: string\n classNameText?: string\n classNameLink?: string\n}\n\nconst MONOGRAM_PATH =\n 'M82.4839273,140.272626 L95.1738252,140.272626 L95.1738252,143 L34.8114657,143 L34.8114657,140.272626 L47.5013636,140.272626 L47.5013636,28.2924381 C40.1277806,26.4177752 32.9252955,25.2241422 26.4088393,25.2241422 C12.1757856,25.2241422 4.11617359,34.5982703 4.11617359,39.8821508 C4.11617359,40.9049161 4.63028596,41.5867596 5.65932936,41.5867596 C7.20248513,41.5867596 7.37440169,40.3931266 8.06043062,38.8593855 C10.4615319,33.575505 15.6059302,31.5307881 20.4073141,31.5307881 C29.152955,31.5307881 35.1552988,38.5184637 35.1552988,47.2107482 C35.1552988,56.2447681 28.8107592,62.8907084 18.0070315,62.8907084 C7.5454996,62.891522 0,53.6882617 0,43.8023442 C0,30.8497582 11.3178401,21.986606 26.5799372,21.986606 C51.1026062,21.986606 84.1989996,39.2011209 104.948509,39.2011209 C118.495534,39.2011209 126.384048,31.7016558 126.384048,19.4300996 C126.384048,10.3968933 118.667451,4.60203698 115.580321,4.60203698 C114.552096,4.60203698 113.69415,5.1130128 113.69415,6.13577809 C113.69415,7.49946515 114.552096,7.6695192 115.409223,8.01044097 C115.752237,8.18049502 122.268693,10.5669474 122.268693,19.2592319 C122.268693,28.2924381 115.238125,34.0872945 107.177694,34.0872945 C97.7460244,34.0872945 91.0584702,26.4177752 91.0584702,17.8955448 C91.0584702,6.64675391 99.9760277,0 109.749893,0 C122.268693,0 129.642276,9.88510384 129.642276,19.6001536 C129.642276,34.2581622 119.181563,42.4386572 104.947691,42.4386572 C98.0890388,42.4386572 90.5443579,40.9049161 82.4839273,38.6901451 L82.4839273,140.272626 Z'\n\nexport function Footer({\n labels,\n layout = 'responsive',\n className,\n style,\n unstyled = false,\n accent = false,\n classNameInner,\n classNameLogo,\n classNameText,\n classNameLink,\n}: FooterProps): ReactElement {\n const t = { ...defaultLabels, ...labels }\n const attribution = t.attribution?.trim()\n\n const footerSurface = unstyled\n ? ''\n : accent\n ? 'border-t border-tollerud-yellow/20 bg-tollerud-yellow/5'\n : 'border-t border-tollerud-border bg-tollerud-noir-900/80'\n\n const innerLayoutClasses =\n layout === 'row'\n ? 'max-w-7xl mx-auto px-8 flex flex-row items-center justify-between gap-4'\n : 'max-w-7xl mx-auto px-8 flex flex-col md:flex-row items-center justify-center md:justify-between gap-4 md:gap-0'\n\n const logoColor = unstyled\n ? ''\n : accent\n ? 'text-tollerud-yellow'\n : 'text-tollerud-text-muted'\n\n const textWrapperClasses =\n layout === 'row' ? 'flex-1 text-right ml-4' : 'flex-1 text-center md:text-right md:ml-4'\n\n const textLayoutClasses =\n layout === 'row'\n ? 'text-sm text-tollerud-text-secondary inline-flex flex-row items-center justify-end text-right gap-0'\n : 'text-sm text-tollerud-text-secondary flex flex-col md:flex-row md:inline gap-0'\n\n return (\n <footer className={cn('w-full pt-4 pb-4', footerSurface, className)} style={style}>\n <div className={cn(innerLayoutClasses, classNameInner)}>\n <div className=\"flex-shrink-0 md:flex-shrink-0\">\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 130 143\"\n version=\"1.1\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlnsXlink=\"http://www.w3.org/1999/xlink\"\n className={cn('h-5 w-5', logoColor, classNameLogo)}\n role=\"img\"\n >\n <title>Tollerud Logo</title>\n <g id=\"Page-1\" stroke=\"none\" strokeWidth=\"1\" fill=\"none\" fillRule=\"evenodd\">\n <g id=\"Tollerud-Monogram\" transform=\"translate(-86.000000, -109.000000)\" fill=\"currentColor\">\n <g id=\"Group-2\" transform=\"translate(32.000000, 55.000000)\">\n <g id=\"Group\" transform=\"translate(54.000000, 54.000000)\">\n <path d={MONOGRAM_PATH} id=\"Monogram\" />\n </g>\n </g>\n </g>\n </g>\n </svg>\n </div>\n\n <div className={textWrapperClasses}>\n <p className={cn(textLayoutClasses, classNameText)}>\n <span>\n <a\n href=\"https://tollerud.no\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'underline decoration-tollerud-yellow decoration-[3px] underline-offset-[4px] hover:opacity-80 transition-opacity',\n classNameLink,\n )}\n style={{\n textDecorationThickness: '3px',\n textUnderlineOffset: '4px',\n }}\n >\n {t.tollerudProject}\n </a>\n {attribution ? (\n <>\n {' '}\n <span>{attribution}</span>\n </>\n ) : null}{' '}\n </span>\n <span className={layout === 'row' ? 'ml-1' : 'md:ml-1'}>{t.allRightsReserved}</span>\n </p>\n </div>\n </div>\n </footer>\n )\n}"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../components/Pill.tsx"],"names":[],"mappings":";;;;AAGA,IAAM,YAAA,GAAe;AAAA,EACnB,OAAA,EAAS,2EAAA;AAAA,EACT,KAAA,EAAO,uDAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAMA,IAAM,IAAA,GAAO,UAAA;AAAA,EACX,CAAC,EAAE,SAAA,EAAW,OAAA,GAAU,WAAW,GAAG,KAAA,IAAS,GAAA,KAAQ;AACrD,IAAA,uBACE,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,0FAAA;AAAA,UACA,aAAa,OAAO,CAAA;AAAA,UACpB;AAAA,SACF;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;AACA,IAAA,CAAK,WAAA,GAAc,MAAA","file":"chunk-ISHZ6ZPJ.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nconst pillVariants = {\n outline: 'bg-transparent border border-tollerud-border text-tollerud-text-secondary',\n solid: 'bg-tollerud-surface-raised text-tollerud-text-primary',\n accent: 'bg-tollerud-yellow/15 border border-tollerud-yellow/30 text-tollerud-yellow',\n} as const\n\nexport interface PillProps extends HTMLAttributes<HTMLSpanElement> {\n variant?: keyof typeof pillVariants\n}\n\nconst Pill = forwardRef<HTMLSpanElement, PillProps>(\n ({ className, variant = 'outline', ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n 'inline-flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-full leading-none',\n pillVariants[variant],\n className\n )}\n {...props}\n />\n )\n }\n)\nPill.displayName = 'Pill'\n\nexport { Pill }\n"]}
@@ -1 +0,0 @@
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 }"]}
@@ -1 +0,0 @@
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"]}