@tollerud/ui 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +2 -2
- package/CHANGELOG.md +35 -0
- package/SKILL.md +5 -4
- package/dist/avatar.d.ts +3 -2
- package/dist/avatar.js +1 -1
- package/dist/bento-dashboard.js +6 -1
- package/dist/button.d.ts +1 -1
- package/dist/button.js +1 -1
- package/dist/{chunk-7TOT5ME3.js → chunk-3LTW224O.js} +6 -6
- package/dist/chunk-3LTW224O.js.map +1 -0
- package/dist/{chunk-RWJELAS6.js → chunk-ADE22JSR.js} +12 -4
- package/dist/chunk-ADE22JSR.js.map +1 -0
- package/dist/chunk-AQT3FZRQ.js +23 -0
- package/dist/chunk-AQT3FZRQ.js.map +1 -0
- package/dist/{chunk-VTRUUT5K.js → chunk-IUPVQWO5.js} +4 -4
- package/dist/chunk-IUPVQWO5.js.map +1 -0
- package/dist/{chunk-ISHZ6ZPJ.js → chunk-JFOW2DI5.js} +17 -5
- package/dist/chunk-JFOW2DI5.js.map +1 -0
- package/dist/{chunk-OONIUDST.js → chunk-OLHMMFQ7.js} +3 -8
- package/dist/chunk-OLHMMFQ7.js.map +1 -0
- package/dist/chunk-ONMTHBZ4.js +54 -0
- package/dist/chunk-ONMTHBZ4.js.map +1 -0
- package/dist/{chunk-XR5QBVEV.js → chunk-OVSIOZHJ.js} +3 -3
- package/dist/{chunk-XR5QBVEV.js.map → chunk-OVSIOZHJ.js.map} +1 -1
- package/dist/{chunk-V3P5QLLX.js → chunk-Q54CVE3W.js} +3 -3
- package/dist/{chunk-V3P5QLLX.js.map → chunk-Q54CVE3W.js.map} +1 -1
- package/dist/chunk-QEIEWGHA.js +62 -0
- package/dist/chunk-QEIEWGHA.js.map +1 -0
- package/dist/{chunk-CBQ63EBL.js → chunk-QQHBEACI.js} +9 -6
- package/dist/chunk-QQHBEACI.js.map +1 -0
- package/dist/chunk-T3UQ7G4T.js +58 -0
- package/dist/chunk-T3UQ7G4T.js.map +1 -0
- package/dist/{chunk-DGCRHVWW.js → chunk-VFS3V3VY.js} +12 -5
- package/dist/chunk-VFS3V3VY.js.map +1 -0
- package/dist/chunk-VOARBYVQ.js +44 -0
- package/dist/chunk-VOARBYVQ.js.map +1 -0
- package/dist/{chunk-3TGMGBKM.js → chunk-YPP7QHYT.js} +5 -5
- package/dist/{chunk-3TGMGBKM.js.map → chunk-YPP7QHYT.js.map} +1 -1
- package/dist/{chunk-O57QMLNI.js → chunk-YTU7BRDW.js} +16 -12
- package/dist/chunk-YTU7BRDW.js.map +1 -0
- package/dist/{chunk-DFM7UUKB.js → chunk-ZTFOR3AN.js} +4 -4
- package/dist/{chunk-DFM7UUKB.js.map → chunk-ZTFOR3AN.js.map} +1 -1
- package/dist/cta-band.js +1 -1
- package/dist/data-table.js +3 -3
- package/dist/date-picker.js +1 -1
- package/dist/footer.js +2 -1
- package/dist/form-row.d.ts +4 -0
- package/dist/form-row.js +1 -1
- package/dist/hero-block.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -21
- package/dist/monogram.d.ts +20 -0
- package/dist/monogram.js +5 -0
- package/dist/monogram.js.map +1 -0
- package/dist/noir-glow-background.d.ts +7 -1
- package/dist/noir-glow-background.js +1 -1
- package/dist/pill.d.ts +5 -2
- package/dist/pill.js +1 -1
- package/dist/pricing-card.js +2 -2
- package/dist/skeleton.d.ts +10 -2
- package/dist/skeleton.js +1 -1
- package/dist/slider.js +1 -1
- package/dist/switch.js +1 -1
- package/dist/timeline.js +1 -1
- package/globals-layers.css +84 -0
- package/package.json +5 -3
- package/registry.json +17 -1
- package/tokens.css +20 -0
- package/tollerud-avatar-full.png +0 -0
- package/dist/chunk-7TOT5ME3.js.map +0 -1
- package/dist/chunk-CBQ63EBL.js.map +0 -1
- package/dist/chunk-DGCRHVWW.js.map +0 -1
- package/dist/chunk-FGXOV2QH.js +0 -23
- package/dist/chunk-FGXOV2QH.js.map +0 -1
- package/dist/chunk-HYQGOC2E.js +0 -79
- package/dist/chunk-HYQGOC2E.js.map +0 -1
- package/dist/chunk-ISHZ6ZPJ.js.map +0 -1
- package/dist/chunk-O57QMLNI.js.map +0 -1
- package/dist/chunk-OONIUDST.js.map +0 -1
- package/dist/chunk-PLF3BBQI.js +0 -139
- package/dist/chunk-PLF3BBQI.js.map +0 -1
- package/dist/chunk-Q74VRQEX.js +0 -26
- package/dist/chunk-Q74VRQEX.js.map +0 -1
- package/dist/chunk-RWJELAS6.js.map +0 -1
- package/dist/chunk-VTRUUT5K.js.map +0 -1
- /package/{tia-full-figure.svg → tollerud-avatar-full.svg} +0 -0
package/AGENTS.md
CHANGED
|
@@ -134,8 +134,8 @@ import { BarChart, AreaChart, Donut, Sparkline, HeroBlock, FeatureCard, CTABand
|
|
|
134
134
|
// Infra / homelab set
|
|
135
135
|
import { HostCard, ServiceHealthCard, DockerStackCard, IncidentCard } from '@tollerud/ui'
|
|
136
136
|
import { ApprovalCard, ActionDiff, AlertInbox, RollbackPlan, BackupStatusPanel } from '@tollerud/ui'
|
|
137
|
-
// Footer
|
|
138
|
-
import { Footer } from '@tollerud/ui' // or: import { Footer } from '@tollerud/footer'
|
|
137
|
+
// Footer & branding
|
|
138
|
+
import { Footer, Monogram } from '@tollerud/ui' // or: import { Footer } from '@tollerud/footer'
|
|
139
139
|
```
|
|
140
140
|
|
|
141
141
|
### Button
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,41 @@
|
|
|
7
7
|
• Never write bold mid-paragraph as a heading substitute — it merges into surrounding text
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
|
+
## 3.1.0 — 2026-06-09 — Monogram component and docs fixes
|
|
11
|
+
|
|
12
|
+
Restores component styling in the docs site, ships the monogram as an npm component, and renames brand avatar assets.
|
|
13
|
+
|
|
14
|
+
### New components
|
|
15
|
+
|
|
16
|
+
- `Monogram` — inline SVG with `color`: `yellow` | `black` | `white`, optional `size` and `title`
|
|
17
|
+
|
|
18
|
+
### Fixes
|
|
19
|
+
|
|
20
|
+
- `Button` — `terminal` variant uses layer classes again
|
|
21
|
+
- `Pill`, `Avatar`, `Skeleton`, `Timeline`, `Switch`, `Slider`, `FormRow` — layer-class / prop adapter fixes
|
|
22
|
+
- `DatePicker` — calendar popover `z-50`
|
|
23
|
+
- `DataTable` — explicit `text-left` on column headers
|
|
24
|
+
- `CTABand` — inline accent bar margin
|
|
25
|
+
- `BentoDashboard` — real infra cards instead of placeholders
|
|
26
|
+
- `Footer` — uses `<Monogram color="yellow" />`
|
|
27
|
+
- `NoirGlowBackground` — `scale` and `offsetX` for edge-biased shader placement
|
|
28
|
+
|
|
29
|
+
### Brand assets
|
|
30
|
+
|
|
31
|
+
- `tia-full-figure.svg` renamed to `tollerud-avatar-full.svg` (plus PNG export)
|
|
32
|
+
- npm exports: `@tollerud/ui/tollerud-avatar-full.svg` and `@tollerud/ui/tollerud-avatar-full.png`
|
|
33
|
+
|
|
34
|
+
### Docs
|
|
35
|
+
|
|
36
|
+
- Docs-only brand layer: `Monogram`, `TiaPortrait`, `TollerudAvatarFull`, `NavLockup` under `@/components/brand`
|
|
37
|
+
- Tailwind `@source` fix, light-mode monogram via `currentColor`, onboarding/auth/foundations page updates
|
|
38
|
+
|
|
39
|
+
### Migration
|
|
40
|
+
|
|
41
|
+
Drop-in. Replace any copied `tia-full-figure` paths with `tollerud-avatar-full`. Use `<Monogram />` instead of inline SVG or `<img src={logo}>` where you need theme-aware fill.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
10
45
|
## 3.0.0 — 2026-06-09 — ESM-only and rich DataTable
|
|
11
46
|
|
|
12
47
|
Ships the full table pattern in npm, drops CommonJS builds, and adds release/props tooling.
|
package/SKILL.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @tollerud/ui clsx tailwind-merge tailwindcss@4 \
|
|
|
20
20
|
npm install @paper-design/shaders-react
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
As of **v3.0.0**, the package is **ESM-only** (no CJS `require` entry). As of **v2.0.0**, Radix, Lucide, Framer Motion, and Sonner are **required peers** (not bundled).
|
|
23
|
+
As of **v3.1.0**, `Monogram` ships as an inline SVG component (`color`: `yellow` | `black` | `white`). As of **v3.0.0**, the package is **ESM-only** (no CJS `require` entry). As of **v2.0.0**, Radix, Lucide, Framer Motion, and Sonner are **required peers** (not bundled).
|
|
24
24
|
|
|
25
25
|
Apply the Tailwind preset when you need extra utilities from `tollerud-preset.js` — `globals.css` already includes tokens and component layers for v4:
|
|
26
26
|
|
|
@@ -445,8 +445,7 @@ import type { IncidentSeverity } from '@tollerud/ui'
|
|
|
445
445
|
### Footer & branding
|
|
446
446
|
|
|
447
447
|
```tsx
|
|
448
|
-
import { Footer } from '@tollerud/ui'
|
|
449
|
-
import logo from '@tollerud/ui/tollerud-logo.svg'
|
|
448
|
+
import { Footer, Monogram } from '@tollerud/ui'
|
|
450
449
|
|
|
451
450
|
<Footer layout="responsive" accent labels={{ tollerudProject: 'A Tollerud Project' }} />
|
|
452
451
|
```
|
|
@@ -454,10 +453,12 @@ The monogram must always sit left of the project name with `gap-2`. Never show t
|
|
|
454
453
|
|
|
455
454
|
```tsx
|
|
456
455
|
<div className="flex items-center gap-2 shrink-0">
|
|
457
|
-
<
|
|
456
|
+
<Monogram color="yellow" className="h-5 w-auto" />
|
|
458
457
|
<span className="font-semibold text-sm text-white">Project Name</span>
|
|
459
458
|
</div>
|
|
460
459
|
```
|
|
460
|
+
|
|
461
|
+
**Monogram** — `color?: 'yellow' | 'black' | 'white'` (default `yellow`), `size?: number`, `title?: string` (default `'Tollerud'`). Brand avatars: `@tollerud/ui/tollerud-avatar.svg`, `tollerud-avatar-full.svg` (+ `.png` variants).
|
|
461
462
|
Monogram sizing: top bar/sidebar expanded → `h-5`, collapsed → `h-6`, footer → `h-4` (handled automatically by `<Footer />`).
|
|
462
463
|
|
|
463
464
|
---
|
package/dist/avatar.d.ts
CHANGED
|
@@ -13,13 +13,14 @@ interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
|
|
|
13
13
|
name?: string;
|
|
14
14
|
/** Explicit fallback content (overrides derived initials) */
|
|
15
15
|
fallback?: React.ReactNode;
|
|
16
|
-
size
|
|
16
|
+
/** Named size token or explicit pixel diameter */
|
|
17
|
+
size?: keyof typeof avatarSizes | number;
|
|
17
18
|
}
|
|
18
19
|
declare const Avatar: react.ForwardRefExoticComponent<AvatarProps & react.RefAttributes<HTMLSpanElement>>;
|
|
19
20
|
interface AvatarGroupProps extends HTMLAttributes<HTMLDivElement> {
|
|
20
21
|
/** Maximum avatars to render before collapsing into a "+N" overflow indicator */
|
|
21
22
|
max?: number;
|
|
22
|
-
size?: keyof typeof avatarSizes;
|
|
23
|
+
size?: keyof typeof avatarSizes | number;
|
|
23
24
|
children: React.ReactNode;
|
|
24
25
|
}
|
|
25
26
|
declare const AvatarGroup: react.ForwardRefExoticComponent<AvatarGroupProps & react.RefAttributes<HTMLDivElement>>;
|
package/dist/avatar.js
CHANGED
package/dist/bento-dashboard.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { BentoDashboard } from './chunk-
|
|
2
|
+
export { BentoDashboard } from './chunk-ONMTHBZ4.js';
|
|
3
|
+
import './chunk-LUM2YJBH.js';
|
|
4
|
+
import './chunk-7EP2T3OW.js';
|
|
5
|
+
import './chunk-DOUDJU4P.js';
|
|
6
|
+
import './chunk-NHPISZWS.js';
|
|
7
|
+
import './chunk-EN4OJCEF.js';
|
|
3
8
|
import './chunk-WSQNPRGN.js';
|
|
4
9
|
//# sourceMappingURL=bento-dashboard.js.map
|
|
5
10
|
//# sourceMappingURL=bento-dashboard.js.map
|
package/dist/button.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare const variants: {
|
|
|
6
6
|
readonly secondary: "bg-transparent text-tollerud-text-primary border-tollerud-border hover:border-tollerud-text-secondary hover:bg-tollerud-surface-hover";
|
|
7
7
|
readonly ghost: "bg-transparent text-tollerud-text-secondary border-transparent hover:text-tollerud-text-primary hover:bg-tollerud-surface-hover";
|
|
8
8
|
readonly destructive: "bg-tollerud-error text-white border-tollerud-error hover:shadow-[0_0_12px_rgba(239,68,68,0.3)]";
|
|
9
|
-
readonly terminal: "font-mono text-tollerud-yellow border-[rgba(255,255,0,0.25)] bg-transparent
|
|
9
|
+
readonly terminal: "font-mono text-tollerud-yellow border-[rgba(255,255,0,0.25)] bg-transparent hover:border-tollerud-yellow hover:shadow-tollerud-glow hover:bg-[rgba(255,255,0,0.05)]";
|
|
10
10
|
};
|
|
11
11
|
declare const sizes: {
|
|
12
12
|
readonly sm: "px-3 py-1 text-sm";
|
package/dist/button.js
CHANGED
|
@@ -23,10 +23,10 @@ var Timeline = forwardRef(
|
|
|
23
23
|
className: cn(
|
|
24
24
|
"tollerud-timeline__dot",
|
|
25
25
|
active && "tollerud-timeline__dot--active",
|
|
26
|
-
item.status === "online" && "
|
|
27
|
-
item.status === "offline" && "
|
|
28
|
-
item.status === "warning" && "
|
|
29
|
-
|
|
26
|
+
item.status === "online" && "tollerud-timeline__dot--online",
|
|
27
|
+
item.status === "offline" && "tollerud-timeline__dot--offline",
|
|
28
|
+
item.status === "warning" && "tollerud-timeline__dot--warning",
|
|
29
|
+
item.status === "idle" && "tollerud-timeline__dot--idle"
|
|
30
30
|
)
|
|
31
31
|
}
|
|
32
32
|
),
|
|
@@ -49,5 +49,5 @@ var Timeline = forwardRef(
|
|
|
49
49
|
Timeline.displayName = "Timeline";
|
|
50
50
|
|
|
51
51
|
export { Timeline };
|
|
52
|
-
//# sourceMappingURL=chunk-
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
52
|
+
//# sourceMappingURL=chunk-3LTW224O.js.map
|
|
53
|
+
//# sourceMappingURL=chunk-3LTW224O.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,gCAAA;AAAA,oBAC5B,IAAA,CAAK,WAAW,SAAA,IAAa,iCAAA;AAAA,oBAC7B,IAAA,CAAK,WAAW,SAAA,IAAa,iCAAA;AAAA,oBAC7B,IAAA,CAAK,WAAW,MAAA,IAAU;AAAA;AAC5B;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-3LTW224O.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' && 'tollerud-timeline__dot--online',\n item.status === 'offline' && 'tollerud-timeline__dot--offline',\n item.status === 'warning' && 'tollerud-timeline__dot--warning',\n item.status === 'idle' && 'tollerud-timeline__dot--idle'\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 }"]}
|
|
@@ -9,7 +9,14 @@ var variants = {
|
|
|
9
9
|
secondary: "bg-transparent text-tollerud-text-primary border-tollerud-border hover:border-tollerud-text-secondary hover:bg-tollerud-surface-hover",
|
|
10
10
|
ghost: "bg-transparent text-tollerud-text-secondary border-transparent hover:text-tollerud-text-primary hover:bg-tollerud-surface-hover",
|
|
11
11
|
destructive: "bg-tollerud-error text-white border-tollerud-error hover:shadow-[0_0_12px_rgba(239,68,68,0.3)]",
|
|
12
|
-
terminal:
|
|
12
|
+
terminal: "font-mono text-tollerud-yellow border-[rgba(255,255,0,0.25)] bg-transparent hover:border-tollerud-yellow hover:shadow-tollerud-glow hover:bg-[rgba(255,255,0,0.05)]"
|
|
13
|
+
};
|
|
14
|
+
var variantLayers = {
|
|
15
|
+
primary: "tollerud-btn--primary",
|
|
16
|
+
secondary: "",
|
|
17
|
+
ghost: "",
|
|
18
|
+
destructive: "",
|
|
19
|
+
terminal: "tollerud-btn--terminal"
|
|
13
20
|
};
|
|
14
21
|
var sizes = {
|
|
15
22
|
sm: "px-3 py-1 text-sm",
|
|
@@ -18,10 +25,11 @@ var sizes = {
|
|
|
18
25
|
};
|
|
19
26
|
function buttonVariants({ variant = "secondary", size = "md", className } = {}) {
|
|
20
27
|
return cn(
|
|
21
|
-
"inline-flex items-center justify-center gap-2 font-semibold rounded transition-all duration-[150ms] focus-visible:outline-2 focus-visible:outline-tollerud-yellow focus-visible:outline-offset-2",
|
|
28
|
+
"tollerud-btn inline-flex items-center justify-center gap-2 font-semibold rounded transition-all duration-[150ms] focus-visible:outline-2 focus-visible:outline-tollerud-yellow focus-visible:outline-offset-2",
|
|
22
29
|
"border cursor-pointer",
|
|
23
30
|
"disabled:opacity-50 disabled:pointer-events-none",
|
|
24
31
|
variants[variant],
|
|
32
|
+
variantLayers[variant],
|
|
25
33
|
sizes[size],
|
|
26
34
|
className
|
|
27
35
|
);
|
|
@@ -42,5 +50,5 @@ var Button = forwardRef(
|
|
|
42
50
|
Button.displayName = "Button";
|
|
43
51
|
|
|
44
52
|
export { Button, buttonVariants };
|
|
45
|
-
//# sourceMappingURL=chunk-
|
|
46
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-ADE22JSR.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-ADE22JSR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/Button.tsx"],"names":[],"mappings":";;;;;AAIA,IAAM,QAAA,GAAW;AAAA,EACf,OAAA,EAAS,mHAAA;AAAA,EACT,SAAA,EAAW,uIAAA;AAAA,EACX,KAAA,EAAO,iIAAA;AAAA,EACP,WAAA,EAAa,gGAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAGA,IAAM,aAAA,GAAgB;AAAA,EACpB,OAAA,EAAS,uBAAA;AAAA,EACT,SAAA,EAAW,EAAA;AAAA,EACX,KAAA,EAAO,EAAA;AAAA,EACP,WAAA,EAAa,EAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAEA,IAAM,KAAA,GAAQ;AAAA,EACZ,EAAA,EAAI,mBAAA;AAAA,EACJ,EAAA,EAAI,qBAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAOO,SAAS,cAAA,CAAe,EAAE,OAAA,GAAU,WAAA,EAAa,OAAO,IAAA,EAAM,SAAA,EAAU,GAAiD,EAAC,EAAG;AAClI,EAAA,OAAO,EAAA;AAAA,IACL,+MAAA;AAAA,IACA,uBAAA;AAAA,IACA,kDAAA;AAAA,IACA,SAAS,OAAO,CAAA;AAAA,IAChB,cAAc,OAAO,CAAA;AAAA,IACrB,MAAM,IAAI,CAAA;AAAA,IACV;AAAA,GACF;AACF;AAOA,IAAM,MAAA,GAAS,UAAA;AAAA,EACb,CAAC,EAAE,SAAA,EAAW,OAAA,GAAU,WAAA,EAAa,IAAA,GAAO,IAAA,EAAM,OAAA,GAAU,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACrF,IAAA,MAAM,IAAA,GAAO,UAAU,IAAA,GAAO,QAAA;AAC9B,IAAA,uBACE,GAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAW,cAAA,CAAe,EAAE,OAAA,EAAS,IAAA,EAAM,WAAW,CAAA;AAAA,QACrD,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"chunk-ADE22JSR.js","sourcesContent":["import { type ButtonHTMLAttributes, forwardRef } from 'react'\nimport { Slot } from '@radix-ui/react-slot'\nimport { cn } from '@/lib/utils'\n\nconst variants = {\n primary: 'bg-tollerud-yellow text-tollerud-black border-tollerud-yellow hover:bg-tollerud-yellow hover:shadow-tollerud-glow',\n secondary: 'bg-transparent text-tollerud-text-primary border-tollerud-border hover:border-tollerud-text-secondary hover:bg-tollerud-surface-hover',\n ghost: 'bg-transparent text-tollerud-text-secondary border-transparent hover:text-tollerud-text-primary hover:bg-tollerud-surface-hover',\n destructive: 'bg-tollerud-error text-white border-tollerud-error hover:shadow-[0_0_12px_rgba(239,68,68,0.3)]',\n terminal: 'font-mono text-tollerud-yellow border-[rgba(255,255,0,0.25)] bg-transparent hover:border-tollerud-yellow hover:shadow-tollerud-glow hover:bg-[rgba(255,255,0,0.05)]',\n} as const\n\n/** Layer classes from globals-layers.css — ❯ prefix, hover glow, magnetic glow in docs */\nconst variantLayers = {\n primary: 'tollerud-btn--primary',\n secondary: '',\n ghost: '',\n destructive: '',\n terminal: 'tollerud-btn--terminal',\n} as const\n\nconst sizes = {\n sm: 'px-3 py-1 text-sm',\n md: 'px-4 py-2 text-base',\n lg: 'px-6 py-3 text-lg',\n} as const\n\nexport interface ButtonVariantProps {\n variant?: keyof typeof variants\n size?: keyof typeof sizes\n}\n\nexport function buttonVariants({ variant = 'secondary', size = 'md', className }: ButtonVariantProps & { className?: string } = {}) {\n return cn(\n 'tollerud-btn inline-flex items-center justify-center gap-2 font-semibold rounded transition-all duration-[150ms] focus-visible:outline-2 focus-visible:outline-tollerud-yellow focus-visible:outline-offset-2',\n 'border cursor-pointer',\n 'disabled:opacity-50 disabled:pointer-events-none',\n variants[variant],\n variantLayers[variant],\n sizes[size],\n className\n )\n}\n\nexport interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, ButtonVariantProps {\n /** Render as the single child element (e.g. a `<Link>`) instead of a `<button>`, merging props and styles onto it. */\n asChild?: boolean\n}\n\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant = 'secondary', size = 'md', asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button'\n return (\n <Comp\n ref={ref}\n className={buttonVariants({ variant, size, className })}\n {...props}\n />\n )\n }\n)\nButton.displayName = 'Button'\n\nexport { Button }\n"]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function Skeleton({ className, h, w, r, style, ...props }) {
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
"div",
|
|
8
|
+
{
|
|
9
|
+
className: cn("tollerud-skeleton", className),
|
|
10
|
+
style: {
|
|
11
|
+
...h != null ? { height: h } : null,
|
|
12
|
+
...w != null ? { width: w } : null,
|
|
13
|
+
...r != null ? { borderRadius: r } : null,
|
|
14
|
+
...style
|
|
15
|
+
},
|
|
16
|
+
...props
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Skeleton };
|
|
22
|
+
//# sourceMappingURL=chunk-AQT3FZRQ.js.map
|
|
23
|
+
//# sourceMappingURL=chunk-AQT3FZRQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/Skeleton.tsx"],"names":[],"mappings":";;;AAWA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAW,CAAA,EAAG,GAAG,CAAA,EAAG,KAAA,EAAO,GAAG,KAAA,EAAM,EAAkB;AACxE,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,mBAAA,EAAqB,SAAS,CAAA;AAAA,MAC5C,KAAA,EAAO;AAAA,QACL,GAAI,CAAA,IAAK,IAAA,GAAO,EAAE,MAAA,EAAQ,GAAE,GAAI,IAAA;AAAA,QAChC,GAAI,CAAA,IAAK,IAAA,GAAO,EAAE,KAAA,EAAO,GAAE,GAAI,IAAA;AAAA,QAC/B,GAAI,CAAA,IAAK,IAAA,GAAO,EAAE,YAAA,EAAc,GAAE,GAAI,IAAA;AAAA,QACtC,GAAG;AAAA,OACL;AAAA,MACC,GAAG;AAAA;AAAA,GACN;AAEJ","file":"chunk-AQT3FZRQ.js","sourcesContent":["import { cn } from '@/lib/utils'\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {\n /** Shorthand height in px (or any CSS length via className) */\n h?: number | string\n /** Shorthand width in px or percentage string e.g. \"60%\" */\n w?: number | string\n /** Shorthand border-radius in px */\n r?: number | string\n}\n\nfunction Skeleton({ className, h, w, r, style, ...props }: SkeletonProps) {\n return (\n <div\n className={cn('tollerud-skeleton', className)}\n style={{\n ...(h != null ? { height: h } : null),\n ...(w != null ? { width: w } : null),\n ...(r != null ? { borderRadius: r } : null),\n ...style,\n }}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n"]}
|
|
@@ -10,7 +10,7 @@ var CTABand = forwardRef(
|
|
|
10
10
|
{
|
|
11
11
|
ref,
|
|
12
12
|
className: cn(
|
|
13
|
-
"rounded-xl border border-tollerud-border bg-tollerud-surface px-8 py-11 text-center",
|
|
13
|
+
"tollerud-card rounded-xl border border-tollerud-border bg-tollerud-surface px-8 py-11 text-center",
|
|
14
14
|
className
|
|
15
15
|
),
|
|
16
16
|
...props,
|
|
@@ -18,7 +18,7 @@ var CTABand = forwardRef(
|
|
|
18
18
|
/* @__PURE__ */ jsx("h2", { className: "tollerud-display text-[30px] text-tollerud-text-primary", children: title }),
|
|
19
19
|
description && /* @__PURE__ */ jsx("p", { className: "mx-auto mt-3 max-w-[440px] text-[15px] text-tollerud-text-secondary", children: description }),
|
|
20
20
|
actions && /* @__PURE__ */ jsx("div", { className: "mt-[22px] flex flex-wrap items-center justify-center gap-3", children: actions }),
|
|
21
|
-
accentBar && /* @__PURE__ */ jsx("hr", { className: "tollerud-accent-bar mx-auto mt-8 max-w-[320px] border-0" })
|
|
21
|
+
accentBar && /* @__PURE__ */ jsx("hr", { className: "tollerud-accent-bar tollerud-accent-bar--inline mx-auto mt-8 max-w-[320px] border-0" })
|
|
22
22
|
]
|
|
23
23
|
}
|
|
24
24
|
);
|
|
@@ -27,5 +27,5 @@ var CTABand = forwardRef(
|
|
|
27
27
|
CTABand.displayName = "CTABand";
|
|
28
28
|
|
|
29
29
|
export { CTABand };
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
30
|
+
//# sourceMappingURL=chunk-IUPVQWO5.js.map
|
|
31
|
+
//# sourceMappingURL=chunk-IUPVQWO5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/CTABand.tsx"],"names":[],"mappings":";;;;AAUA,IAAM,OAAA,GAAU,UAAA;AAAA,EACd,CAAC,EAAE,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,SAAA,GAAY,IAAA,EAAM,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC/E,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,mGAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,yDAAA,EAA2D,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,UAC9E,WAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uEACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,UAED,OAAA,oBACC,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8DAA8D,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,UAEtF,SAAA,oBACC,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qFAAA,EAAsF;AAAA;AAAA;AAAA,KAExG;AAAA,EAEJ;AACF;AACA,OAAA,CAAQ,WAAA,GAAc,SAAA","file":"chunk-IUPVQWO5.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface CTABandProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n title: React.ReactNode\n description?: React.ReactNode\n actions?: React.ReactNode\n accentBar?: boolean\n}\n\nconst CTABand = forwardRef<HTMLDivElement, CTABandProps>(\n ({ className, title, description, actions, accentBar = true, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'tollerud-card rounded-xl border border-tollerud-border bg-tollerud-surface px-8 py-11 text-center',\n className\n )}\n {...props}\n >\n <h2 className=\"tollerud-display text-[30px] text-tollerud-text-primary\">{title}</h2>\n {description && (\n <p className=\"mx-auto mt-3 max-w-[440px] text-[15px] text-tollerud-text-secondary\">\n {description}\n </p>\n )}\n {actions && (\n <div className=\"mt-[22px] flex flex-wrap items-center justify-center gap-3\">{actions}</div>\n )}\n {accentBar && (\n <hr className=\"tollerud-accent-bar tollerud-accent-bar--inline mx-auto mt-8 max-w-[320px] border-0\" />\n )}\n </div>\n )\n }\n)\nCTABand.displayName = 'CTABand'\n\nexport { CTABand }\n"]}
|
|
@@ -3,9 +3,20 @@ import { cn } from './chunk-WSQNPRGN.js';
|
|
|
3
3
|
import { forwardRef } from 'react';
|
|
4
4
|
import { jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
|
+
var pillLayers = {
|
|
7
|
+
outline: "tollerud-pill--outline",
|
|
8
|
+
muted: "tollerud-pill--muted",
|
|
9
|
+
success: "tollerud-pill--success",
|
|
10
|
+
error: "tollerud-pill--error",
|
|
11
|
+
solid: "",
|
|
12
|
+
accent: ""
|
|
13
|
+
};
|
|
6
14
|
var pillVariants = {
|
|
7
|
-
outline: "
|
|
8
|
-
|
|
15
|
+
outline: "",
|
|
16
|
+
muted: "",
|
|
17
|
+
success: "",
|
|
18
|
+
error: "",
|
|
19
|
+
solid: "bg-tollerud-surface-raised text-tollerud-text-primary border-transparent",
|
|
9
20
|
accent: "bg-tollerud-yellow/15 border border-tollerud-yellow/30 text-tollerud-yellow"
|
|
10
21
|
};
|
|
11
22
|
var Pill = forwardRef(
|
|
@@ -15,7 +26,8 @@ var Pill = forwardRef(
|
|
|
15
26
|
{
|
|
16
27
|
ref,
|
|
17
28
|
className: cn(
|
|
18
|
-
"inline-flex items-center gap-1
|
|
29
|
+
"tollerud-pill inline-flex items-center gap-1 leading-none",
|
|
30
|
+
pillLayers[variant],
|
|
19
31
|
pillVariants[variant],
|
|
20
32
|
className
|
|
21
33
|
),
|
|
@@ -27,5 +39,5 @@ var Pill = forwardRef(
|
|
|
27
39
|
Pill.displayName = "Pill";
|
|
28
40
|
|
|
29
41
|
export { Pill };
|
|
30
|
-
//# sourceMappingURL=chunk-
|
|
31
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-JFOW2DI5.js.map
|
|
43
|
+
//# sourceMappingURL=chunk-JFOW2DI5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/Pill.tsx"],"names":[],"mappings":";;;;AAIA,IAAM,UAAA,GAAa;AAAA,EACjB,OAAA,EAAS,wBAAA;AAAA,EACT,KAAA,EAAO,sBAAA;AAAA,EACP,OAAA,EAAS,wBAAA;AAAA,EACT,KAAA,EAAO,sBAAA;AAAA,EACP,KAAA,EAAO,EAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAEA,IAAM,YAAA,GAAe;AAAA,EACnB,OAAA,EAAS,EAAA;AAAA,EACT,KAAA,EAAO,EAAA;AAAA,EACP,OAAA,EAAS,EAAA;AAAA,EACT,KAAA,EAAO,EAAA;AAAA,EACP,KAAA,EAAO,0EAAA;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,2DAAA;AAAA,UACA,WAAW,OAAO,CAAA;AAAA,UAClB,aAAa,OAAO,CAAA;AAAA,UACpB;AAAA,SACF;AAAA,QACC,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AACF;AACA,IAAA,CAAK,WAAA,GAAc,MAAA","file":"chunk-JFOW2DI5.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\n/** Layer classes from globals-layers.css — colored mono tags */\nconst pillLayers = {\n outline: 'tollerud-pill--outline',\n muted: 'tollerud-pill--muted',\n success: 'tollerud-pill--success',\n error: 'tollerud-pill--error',\n solid: '',\n accent: '',\n} as const\n\nconst pillVariants = {\n outline: '',\n muted: '',\n success: '',\n error: '',\n solid: 'bg-tollerud-surface-raised text-tollerud-text-primary border-transparent',\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 'tollerud-pill inline-flex items-center gap-1 leading-none',\n pillLayers[variant],\n pillVariants[variant],\n className\n )}\n {...props}\n />\n )\n }\n)\nPill.displayName = 'Pill'\n\nexport { Pill }\n"]}
|
|
@@ -25,12 +25,7 @@ var Slider = forwardRef(
|
|
|
25
25
|
defaultValue,
|
|
26
26
|
onChange: (e) => onChange?.(Number(e.target.value)),
|
|
27
27
|
className: cn(
|
|
28
|
-
"
|
|
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",
|
|
28
|
+
"tollerud-slider cursor-pointer accent-tollerud-yellow",
|
|
34
29
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-tollerud-yellow/50",
|
|
35
30
|
"disabled:opacity-40 disabled:pointer-events-none",
|
|
36
31
|
className
|
|
@@ -44,5 +39,5 @@ var Slider = forwardRef(
|
|
|
44
39
|
Slider.displayName = "Slider";
|
|
45
40
|
|
|
46
41
|
export { Slider };
|
|
47
|
-
//# sourceMappingURL=chunk-
|
|
48
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-OLHMMFQ7.js.map
|
|
43
|
+
//# sourceMappingURL=chunk-OLHMMFQ7.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,uDAAA;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-OLHMMFQ7.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 'tollerud-slider cursor-pointer accent-tollerud-yellow',\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,54 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { StatCard } from './chunk-LUM2YJBH.js';
|
|
3
|
+
import { ServiceHealthCard } from './chunk-7EP2T3OW.js';
|
|
4
|
+
import { HostCard } from './chunk-DOUDJU4P.js';
|
|
5
|
+
import { IncidentCard } from './chunk-EN4OJCEF.js';
|
|
6
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
7
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
function BentoDashboard({
|
|
10
|
+
title,
|
|
11
|
+
hosts = [],
|
|
12
|
+
metrics = [],
|
|
13
|
+
services = [],
|
|
14
|
+
incidents = [],
|
|
15
|
+
className
|
|
16
|
+
}) {
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
19
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-tollerud-text-primary", children: title }),
|
|
20
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-tollerud-text-muted", children: [
|
|
21
|
+
hosts.length,
|
|
22
|
+
" hosts \xB7 ",
|
|
23
|
+
services.length,
|
|
24
|
+
" services",
|
|
25
|
+
incidents.length > 0 && ` \xB7 ${incidents.length} active incident${incidents.length > 1 ? "s" : ""}`
|
|
26
|
+
] })
|
|
27
|
+
] }) }),
|
|
28
|
+
hosts.length > 0 && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: [
|
|
29
|
+
/* @__PURE__ */ jsx("div", { className: "md:col-span-2 lg:col-span-1", children: /* @__PURE__ */ jsx(HostCard, { ...hosts[0] }) }),
|
|
30
|
+
/* @__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(HostCard, { ...h }, h.hostname ?? i)) })
|
|
31
|
+
] }),
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-3 gap-3", children: [
|
|
33
|
+
metrics.length > 0 && /* @__PURE__ */ jsxs("div", { className: "lg:col-span-2", children: [
|
|
34
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Metrics" }),
|
|
35
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-4 gap-2", children: metrics.map((m, i) => /* @__PURE__ */ jsx(StatCard, { ...m }, m.label ?? i)) })
|
|
36
|
+
] }),
|
|
37
|
+
services.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
38
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Services" }),
|
|
39
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: services.slice(0, 4).map((s, i) => /* @__PURE__ */ jsx(ServiceHealthCard, { ...s }, s.service ?? i)) })
|
|
40
|
+
] })
|
|
41
|
+
] }),
|
|
42
|
+
incidents.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
43
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Recent Incidents" }),
|
|
44
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: incidents.slice(0, 4).map((inc, i) => /* @__PURE__ */ jsx(IncidentCard, { ...inc }, inc.title + i)) })
|
|
45
|
+
] })
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
function SectionLabel({ children }) {
|
|
49
|
+
return /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider mb-2", children });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { BentoDashboard };
|
|
53
|
+
//# sourceMappingURL=chunk-ONMTHBZ4.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-ONMTHBZ4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/BentoDashboard.tsx"],"names":[],"mappings":";;;;;;;AAyBO,SAAS,cAAA,CAAe;AAAA,EAC7B,KAAA;AAAA,EACA,QAAQ,EAAC;AAAA,EACT,UAAU,EAAC;AAAA,EACX,WAAW,EAAC;AAAA,EACZ,YAAY,EAAC;AAAA,EACb;AACF,CAAA,EAAwB;AACtB,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,WAAA,EAAa,SAAS,CAAA,EAEvC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,mCAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,kDAAA,EAAoD,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBACxE,IAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,kCAAA,EACV,QAAA,EAAA;AAAA,QAAA,KAAA,CAAM,MAAA;AAAA,QAAO,cAAA;AAAA,QAAU,QAAA,CAAS,MAAA;AAAA,QAAO,WAAA;AAAA,QACvC,SAAA,CAAU,MAAA,GAAS,CAAA,IAAK,CAAA,MAAA,EAAM,SAAA,CAAU,MAAM,CAAA,gBAAA,EAAmB,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,GAAA,GAAM,EAAE,CAAA;AAAA,OAAA,EACnG;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,IAGC,MAAM,MAAA,GAAS,CAAA,oBACd,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,uCAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,WAAU,6BAAA,EACb,QAAA,kBAAA,GAAA,CAAC,YAAU,GAAG,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,EAC1B,CAAA;AAAA,sBACA,GAAA,CAAC,SAAI,SAAA,EAAU,oDAAA,EACZ,gBAAM,KAAA,CAAM,CAAC,EAAE,GAAA,CAAI,CAAC,GAAG,CAAA,qBACtB,GAAA,CAAC,YAAgC,GAAG,CAAA,EAAA,EAArB,EAAE,QAAA,IAAY,CAAU,CACxC,CAAA,EACH;AAAA,KAAA,EACF,CAAA;AAAA,oBAIF,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EACZ,QAAA,EAAA;AAAA,MAAA,OAAA,CAAQ,MAAA,GAAS,CAAA,oBAChB,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,eAAA,EACb,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,gBAAa,QAAA,EAAA,SAAA,EAAO,CAAA;AAAA,4BACpB,KAAA,EAAA,EAAI,SAAA,EAAU,uCAAA,EACZ,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAC,CAAA,EAAG,CAAA,qBACf,GAAA,CAAC,YAA6B,GAAG,CAAA,EAAA,EAAlB,EAAE,KAAA,IAAS,CAAU,CACrC,CAAA,EACH;AAAA,OAAA,EACF,CAAA;AAAA,MAGD,QAAA,CAAS,MAAA,GAAS,CAAA,oBACjB,IAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,gBAAa,QAAA,EAAA,UAAA,EAAQ,CAAA;AAAA,wBACtB,GAAA,CAAC,SAAI,SAAA,EAAU,WAAA,EACZ,mBAAS,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,yBAC3B,iBAAA,EAAA,EAAwC,GAAG,KAApB,CAAA,CAAE,OAAA,IAAW,CAAU,CAChD,CAAA,EACH;AAAA,OAAA,EACF;AAAA,KAAA,EAEJ,CAAA;AAAA,IAGC,SAAA,CAAU,MAAA,GAAS,CAAA,oBAClB,IAAA,CAAC,KAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,gBAAa,QAAA,EAAA,kBAAA,EAAgB,CAAA;AAAA,sBAC9B,GAAA,CAAC,SAAI,SAAA,EAAU,aAAA,EACZ,oBAAU,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,yBAC9B,YAAA,EAAA,EAAkC,GAAG,OAAnB,GAAA,CAAI,KAAA,GAAQ,CAAY,CAC5C,CAAA,EACH;AAAA,KAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ;AAEA,SAAS,YAAA,CAAa,EAAE,QAAA,EAAS,EAA4B;AAC3D,EAAA,uBACE,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,8EAAA,EAAgF,QAAA,EAAS,CAAA;AAE1G","file":"chunk-ONMTHBZ4.js","sourcesContent":["'use client'\n\nimport { type ReactNode } from 'react'\nimport { cn } from '@/lib/utils'\nimport { HostCard, type HostCardProps } from './HostCard'\nimport { StatCard, type StatCardProps } from './StatCard'\nimport { ServiceHealthCard, type ServiceHealthCardProps } from './ServiceHealthCard'\nimport { IncidentCard } from './IncidentCard'\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 <div className=\"md:col-span-2 lg:col-span-1\">\n <HostCard {...hosts[0]} />\n </div>\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 <HostCard key={h.hostname ?? i} {...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.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 <StatCard key={m.label ?? i} {...m} />\n ))}\n </div>\n </div>\n )}\n\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 <ServiceHealthCard key={s.service ?? i} {...s} />\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 <IncidentCard key={inc.title + i} {...inc} />\n ))}\n </div>\n </div>\n )}\n </div>\n )\n}\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\nexport default BentoDashboard\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { Button } from './chunk-
|
|
2
|
+
import { Button } from './chunk-ADE22JSR.js';
|
|
3
3
|
import { cn } from './chunk-WSQNPRGN.js';
|
|
4
4
|
import { forwardRef } from 'react';
|
|
5
5
|
import { Check } from 'lucide-react';
|
|
@@ -52,5 +52,5 @@ var PricingCard = forwardRef(
|
|
|
52
52
|
PricingCard.displayName = "PricingCard";
|
|
53
53
|
|
|
54
54
|
export { PricingCard };
|
|
55
|
-
//# sourceMappingURL=chunk-
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
55
|
+
//# sourceMappingURL=chunk-OVSIOZHJ.js.map
|
|
56
|
+
//# sourceMappingURL=chunk-OVSIOZHJ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../components/PricingCard.tsx"],"names":[],"mappings":";;;;;;AAoBA,IAAM,WAAA,GAAc,UAAA;AAAA,EAClB,CACE;AAAA,IACE,SAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAW,EAAC;AAAA,IACZ,QAAA,GAAW,aAAA;AAAA,IACX,UAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,2CAAA;AAAA,UACA,WACI,0FAAA,GACA,4CAAA;AAAA,UACJ;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0HAAA,EACb,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,4BAEF,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,kDAAA,EAAoD,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,YACtE,WAAA,oBAAe,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oCAAoC,QAAA,EAAA,WAAA,EAAY;AAAA,WAAA,EAC/E,CAAA;AAAA,0BAEA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kEAAA,EAAoE,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,YACzF,MAAA,oBAAU,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oCAAoC,QAAA,EAAA,MAAA,EAAO;AAAA,WAAA,EACxE,CAAA;AAAA,UAEC,QAAA,CAAS,MAAA,GAAS,CAAA,oBACjB,GAAA,CAAC,QAAG,SAAA,EAAU,uBAAA,EACX,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,EAAS,CAAA,qBACtB,IAAA,CAAC,IAAA,EAAA,EAAW,WAAU,+DAAA,EACpB,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,KAAA,EAAA,EAAM,IAAA,EAAM,EAAA,EAAI,SAAA,EAAU,sCAAA,EAAuC,CAAA;AAAA,4BAClE,GAAA,CAAC,UAAM,QAAA,EAAA,OAAA,EAAQ;AAAA,WAAA,EAAA,EAFR,CAGT,CACD,CAAA,EACH,CAAA;AAAA,0BAGF,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,QAAA,GAAW,SAAA,GAAY,aAAa,OAAA,EAAS,UAAA,EAAY,SAAA,EAAU,gBAAA,EACjF,QAAA,EAAA,QAAA,EACH;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-
|
|
1
|
+
{"version":3,"sources":["../components/PricingCard.tsx"],"names":[],"mappings":";;;;;;AAoBA,IAAM,WAAA,GAAc,UAAA;AAAA,EAClB,CACE;AAAA,IACE,SAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,WAAA;AAAA,IACA,WAAW,EAAC;AAAA,IACZ,QAAA,GAAW,aAAA;AAAA,IACX,UAAA;AAAA,IACA,QAAA;AAAA,IACA,KAAA;AAAA,IACA,GAAG;AAAA,KAEL,GAAA,KACG;AACH,IAAA,uBACE,IAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAW,EAAA;AAAA,UACT,2CAAA;AAAA,UACA,WACI,0FAAA,GACA,4CAAA;AAAA,UACJ;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,qBAAA,EACZ,QAAA,EAAA;AAAA,YAAA,KAAA,oBACC,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,0HAAA,EACb,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,4BAEF,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,kDAAA,EAAoD,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,YACtE,WAAA,oBAAe,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,oCAAoC,QAAA,EAAA,WAAA,EAAY;AAAA,WAAA,EAC/E,CAAA;AAAA,0BAEA,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAAA,EACb,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kEAAA,EAAoE,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,YACzF,MAAA,oBAAU,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oCAAoC,QAAA,EAAA,MAAA,EAAO;AAAA,WAAA,EACxE,CAAA;AAAA,UAEC,QAAA,CAAS,MAAA,GAAS,CAAA,oBACjB,GAAA,CAAC,QAAG,SAAA,EAAU,uBAAA,EACX,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,OAAA,EAAS,CAAA,qBACtB,IAAA,CAAC,IAAA,EAAA,EAAW,WAAU,+DAAA,EACpB,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,KAAA,EAAA,EAAM,IAAA,EAAM,EAAA,EAAI,SAAA,EAAU,sCAAA,EAAuC,CAAA;AAAA,4BAClE,GAAA,CAAC,UAAM,QAAA,EAAA,OAAA,EAAQ;AAAA,WAAA,EAAA,EAFR,CAGT,CACD,CAAA,EACH,CAAA;AAAA,0BAGF,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,QAAA,GAAW,SAAA,GAAY,aAAa,OAAA,EAAS,UAAA,EAAY,SAAA,EAAU,gBAAA,EACjF,QAAA,EAAA,QAAA,EACH;AAAA;AAAA;AAAA,KACF;AAAA,EAEJ;AACF;AACA,WAAA,CAAY,WAAA,GAAc,aAAA","file":"chunk-OVSIOZHJ.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { Check } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Button } from './Button'\n\nexport interface PricingCardProps extends HTMLAttributes<HTMLDivElement> {\n name: React.ReactNode\n price: React.ReactNode\n /** Rendered after the price, e.g. \"/month\" */\n period?: React.ReactNode\n description?: React.ReactNode\n features?: React.ReactNode[]\n ctaLabel?: React.ReactNode\n onCtaClick?: () => void\n /** Visually highlights this plan as the recommended/featured option */\n featured?: boolean\n /** Small label shown above the price when featured, e.g. \"Most popular\" */\n badge?: React.ReactNode\n}\n\nconst PricingCard = forwardRef<HTMLDivElement, PricingCardProps>(\n (\n {\n className,\n name,\n price,\n period,\n description,\n features = [],\n ctaLabel = 'Get started',\n onCtaClick,\n featured,\n badge,\n ...props\n },\n ref\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col gap-5 rounded-xl border p-6',\n featured\n ? 'border-tollerud-yellow bg-tollerud-yellow/[0.04] shadow-[0_0_0_1px_rgba(255,255,0,0.15)]'\n : 'border-tollerud-border bg-tollerud-surface',\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-1\">\n {badge && (\n <span className=\"inline-flex w-fit items-center rounded-full bg-tollerud-yellow/15 px-2.5 py-0.5 text-xs font-medium text-tollerud-yellow\">\n {badge}\n </span>\n )}\n <h3 className=\"text-base font-medium text-tollerud-text-primary\">{name}</h3>\n {description && <p className=\"text-sm text-tollerud-text-muted\">{description}</p>}\n </div>\n\n <div className=\"flex items-baseline gap-1\">\n <span className=\"text-3xl font-semibold tracking-tight text-tollerud-text-primary\">{price}</span>\n {period && <span className=\"text-sm text-tollerud-text-muted\">{period}</span>}\n </div>\n\n {features.length > 0 && (\n <ul className=\"flex flex-col gap-2.5\">\n {features.map((feature, i) => (\n <li key={i} className=\"flex items-start gap-2.5 text-sm text-tollerud-text-secondary\">\n <Check size={16} className=\"mt-0.5 shrink-0 text-tollerud-yellow\" />\n <span>{feature}</span>\n </li>\n ))}\n </ul>\n )}\n\n <Button variant={featured ? 'primary' : 'secondary'} onClick={onCtaClick} className=\"mt-auto w-full\">\n {ctaLabel}\n </Button>\n </div>\n )\n }\n)\nPricingCard.displayName = 'PricingCard'\n\nexport { PricingCard }\n"]}
|
|
@@ -94,7 +94,7 @@ function DatePicker({
|
|
|
94
94
|
{
|
|
95
95
|
role: "dialog",
|
|
96
96
|
"aria-label": "Choose date",
|
|
97
|
-
className: "absolute top-full z-
|
|
97
|
+
className: "absolute top-full z-50 mt-1 w-72 rounded-lg border border-tollerud-border bg-tollerud-surface-overlay p-3 shadow-lg",
|
|
98
98
|
children: [
|
|
99
99
|
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between", children: [
|
|
100
100
|
/* @__PURE__ */ jsx(
|
|
@@ -150,5 +150,5 @@ function DatePicker({
|
|
|
150
150
|
DatePicker.displayName = "DatePicker";
|
|
151
151
|
|
|
152
152
|
export { DatePicker };
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
154
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-Q54CVE3W.js.map
|
|
154
|
+
//# sourceMappingURL=chunk-Q54CVE3W.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../components/DatePicker.tsx"],"names":["CalendarIcon"],"mappings":"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","file":"chunk-V3P5QLLX.js","sourcesContent":["'use client'\n\nimport { useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { ChevronLeft, ChevronRight, Calendar as CalendarIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface DatePickerProps {\n value?: Date | null\n defaultValue?: Date | null\n onChange?: (date: Date | null) => void\n label?: string\n error?: string\n placeholder?: string\n /** Format a date for display in the input (defaults to locale short date) */\n formatDate?: (date: Date) => string\n className?: string\n disabled?: boolean\n}\n\nconst defaultFormat = (date: Date) =>\n date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })\n\nfunction isSameDay(a: Date, b: Date) {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\n}\n\nfunction startOfMonth(date: Date) {\n return new Date(date.getFullYear(), date.getMonth(), 1)\n}\n\nfunction buildCalendarGrid(monthDate: Date): (Date | null)[] {\n const first = startOfMonth(monthDate)\n const startWeekday = first.getDay()\n const daysInMonth = new Date(monthDate.getFullYear(), monthDate.getMonth() + 1, 0).getDate()\n\n const cells: (Date | null)[] = []\n for (let i = 0; i < startWeekday; i++) cells.push(null)\n for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(monthDate.getFullYear(), monthDate.getMonth(), d))\n return cells\n}\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nfunction DatePicker({\n value: valueProp,\n defaultValue = null,\n onChange,\n label,\n error,\n placeholder = 'Select a date',\n formatDate = defaultFormat,\n className,\n disabled,\n}: DatePickerProps) {\n const id = useId()\n const rootRef = useRef<HTMLDivElement>(null)\n const isControlled = valueProp !== undefined\n const [internalValue, setInternalValue] = useState<Date | null>(defaultValue)\n const value = isControlled ? valueProp ?? null : internalValue\n\n const [open, setOpen] = useState(false)\n const [viewMonth, setViewMonth] = useState(() => startOfMonth(value ?? new Date()))\n\n const cells = useMemo(() => buildCalendarGrid(viewMonth), [viewMonth])\n\n useEffect(() => {\n if (!open) return\n function onClickOutside(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false)\n }\n function onResize() { setOpen(false) }\n document.addEventListener('mousedown', onClickOutside)\n window.addEventListener('resize', onResize)\n return () => {\n document.removeEventListener('mousedown', onClickOutside)\n window.removeEventListener('resize', onResize)\n }\n }, [open])\n\n const select = (date: Date) => {\n if (!isControlled) setInternalValue(date)\n onChange?.(date)\n setOpen(false)\n }\n\n return (\n <div ref={rootRef} className={cn('relative flex flex-col gap-1', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n <button\n id={id}\n type=\"button\"\n disabled={disabled}\n onClick={() => {\n setViewMonth(startOfMonth(value ?? new Date()))\n setOpen((o) => !o)\n }}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n className={cn(\n 'flex w-full items-center justify-between gap-2 rounded px-3 py-2 text-left text-base',\n 'bg-tollerud-surface-raised border',\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 value ? 'text-tollerud-text-primary' : 'text-tollerud-text-muted',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <span>{value ? formatDate(value) : placeholder}</span>\n <CalendarIcon size={15} className=\"text-tollerud-text-muted\" />\n </button>\n\n {open && (\n <div\n role=\"dialog\"\n aria-label=\"Choose date\"\n className=\"absolute top-full z-20 mt-1 w-72 rounded-lg border border-tollerud-border bg-tollerud-surface-overlay p-3 shadow-lg\"\n >\n <div className=\"mb-2 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n onClick={() => setViewMonth((m) => new Date(m.getFullYear(), m.getMonth() - 1, 1))}\n className=\"rounded p-1 text-tollerud-text-secondary hover:bg-tollerud-surface-hover\"\n >\n <ChevronLeft size={16} />\n </button>\n <span className=\"text-sm font-medium text-tollerud-text-primary\">\n {viewMonth.toLocaleDateString(undefined, { month: 'long', year: 'numeric' })}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n onClick={() => setViewMonth((m) => new Date(m.getFullYear(), m.getMonth() + 1, 1))}\n className=\"rounded p-1 text-tollerud-text-secondary hover:bg-tollerud-surface-hover\"\n >\n <ChevronRight size={16} />\n </button>\n </div>\n\n <div className=\"grid grid-cols-7 gap-1 text-center\">\n {WEEKDAYS.map((d) => (\n <span key={d} className=\"text-[11px] font-medium text-tollerud-text-muted py-1\">\n {d}\n </span>\n ))}\n {cells.map((date, i) => {\n if (!date) return <span key={i} />\n const selected = value ? isSameDay(date, value) : false\n const today = isSameDay(date, new Date())\n return (\n <button\n key={i}\n type=\"button\"\n onClick={() => select(date)}\n className={cn(\n 'h-8 w-8 rounded-full text-sm transition-colors duration-[150ms]',\n selected\n ? 'bg-tollerud-yellow text-tollerud-noir-black font-medium'\n : 'text-tollerud-text-secondary hover:bg-tollerud-surface-hover',\n !selected && today && 'ring-1 ring-tollerud-yellow/40'\n )}\n >\n {date.getDate()}\n </button>\n )\n })}\n </div>\n </div>\n )}\n\n {error && <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>}\n </div>\n )\n}\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\n"]}
|
|
1
|
+
{"version":3,"sources":["../components/DatePicker.tsx"],"names":["CalendarIcon"],"mappings":"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","file":"chunk-Q54CVE3W.js","sourcesContent":["'use client'\n\nimport { useEffect, useId, useMemo, useRef, useState } from 'react'\nimport { ChevronLeft, ChevronRight, Calendar as CalendarIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface DatePickerProps {\n value?: Date | null\n defaultValue?: Date | null\n onChange?: (date: Date | null) => void\n label?: string\n error?: string\n placeholder?: string\n /** Format a date for display in the input (defaults to locale short date) */\n formatDate?: (date: Date) => string\n className?: string\n disabled?: boolean\n}\n\nconst defaultFormat = (date: Date) =>\n date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })\n\nfunction isSameDay(a: Date, b: Date) {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate()\n}\n\nfunction startOfMonth(date: Date) {\n return new Date(date.getFullYear(), date.getMonth(), 1)\n}\n\nfunction buildCalendarGrid(monthDate: Date): (Date | null)[] {\n const first = startOfMonth(monthDate)\n const startWeekday = first.getDay()\n const daysInMonth = new Date(monthDate.getFullYear(), monthDate.getMonth() + 1, 0).getDate()\n\n const cells: (Date | null)[] = []\n for (let i = 0; i < startWeekday; i++) cells.push(null)\n for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(monthDate.getFullYear(), monthDate.getMonth(), d))\n return cells\n}\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nfunction DatePicker({\n value: valueProp,\n defaultValue = null,\n onChange,\n label,\n error,\n placeholder = 'Select a date',\n formatDate = defaultFormat,\n className,\n disabled,\n}: DatePickerProps) {\n const id = useId()\n const rootRef = useRef<HTMLDivElement>(null)\n const isControlled = valueProp !== undefined\n const [internalValue, setInternalValue] = useState<Date | null>(defaultValue)\n const value = isControlled ? valueProp ?? null : internalValue\n\n const [open, setOpen] = useState(false)\n const [viewMonth, setViewMonth] = useState(() => startOfMonth(value ?? new Date()))\n\n const cells = useMemo(() => buildCalendarGrid(viewMonth), [viewMonth])\n\n useEffect(() => {\n if (!open) return\n function onClickOutside(e: MouseEvent) {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false)\n }\n function onResize() { setOpen(false) }\n document.addEventListener('mousedown', onClickOutside)\n window.addEventListener('resize', onResize)\n return () => {\n document.removeEventListener('mousedown', onClickOutside)\n window.removeEventListener('resize', onResize)\n }\n }, [open])\n\n const select = (date: Date) => {\n if (!isControlled) setInternalValue(date)\n onChange?.(date)\n setOpen(false)\n }\n\n return (\n <div ref={rootRef} className={cn('relative flex flex-col gap-1', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n <button\n id={id}\n type=\"button\"\n disabled={disabled}\n onClick={() => {\n setViewMonth(startOfMonth(value ?? new Date()))\n setOpen((o) => !o)\n }}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n className={cn(\n 'flex w-full items-center justify-between gap-2 rounded px-3 py-2 text-left text-base',\n 'bg-tollerud-surface-raised border',\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 value ? 'text-tollerud-text-primary' : 'text-tollerud-text-muted',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <span>{value ? formatDate(value) : placeholder}</span>\n <CalendarIcon size={15} className=\"text-tollerud-text-muted\" />\n </button>\n\n {open && (\n <div\n role=\"dialog\"\n aria-label=\"Choose date\"\n className=\"absolute top-full z-50 mt-1 w-72 rounded-lg border border-tollerud-border bg-tollerud-surface-overlay p-3 shadow-lg\"\n >\n <div className=\"mb-2 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n onClick={() => setViewMonth((m) => new Date(m.getFullYear(), m.getMonth() - 1, 1))}\n className=\"rounded p-1 text-tollerud-text-secondary hover:bg-tollerud-surface-hover\"\n >\n <ChevronLeft size={16} />\n </button>\n <span className=\"text-sm font-medium text-tollerud-text-primary\">\n {viewMonth.toLocaleDateString(undefined, { month: 'long', year: 'numeric' })}\n </span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n onClick={() => setViewMonth((m) => new Date(m.getFullYear(), m.getMonth() + 1, 1))}\n className=\"rounded p-1 text-tollerud-text-secondary hover:bg-tollerud-surface-hover\"\n >\n <ChevronRight size={16} />\n </button>\n </div>\n\n <div className=\"grid grid-cols-7 gap-1 text-center\">\n {WEEKDAYS.map((d) => (\n <span key={d} className=\"text-[11px] font-medium text-tollerud-text-muted py-1\">\n {d}\n </span>\n ))}\n {cells.map((date, i) => {\n if (!date) return <span key={i} />\n const selected = value ? isSameDay(date, value) : false\n const today = isSameDay(date, new Date())\n return (\n <button\n key={i}\n type=\"button\"\n onClick={() => select(date)}\n className={cn(\n 'h-8 w-8 rounded-full text-sm transition-colors duration-[150ms]',\n selected\n ? 'bg-tollerud-yellow text-tollerud-noir-black font-medium'\n : 'text-tollerud-text-secondary hover:bg-tollerud-surface-hover',\n !selected && today && 'ring-1 ring-tollerud-yellow/40'\n )}\n >\n {date.getDate()}\n </button>\n )\n })}\n </div>\n </div>\n )}\n\n {error && <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>}\n </div>\n )\n}\nDatePicker.displayName = 'DatePicker'\n\nexport { DatePicker }\n"]}
|