@tollerud/ui 3.1.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.
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +32 -0
- package/COMPONENTS.md +13 -1
- package/README.md +1 -0
- package/SKILL.md +4 -2
- package/components.json +1 -1
- package/dist/bento-dashboard.js +1 -1
- package/dist/button.d.ts +2 -2
- package/dist/button.js +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/{chunk-ADE22JSR.js → chunk-BQWF5MP7.js} +7 -7
- package/dist/chunk-BQWF5MP7.js.map +1 -0
- package/dist/{chunk-IUPVQWO5.js → chunk-FPFLOYIJ.js} +5 -5
- package/dist/chunk-FPFLOYIJ.js.map +1 -0
- package/dist/{chunk-6SKTH45H.js → chunk-J2Z4ZFVX.js} +29 -18
- package/dist/chunk-J2Z4ZFVX.js.map +1 -0
- package/dist/{chunk-YPP7QHYT.js → chunk-K4ALNUZI.js} +4 -4
- package/dist/{chunk-YPP7QHYT.js.map → chunk-K4ALNUZI.js.map} +1 -1
- package/dist/{chunk-ONMTHBZ4.js → chunk-LGVXEWNB.js} +10 -10
- package/dist/chunk-LGVXEWNB.js.map +1 -0
- package/dist/{chunk-OVSIOZHJ.js → chunk-SNNMZ444.js} +3 -3
- package/dist/{chunk-OVSIOZHJ.js.map → chunk-SNNMZ444.js.map} +1 -1
- package/dist/{chunk-T3TQPOVM.js → chunk-TLEKK53J.js} +5 -8
- package/dist/chunk-TLEKK53J.js.map +1 -0
- package/dist/cta-band.js +1 -1
- package/dist/data-table.js +3 -3
- package/dist/index.js +7 -7
- package/dist/pricing-card.js +2 -2
- package/dist/radio-group.d.ts +6 -0
- package/dist/radio-group.js +1 -1
- package/globals-layers.css +27 -1
- package/package.json +1 -1
- package/registry.json +14 -9
- package/tokens.css +29 -5
- package/dist/chunk-6SKTH45H.js.map +0 -1
- package/dist/chunk-ADE22JSR.js.map +0 -1
- package/dist/chunk-IUPVQWO5.js.map +0 -1
- package/dist/chunk-ONMTHBZ4.js.map +0 -1
- package/dist/chunk-T3TQPOVM.js.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -330,7 +330,9 @@ Monogram sizing: top bar/sidebar expanded → `h-5`, sidebar collapsed → `h-6`
|
|
|
330
330
|
|
|
331
331
|
```html
|
|
332
332
|
<h1 class="tollerud-display text-[70px]">Dark. Monochrome.</h1>
|
|
333
|
-
<h2 class="tollerud-display--secondary text-[40px]">
|
|
333
|
+
<h2 class="tollerud-display--secondary text-[40px]">
|
|
334
|
+
<span class="tollerud-display-shimmer">Yellow where it counts</span>
|
|
335
|
+
</h2>
|
|
334
336
|
```
|
|
335
337
|
|
|
336
338
|
### Container
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,38 @@
|
|
|
7
7
|
• Never write bold mid-paragraph as a heading substitute — it merges into surrounding text
|
|
8
8
|
-->
|
|
9
9
|
|
|
10
|
+
## 3.1.1 — 2026-06-09 — Display shimmer, form indicators, and button fixes
|
|
11
|
+
|
|
12
|
+
Patch release: ships hero text shimmer for consumer apps, fixes secondary/checkbox/radio styling, and polishes docs layout components.
|
|
13
|
+
|
|
14
|
+
### New utilities
|
|
15
|
+
|
|
16
|
+
- `.tollerud-display-shimmer` — animated yellow gradient clipped to text; respects `prefers-reduced-motion` (static `var(--primary)` fallback)
|
|
17
|
+
|
|
18
|
+
### Fixes
|
|
19
|
+
|
|
20
|
+
- `Button` — secondary variant restores raised surface and border (theme-aware CSS vars); all variants apply layer classes again
|
|
21
|
+
- `Checkbox` — checkmark visible on `defaultChecked` and click via `peer-checked` on the custom indicator
|
|
22
|
+
- `RadioGroup` — wires `value`, `onChange`, and `name` to children; inner dot shows when selected
|
|
23
|
+
- `CTABand` — title and description centered in the band
|
|
24
|
+
- `BentoDashboard` — section spacing and label alignment
|
|
25
|
+
- Docs `PageTOC` — restores `jumpToSection` import for in-page scroll
|
|
26
|
+
|
|
27
|
+
### Registry
|
|
28
|
+
|
|
29
|
+
- Top-level `name` → `Tollerud User Interface`; updated description and component metadata for blocks
|
|
30
|
+
|
|
31
|
+
### Docs
|
|
32
|
+
|
|
33
|
+
- Overview, Backgrounds, and Foundations Typography use `.tollerud-display-shimmer` (replaces docs-only `.ds-shimmer`)
|
|
34
|
+
- Light theme shimmer and secondary-button token overrides
|
|
35
|
+
|
|
36
|
+
### Migration
|
|
37
|
+
|
|
38
|
+
Drop-in. Replace any copied `.ds-shimmer` with `.tollerud-display-shimmer` from `@tollerud/ui/globals.css`.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
10
42
|
## 3.1.0 — 2026-06-09 — Monogram component and docs fixes
|
|
11
43
|
|
|
12
44
|
Restores component styling in the docs site, ships the monogram as an npm component, and renames brand avatar assets.
|
package/COMPONENTS.md
CHANGED
|
@@ -786,10 +786,22 @@ The config-driven table. Pass `rows` + a `columns` spec and opt into search, a f
|
|
|
786
786
|
|
|
787
787
|
```html
|
|
788
788
|
<h1 class="tollerud-display text-[70px]">Dark. Monochrome.</h1>
|
|
789
|
-
<h2 class="tollerud-display--secondary text-[40px]">
|
|
789
|
+
<h2 class="tollerud-display--secondary text-[40px]">
|
|
790
|
+
<span class="tollerud-display-shimmer">Yellow where it counts</span>
|
|
791
|
+
</h2>
|
|
790
792
|
<h3 class="tollerud-display--tertiary text-[28px]">Subtle hierarchy</h3>
|
|
791
793
|
```
|
|
792
794
|
|
|
795
|
+
## Display shimmer
|
|
796
|
+
|
|
797
|
+
Animated yellow gradient clipped to text — for hero accent lines and key metrics on **dark surfaces**. Respects `prefers-reduced-motion` (falls back to static `var(--primary)` / `var(--tollerud-yellow)`).
|
|
798
|
+
|
|
799
|
+
```html
|
|
800
|
+
<span class="tollerud-display-shimmer">Yellow where it counts.</span>
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
Pair with `.tollerud-display` on the parent heading. Not for body copy or light backgrounds (yellow fails contrast on white).
|
|
804
|
+
|
|
793
805
|
## Container
|
|
794
806
|
|
|
795
807
|
```jsx
|
package/README.md
CHANGED
|
@@ -288,4 +288,5 @@ New additions inspired by [Graphify Labs](https://graphifylabs.ai/):
|
|
|
288
288
|
| Accent Bar | `.tollerud-accent-bar` | `bg-tollerud-gradient-bar h-[1px]` | Gradient divider bar |
|
|
289
289
|
| Gradient Text | `.tollerud-gradient-text` | `bg-tollerud-gradient-soft bg-clip-text text-transparent` | Yellow → amber gradient text |
|
|
290
290
|
| Display Heading | `.tollerud-display` | `tracking-tightest leading-[0.95] font-semibold text-white` | Tight, impactful display heads |
|
|
291
|
+
| Display Shimmer | `.tollerud-display-shimmer` | — | Animated yellow gradient sweep clipped to hero accent text (dark surfaces) |
|
|
291
292
|
| Section Container | `.tollerud-section` | `max-w-[1100px] mx-auto px-6` | Content width constraint |
|
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.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).
|
|
23
|
+
As of **v3.1.1**, `.tollerud-display-shimmer` ships in `globals.css` for animated hero accent text. 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
|
|
|
@@ -469,7 +469,9 @@ Monogram sizing: top bar/sidebar expanded → `h-5`, collapsed → `h-6`, footer
|
|
|
469
469
|
<nav class="tollerud-glass fixed top-0 inset-x-0 z-50 h-14 flex items-center px-6">…</nav>
|
|
470
470
|
<section class="tollerud-grid-bg">…</section>
|
|
471
471
|
<h1 class="tollerud-display text-[70px]">Dark. Monochrome.</h1>
|
|
472
|
-
<h2 class="tollerud-display--secondary text-[40px]">
|
|
472
|
+
<h2 class="tollerud-display--secondary text-[40px]">
|
|
473
|
+
<span class="tollerud-display-shimmer">Yellow where it counts</span>
|
|
474
|
+
</h2>
|
|
473
475
|
<div data-density="compact">…dense tables / forms…</div>
|
|
474
476
|
```
|
|
475
477
|
|
package/components.json
CHANGED
package/dist/bento-dashboard.js
CHANGED
package/dist/button.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { ButtonHTMLAttributes } from 'react';
|
|
|
3
3
|
|
|
4
4
|
declare const variants: {
|
|
5
5
|
readonly primary: "bg-tollerud-yellow text-tollerud-black border-tollerud-yellow hover:bg-tollerud-yellow hover:shadow-tollerud-glow";
|
|
6
|
-
readonly secondary: "
|
|
7
|
-
readonly ghost: "
|
|
6
|
+
readonly secondary: "text-tollerud-text-primary [background:var(--surface-raised,var(--tollerud-surface-raised))] [border-color:var(--border,var(--tollerud-border))] hover:[border-color:var(--text-secondary,var(--tollerud-text-secondary))] hover:[background:var(--surface-hover,var(--tollerud-surface-hover))]";
|
|
7
|
+
readonly ghost: "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
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
|
};
|
package/dist/button.js
CHANGED
package/dist/checkbox.js
CHANGED
|
@@ -6,16 +6,16 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
6
6
|
|
|
7
7
|
var variants = {
|
|
8
8
|
primary: "bg-tollerud-yellow text-tollerud-black border-tollerud-yellow hover:bg-tollerud-yellow hover:shadow-tollerud-glow",
|
|
9
|
-
secondary: "
|
|
10
|
-
ghost: "
|
|
9
|
+
secondary: "text-tollerud-text-primary [background:var(--surface-raised,var(--tollerud-surface-raised))] [border-color:var(--border,var(--tollerud-border))] hover:[border-color:var(--text-secondary,var(--tollerud-text-secondary))] hover:[background:var(--surface-hover,var(--tollerud-surface-hover))]",
|
|
10
|
+
ghost: "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
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
13
|
};
|
|
14
14
|
var variantLayers = {
|
|
15
15
|
primary: "tollerud-btn--primary",
|
|
16
|
-
secondary: "",
|
|
17
|
-
ghost: "",
|
|
18
|
-
destructive: "",
|
|
16
|
+
secondary: "tollerud-btn--secondary",
|
|
17
|
+
ghost: "tollerud-btn--ghost",
|
|
18
|
+
destructive: "tollerud-btn--destructive",
|
|
19
19
|
terminal: "tollerud-btn--terminal"
|
|
20
20
|
};
|
|
21
21
|
var sizes = {
|
|
@@ -50,5 +50,5 @@ var Button = forwardRef(
|
|
|
50
50
|
Button.displayName = "Button";
|
|
51
51
|
|
|
52
52
|
export { Button, buttonVariants };
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-BQWF5MP7.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-BQWF5MP7.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,EACE,kSAAA;AAAA,EACF,KAAA,EAAO,kHAAA;AAAA,EACP,WAAA,EAAa,gGAAA;AAAA,EACb,QAAA,EAAU;AACZ,CAAA;AAGA,IAAM,aAAA,GAAgB;AAAA,EACpB,OAAA,EAAS,uBAAA;AAAA,EACT,SAAA,EAAW,yBAAA;AAAA,EACX,KAAA,EAAO,qBAAA;AAAA,EACP,WAAA,EAAa,2BAAA;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-BQWF5MP7.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:\n 'text-tollerud-text-primary [background:var(--surface-raised,var(--tollerud-surface-raised))] [border-color:var(--border,var(--tollerud-border))] hover:[border-color:var(--text-secondary,var(--tollerud-text-secondary))] hover:[background:var(--surface-hover,var(--tollerud-surface-hover))]',\n ghost: '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: 'tollerud-btn--secondary',\n ghost: 'tollerud-btn--ghost',\n destructive: 'tollerud-btn--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"]}
|
|
@@ -10,13 +10,13 @@ var CTABand = forwardRef(
|
|
|
10
10
|
{
|
|
11
11
|
ref,
|
|
12
12
|
className: cn(
|
|
13
|
-
"tollerud-card rounded-xl border border-tollerud-border bg-tollerud-surface px-8 py-11 text-center",
|
|
13
|
+
"tollerud-card w-full rounded-xl border border-tollerud-border bg-tollerud-surface px-8 py-11 text-center",
|
|
14
14
|
className
|
|
15
15
|
),
|
|
16
16
|
...props,
|
|
17
17
|
children: [
|
|
18
|
-
/* @__PURE__ */ jsx("h2", { className: "tollerud-display text-[30px] text-tollerud-text-primary", children: title }),
|
|
19
|
-
description && /* @__PURE__ */ jsx("p", { className: "mx-auto mt-3 max-w-[440px] text-[15px] text-tollerud-text-secondary", children: description }),
|
|
18
|
+
/* @__PURE__ */ jsx("h2", { className: "tollerud-display mx-auto max-w-[640px] text-center text-[30px] text-tollerud-text-primary", children: title }),
|
|
19
|
+
description && /* @__PURE__ */ jsx("p", { className: "mx-auto mt-3 max-w-[440px] text-center 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
21
|
accentBar && /* @__PURE__ */ jsx("hr", { className: "tollerud-accent-bar tollerud-accent-bar--inline mx-auto mt-8 max-w-[320px] border-0" })
|
|
22
22
|
]
|
|
@@ -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-FPFLOYIJ.js.map
|
|
31
|
+
//# sourceMappingURL=chunk-FPFLOYIJ.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,0GAAA;AAAA,UACA;AAAA,SACF;AAAA,QACC,GAAG,KAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,2FAAA,EACX,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UACC,WAAA,oBACC,GAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mFACV,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-FPFLOYIJ.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 w-full 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 mx-auto max-w-[640px] text-center text-[30px] text-tollerud-text-primary\">\n {title}\n </h2>\n {description && (\n <p className=\"mx-auto mt-3 max-w-[440px] text-center 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"]}
|
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
-
import { forwardRef, useId } from 'react';
|
|
3
|
+
import { forwardRef, useId, Children, isValidElement, cloneElement } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
var RadioGroup = forwardRef(
|
|
7
|
-
({ label, error, children, className }, ref) => {
|
|
7
|
+
({ label, error, value, onChange, name: nameProp, children, className }, ref) => {
|
|
8
|
+
const autoName = useId();
|
|
9
|
+
const name = nameProp ?? autoName;
|
|
10
|
+
const wired = Children.map(children, (child) => {
|
|
11
|
+
if (!isValidElement(child)) return child;
|
|
12
|
+
const radio = child;
|
|
13
|
+
const optionValue = radio.props.value;
|
|
14
|
+
if (optionValue === void 0) return child;
|
|
15
|
+
const option = String(optionValue);
|
|
16
|
+
const checked = value !== void 0 ? value === option : radio.props.checked;
|
|
17
|
+
return cloneElement(radio, {
|
|
18
|
+
name,
|
|
19
|
+
...checked !== void 0 ? { checked } : {},
|
|
20
|
+
onChange: (e) => {
|
|
21
|
+
radio.props.onChange?.(e);
|
|
22
|
+
if (e.target.checked) onChange?.(option);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
});
|
|
8
26
|
return /* @__PURE__ */ jsxs("fieldset", { ref, className: cn("flex flex-col gap-1", className), children: [
|
|
9
27
|
label && /* @__PURE__ */ jsx("legend", { className: "text-xs font-medium text-tollerud-text-muted mb-1", children: label }),
|
|
10
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children }),
|
|
28
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: wired }),
|
|
11
29
|
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
|
|
12
30
|
] });
|
|
13
31
|
}
|
|
14
32
|
);
|
|
15
33
|
RadioGroup.displayName = "RadioGroup";
|
|
16
34
|
var Radio = forwardRef(
|
|
17
|
-
({ className, label, id: idProp, ...props }, ref) => {
|
|
35
|
+
({ className, label, id: idProp, checked, ...props }, ref) => {
|
|
18
36
|
const autoId = useId();
|
|
19
37
|
const id = idProp ?? autoId;
|
|
20
38
|
return /* @__PURE__ */ jsxs(
|
|
@@ -35,6 +53,7 @@ var Radio = forwardRef(
|
|
|
35
53
|
ref,
|
|
36
54
|
id,
|
|
37
55
|
type: "radio",
|
|
56
|
+
...checked !== void 0 ? { checked } : {},
|
|
38
57
|
className: "peer sr-only",
|
|
39
58
|
...props
|
|
40
59
|
}
|
|
@@ -43,22 +62,14 @@ var Radio = forwardRef(
|
|
|
43
62
|
"span",
|
|
44
63
|
{
|
|
45
64
|
className: cn(
|
|
46
|
-
"h-4 w-4 rounded-full border transition-all duration-[150ms]",
|
|
65
|
+
"flex h-4 w-4 items-center justify-center rounded-full border transition-all duration-[150ms]",
|
|
47
66
|
"bg-tollerud-surface-raised border-tollerud-border",
|
|
48
67
|
"peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow",
|
|
49
68
|
"peer-checked:border-tollerud-yellow",
|
|
50
|
-
"
|
|
51
|
-
"
|
|
69
|
+
"peer-checked:[&>span]:opacity-100",
|
|
70
|
+
"group-hover:border-tollerud-text-secondary"
|
|
52
71
|
),
|
|
53
|
-
children: /* @__PURE__ */ jsx(
|
|
54
|
-
"span",
|
|
55
|
-
{
|
|
56
|
-
className: cn(
|
|
57
|
-
"h-2 w-2 rounded-full bg-tollerud-yellow transition-opacity duration-[150ms]",
|
|
58
|
-
props.checked ? "opacity-100" : "opacity-0"
|
|
59
|
-
)
|
|
60
|
-
}
|
|
61
|
-
)
|
|
72
|
+
children: /* @__PURE__ */ jsx("span", { className: "pointer-events-none h-2 w-2 rounded-full bg-tollerud-yellow opacity-0 transition-opacity duration-[150ms]" })
|
|
62
73
|
}
|
|
63
74
|
)
|
|
64
75
|
] }),
|
|
@@ -71,5 +82,5 @@ var Radio = forwardRef(
|
|
|
71
82
|
Radio.displayName = "Radio";
|
|
72
83
|
|
|
73
84
|
export { Radio, RadioGroup };
|
|
74
|
-
//# sourceMappingURL=chunk-
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-J2Z4ZFVX.js.map
|
|
86
|
+
//# sourceMappingURL=chunk-J2Z4ZFVX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/RadioGroup.tsx"],"names":[],"mappings":"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","file":"chunk-J2Z4ZFVX.js","sourcesContent":["'use client'\n\nimport {\n Children,\n cloneElement,\n isValidElement,\n type InputHTMLAttributes,\n type ReactElement,\n forwardRef,\n useId,\n} from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface RadioGroupProps {\n /** Group label */\n label?: string\n /** Error message */\n error?: string\n /** Controlled selected value */\n value?: string\n /** Called with the selected option value */\n onChange?: (value: string) => void\n /** Shared name for native radio grouping (auto-generated if omitted) */\n name?: string\n children?: React.ReactNode\n className?: string\n}\n\nconst RadioGroup = forwardRef<HTMLFieldSetElement, RadioGroupProps>(\n ({ label, error, value, onChange, name: nameProp, children, className }, ref) => {\n const autoName = useId()\n const name = nameProp ?? autoName\n\n const wired = Children.map(children, (child) => {\n if (!isValidElement(child)) return child\n const radio = child as ReactElement<RadioProps>\n const optionValue = radio.props.value\n if (optionValue === undefined) return child\n\n const option = String(optionValue)\n const checked = value !== undefined ? value === option : radio.props.checked\n\n return cloneElement(radio, {\n name,\n ...(checked !== undefined ? { checked } : {}),\n onChange: (e) => {\n radio.props.onChange?.(e)\n if (e.target.checked) onChange?.(option)\n },\n })\n })\n\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\">{wired}</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, 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 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 {...(checked !== undefined ? { checked } : {})}\n className=\"peer sr-only\"\n {...props}\n />\n {/* Custom radio circle */}\n <span\n className={cn(\n 'flex h-4 w-4 items-center justify-center 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 'peer-checked:[&>span]:opacity-100',\n 'group-hover:border-tollerud-text-secondary'\n )}\n >\n {/* Inner dot — visible when checked (via peer on sibling input) */}\n <span className=\"pointer-events-none h-2 w-2 rounded-full bg-tollerud-yellow opacity-0 transition-opacity duration-[150ms]\" />\n </span>\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nRadio.displayName = 'Radio'\n\nexport { RadioGroup, Radio }"]}
|
|
@@ -3,9 +3,9 @@ import { Skeleton } from './chunk-AQT3FZRQ.js';
|
|
|
3
3
|
import { Segmented } from './chunk-NSMU66ZX.js';
|
|
4
4
|
import { Pagination } from './chunk-RJTDQOT2.js';
|
|
5
5
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuItem } from './chunk-435JHF7G.js';
|
|
6
|
-
import { Checkbox } from './chunk-
|
|
6
|
+
import { Checkbox } from './chunk-TLEKK53J.js';
|
|
7
7
|
import { Badge } from './chunk-QEHTPQHL.js';
|
|
8
|
-
import { Button } from './chunk-
|
|
8
|
+
import { Button } from './chunk-BQWF5MP7.js';
|
|
9
9
|
import { cn } from './chunk-WSQNPRGN.js';
|
|
10
10
|
import { forwardRef, useMemo, useState } from 'react';
|
|
11
11
|
import { Search, X, MoreHorizontal, ChevronDown } from 'lucide-react';
|
|
@@ -389,5 +389,5 @@ var DataTable = forwardRef((props, ref) => /* @__PURE__ */ jsx(DataTableInner, {
|
|
|
389
389
|
DataTable.displayName = "DataTable";
|
|
390
390
|
|
|
391
391
|
export { DataTable };
|
|
392
|
-
//# sourceMappingURL=chunk-
|
|
393
|
-
//# sourceMappingURL=chunk-
|
|
392
|
+
//# sourceMappingURL=chunk-K4ALNUZI.js.map
|
|
393
|
+
//# sourceMappingURL=chunk-K4ALNUZI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../components/DataTable.tsx"],"names":[],"mappings":"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","file":"chunk-YPP7QHYT.js","sourcesContent":["'use client'\n\nimport { useState, useMemo, forwardRef, type ReactNode } from 'react'\nimport { ChevronDown, MoreHorizontal, Search, X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from './Badge'\nimport { Button } from './Button'\nimport { Checkbox } from './Checkbox'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './DropdownMenu'\nimport { Pagination } from './Pagination'\nimport { Segmented } from './Segmented'\nimport { Skeleton } from './Skeleton'\n\n/* ──────────────────── Sortable & Filterable Data Table ──────────────────── */\n\nexport interface Column<T> {\n key: string\n label: string\n sortable?: boolean\n filterable?: boolean\n align?: 'left' | 'center' | 'right'\n width?: string\n render?: (value: unknown, row: T) => ReactNode\n}\n\nexport interface DataTableFilter {\n key: string\n options?: string[]\n allLabel?: string\n}\n\nexport interface DataTableBulkAction {\n label: string\n variant?: 'primary' | 'secondary' | 'ghost' | 'destructive' | 'terminal'\n icon?: ReactNode\n onRun: (selectedIds: (string | number)[], clearSelection: () => void) => void\n}\n\nexport interface DataTableRowMenuItem {\n label: string\n onSelect?: () => void\n icon?: ReactNode\n sep?: boolean\n heading?: boolean\n}\n\nexport interface DataTableProps<T extends Record<string, unknown>> {\n columns: Column<T>[]\n /** Row data — use `data` or `rows` (alias). */\n data?: T[]\n rows?: T[]\n /** Row key extractor — defaults to `row.id` or `row.key` */\n rowKey?: keyof T | ((row: T) => string | number)\n onRowClick?: (row: T) => void\n className?: string\n emptyMessage?: string\n /** Global search across `searchKeys` (or all column keys). */\n searchable?: boolean\n searchKeys?: (keyof T | string)[]\n searchPlaceholder?: string\n /** Segmented filter on a single column value. */\n filter?: DataTableFilter\n selectable?: boolean\n pageSize?: number\n bulkActions?: DataTableBulkAction[]\n rowMenu?: (row: T) => DataTableRowMenuItem[]\n toolbarRight?: ReactNode\n emptyState?: ReactNode\n loading?: boolean\n skeletonRows?: number\n}\n\ninterface DataTableInnerProps<T extends Record<string, unknown>> extends DataTableProps<T> {\n forwardedRef?: React.Ref<HTMLDivElement>\n}\n\nfunction DataTableInner<T extends Record<string, unknown>>({\n columns,\n data,\n rows,\n rowKey,\n onRowClick,\n className,\n emptyMessage = 'No data',\n searchable = false,\n searchKeys,\n searchPlaceholder = 'Search…',\n filter,\n selectable = false,\n pageSize,\n bulkActions = [],\n rowMenu,\n toolbarRight,\n emptyState,\n loading = false,\n skeletonRows = 5,\n forwardedRef,\n}: DataTableInnerProps<T>) {\n const tableData = useMemo(() => rows ?? data ?? [], [rows, data])\n\n const isRich =\n searchable ||\n filter ||\n selectable ||\n pageSize !== undefined ||\n !!rowMenu ||\n !!toolbarRight ||\n bulkActions.length > 0 ||\n !!emptyState ||\n loading\n\n const [sortKey, setSortKey] = useState<string | null>(null)\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')\n const [filters, setFilters] = useState<Record<string, string>>({})\n const [query, setQuery] = useState('')\n const [filterValue, setFilterValue] = useState('all')\n const [selected, setSelected] = useState<(string | number)[]>([])\n const [page, setPage] = useState(1)\n\n const getRowKey = (row: T, i: number): string | number => {\n if (typeof rowKey === 'function') return rowKey(row)\n if (rowKey) return row[rowKey] as string | number\n return (row.id ?? row.key ?? i) as string | number\n }\n\n const toggleSort = (key: string) => {\n if (sortKey === key) {\n setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n } else {\n setSortKey(key)\n setSortDir('asc')\n }\n }\n\n const updateFilter = (key: string, value: string) => {\n setFilters((prev) => {\n const next = { ...prev }\n if (value.trim() === '') {\n delete next[key]\n } else {\n next[key] = value\n }\n return next\n })\n }\n\n const searchKeysResolved = searchKeys ?? columns.map((c) => c.key)\n const filterOptions = filter\n ? (filter.options ?? Array.from(new Set(tableData.map((r) => String(r[filter.key] ?? '')))))\n : []\n\n const filtered = useMemo(() => {\n let result = tableData\n\n if (isRich && filter && filterValue !== 'all') {\n result = result.filter((row) => String(row[filter.key] ?? '') === filterValue)\n }\n\n if (isRich && searchable && query.trim()) {\n const q = query.trim().toLowerCase()\n result = result.filter((row) =>\n searchKeysResolved.some((key) => String(row[key as keyof T] ?? '').toLowerCase().includes(q))\n )\n }\n\n if (!isRich) {\n const activeFilters = Object.entries(filters).filter(([, v]) => v.trim() !== '')\n if (activeFilters.length > 0) {\n result = result.filter((row) =>\n activeFilters.every(([key, filterVal]) => {\n const cellValue = String(row[key] ?? '').toLowerCase()\n return cellValue.includes(filterVal.toLowerCase())\n })\n )\n }\n }\n\n return result\n }, [tableData, filters, isRich, filter, filterValue, searchable, query, searchKeysResolved])\n\n const sorted = useMemo(() => {\n if (!sortKey) return filtered\n const col = columns.find((c) => c.key === sortKey)\n if (!col?.sortable) return filtered\n\n return [...filtered].sort((a, b) => {\n const aVal = a[sortKey]\n const bVal = b[sortKey]\n\n if (typeof aVal === 'number' && typeof bVal === 'number') {\n return sortDir === 'asc' ? aVal - bVal : bVal - aVal\n }\n\n const aStr = String(aVal ?? '')\n const bStr = String(bVal ?? '')\n const cmp = aStr.localeCompare(bStr, 'nb', { numeric: true })\n return sortDir === 'asc' ? cmp : -cmp\n })\n }, [filtered, sortKey, sortDir, columns])\n\n const pageCount = pageSize ? Math.max(1, Math.ceil(sorted.length / pageSize)) : 1\n const currentPage = Math.min(page, pageCount)\n const pageRows = pageSize\n ? sorted.slice((currentPage - 1) * pageSize, currentPage * pageSize)\n : sorted\n\n const clearSelection = () => setSelected([])\n const allOnPageSelected =\n pageRows.length > 0 && pageRows.every((row) => selected.includes(getRowKey(row, 0)))\n\n const toggleAllOnPage = () => {\n const pageIds = pageRows.map((row, i) => getRowKey(row, i))\n if (allOnPageSelected) {\n setSelected((prev) => prev.filter((id) => !pageIds.includes(id)))\n } else {\n setSelected((prev) => Array.from(new Set([...prev, ...pageIds])))\n }\n }\n\n const toggleRow = (id: string | number) => {\n setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]))\n }\n\n const hasActiveFilters = Object.values(filters).some((v) => v.trim() !== '')\n const filterableColumns = columns.filter((c) => c.filterable)\n const colSpan = columns.length + (selectable ? 1 : 0) + (rowMenu ? 1 : 0)\n\n const sortIndicator = (key: string) => {\n const active = sortKey === key\n return (\n <ChevronDown\n size={12}\n className={cn(\n 'shrink-0 transition-transform duration-150',\n active ? 'text-tollerud-yellow opacity-100' : 'opacity-25',\n active && sortDir === 'desc' && 'rotate-180'\n )}\n aria-hidden\n />\n )\n }\n\n const headerCell = (col: Column<T>) => (\n <th\n key={col.key}\n className={cn(\n 'px-3 py-2.5 text-left text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider',\n col.sortable && 'cursor-pointer select-none hover:text-tollerud-text-primary transition-colors',\n col.align === 'right' && 'text-right',\n col.align === 'center' && 'text-center',\n )}\n style={col.width ? { width: col.width } : undefined}\n onClick={() => col.sortable && toggleSort(col.key)}\n >\n <span\n className={cn(\n 'inline-flex items-center gap-1',\n col.align === 'right' && 'justify-end w-full',\n col.align === 'center' && 'justify-center w-full',\n )}\n >\n {col.label}\n {col.sortable && (isRich ? sortIndicator(col.key) : (\n <>\n {sortKey === col.key && (\n <span className=\"text-tollerud-accent\">{sortDir === 'asc' ? '↑' : '↓'}</span>\n )}\n {sortKey !== col.key && <span className=\"text-tollerud-text-muted/30\">↕</span>}\n </>\n ))}\n {!isRich && col.filterable && (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('opacity-40', filters[col.key] && 'opacity-100 text-tollerud-yellow')}\n aria-hidden\n >\n <path d=\"M4 4h16v2.172a2 2 0 0 1-.586 1.414L15 12v7l-6 2v-8.5L4.52 7.53A2 2 0 0 1 4 6.16V4z\" />\n </svg>\n )}\n </span>\n </th>\n )\n\n const tableBody = () => {\n if (loading) {\n return (\n <tbody>\n {Array.from({ length: skeletonRows }).map((_, i) => (\n <tr key={i} className=\"border-b border-tollerud-border/20\">\n {selectable && (\n <td className=\"px-3 py-2.5 w-10\">\n <Skeleton className=\"h-4 w-4 rounded\" />\n </td>\n )}\n {columns.map((col, j) => (\n <td key={col.key} className={cn('px-3 py-2.5', col.align === 'right' && 'text-right')}>\n <Skeleton className={cn('h-3', j === 0 ? 'w-[70%]' : 'w-[55%]')} />\n </td>\n ))}\n {rowMenu && (\n <td className=\"px-3 py-2.5 w-11\">\n <Skeleton className=\"h-4 w-4 rounded\" />\n </td>\n )}\n </tr>\n ))}\n </tbody>\n )\n }\n\n if (sorted.length === 0) {\n if (isRich && emptyState) {\n return null\n }\n return (\n <tbody>\n <tr>\n <td colSpan={colSpan} className=\"px-3 py-8 text-center text-sm text-tollerud-text-muted\">\n {hasActiveFilters || query || filterValue !== 'all' ? 'No matching rows' : emptyMessage}\n </td>\n </tr>\n </tbody>\n )\n }\n\n return (\n <tbody>\n {pageRows.map((row, i) => {\n const id = getRowKey(row, i)\n const isSelected = selected.includes(id)\n return (\n <tr\n key={id}\n className={cn(\n 'border-b border-tollerud-border/20 transition-colors',\n onRowClick && 'cursor-pointer hover:bg-tollerud-surface-raised/50',\n isSelected && 'bg-tollerud-yellow/[0.05]',\n )}\n onClick={() => onRowClick?.(row)}\n >\n {selectable && (\n <td className=\"px-3 py-2.5 w-10\" onClick={(e) => e.stopPropagation()}>\n <Checkbox checked={isSelected} onChange={() => toggleRow(id)} aria-label={`Select row ${id}`} />\n </td>\n )}\n {columns.map((col) => {\n const value = row[col.key]\n return (\n <td\n key={col.key}\n className={cn(\n 'px-3 py-2.5 text-tollerud-text-secondary',\n col.align === 'right' && 'text-right',\n col.align === 'center' && 'text-center',\n !col.render && 'font-mono text-xs',\n )}\n >\n {col.render ? col.render(value, row) : String(value ?? '—')}\n </td>\n )\n })}\n {rowMenu && (\n <td className=\"px-2 py-2 w-11\" onClick={(e) => e.stopPropagation()}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md text-tollerud-text-muted hover:text-tollerud-text-primary hover:bg-tollerud-surface-raised transition-colors tollerud-focus-ring\"\n aria-label=\"Row actions\"\n >\n <MoreHorizontal size={15} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {rowMenu(row).map((item, index) => {\n if (item.sep) return <DropdownMenuSeparator key={index} />\n if (item.heading) return <DropdownMenuLabel key={index}>{item.label}</DropdownMenuLabel>\n return (\n <DropdownMenuItem key={index} onSelect={() => item.onSelect?.()}>\n {item.icon ? <span className=\"mr-2 inline-flex\">{item.icon}</span> : null}\n {item.label}\n </DropdownMenuItem>\n )\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n </td>\n )}\n </tr>\n )\n })}\n {isRich &&\n pageSize &&\n pageRows.length < pageSize &&\n Array.from({ length: pageSize - pageRows.length }).map((_, i) => (\n <tr key={`spacer-${i}`} aria-hidden className=\"h-[49px]\">\n <td colSpan={colSpan} />\n </tr>\n ))}\n </tbody>\n )\n }\n\n const table = (\n <table className=\"w-full min-w-[640px] text-sm\">\n <thead>\n <tr className=\"border-b border-tollerud-border/30 bg-tollerud-noir-900\">\n {selectable && (\n <th className=\"px-3 py-2.5 w-10\">\n <Checkbox\n checked={allOnPageSelected}\n onChange={toggleAllOnPage}\n aria-label=\"Select all rows on page\"\n />\n </th>\n )}\n {columns.map((col) => headerCell(col))}\n {rowMenu && <th className=\"w-11\" />}\n </tr>\n {!isRich && filterableColumns.length > 0 && (\n <tr className=\"border-b border-tollerud-border/20\">\n {columns.map((col) => (\n <th\n key={`filter-${col.key}`}\n className={cn('px-1.5 py-1', col.align === 'right' && 'text-right', col.align === 'center' && 'text-center')}\n >\n {col.filterable ? (\n <input\n type=\"text\"\n placeholder={`Filter ${col.label.toLowerCase()}…`}\n value={filters[col.key] ?? ''}\n onChange={(e) => updateFilter(col.key, e.target.value)}\n className={cn(\n 'w-full px-2 py-1 text-xs rounded border transition-colors outline-none',\n 'bg-tollerud-noir-900/50 border-tollerud-border/20 text-tollerud-text-primary placeholder:text-tollerud-text-muted/40',\n 'focus:border-tollerud-yellow/40 focus:ring-1 focus:ring-tollerud-yellow/20',\n )}\n />\n ) : null}\n </th>\n ))}\n </tr>\n )}\n </thead>\n {tableBody()}\n </table>\n )\n\n if (!isRich) {\n return (\n <div ref={forwardedRef} className={cn('overflow-x-auto rounded-lg border border-tollerud-border/30', className)}>\n {table}\n </div>\n )\n }\n\n const showEmpty = !loading && sorted.length === 0\n\n return (\n <div\n ref={forwardedRef}\n className={cn(\n 'overflow-hidden rounded-lg border border-tollerud-border/30 bg-tollerud-noir-900',\n className,\n )}\n >\n {(searchable || filter || toolbarRight) && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-b border-tollerud-border/30 px-4 py-3.5\">\n <div className=\"flex flex-wrap items-center gap-2.5\">\n {searchable && (\n <div className=\"flex h-9 w-[230px] max-w-full items-center gap-2 rounded-lg border border-tollerud-border/30 bg-tollerud-noir-950 px-3\">\n <Search size={15} className=\"shrink-0 text-tollerud-text-muted\" aria-hidden />\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value)\n setPage(1)\n }}\n placeholder={searchPlaceholder}\n className=\"min-w-0 flex-1 border-none bg-transparent text-sm text-tollerud-text-primary outline-none placeholder:text-tollerud-text-muted\"\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n className=\"text-tollerud-text-muted hover:text-tollerud-text-primary\"\n aria-label=\"Clear search\"\n >\n <X size={13} />\n </button>\n )}\n </div>\n )}\n {filter && (\n <Segmented\n size=\"sm\"\n value={filterValue}\n onChange={(value) => {\n setFilterValue(value)\n setPage(1)\n }}\n options={[\n { value: 'all', label: filter.allLabel ?? 'All' },\n ...filterOptions.map((opt) => ({ value: opt, label: opt })),\n ]}\n />\n )}\n </div>\n {toolbarRight}\n </div>\n )}\n\n {selectable && selected.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-b border-tollerud-border/30 bg-tollerud-yellow/[0.07] px-4 py-2.5\">\n <span className=\"flex items-center gap-2 text-sm text-tollerud-text-primary\">\n <Badge variant=\"accent\">{selected.length}</Badge>\n selected\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n {bulkActions.map((action, index) => (\n <Button\n key={index}\n variant={action.variant ?? 'ghost'}\n size=\"sm\"\n onClick={() => action.onRun(selected, clearSelection)}\n >\n {action.icon}\n {action.label}\n </Button>\n ))}\n </div>\n </div>\n )}\n\n {showEmpty ? (\n <div className=\"p-2\">{emptyState ?? <div className=\"py-12 text-center text-sm text-tollerud-text-muted\">No results.</div>}</div>\n ) : (\n <div className=\"overflow-x-auto\">{table}</div>\n )}\n\n {!loading && sorted.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-t border-tollerud-border/30 px-4 py-3\">\n <span className=\"text-xs text-tollerud-text-muted\">\n {pageSize\n ? `Showing ${(currentPage - 1) * pageSize + 1}–${(currentPage - 1) * pageSize + pageRows.length} of ${sorted.length}`\n : `${sorted.length} row${sorted.length === 1 ? '' : 's'}`}\n </span>\n {pageSize && pageCount > 1 && (\n <Pagination page={currentPage} pageCount={pageCount} onChange={setPage} siblingCount={1} />\n )}\n </div>\n )}\n </div>\n )\n}\n\nconst DataTable = forwardRef(<T extends Record<string, unknown>>(\n props: DataTableProps<T>,\n ref: React.Ref<HTMLDivElement>\n) => <DataTableInner {...props} forwardedRef={ref} />)\n\nDataTable.displayName = 'DataTable'\n\nexport { DataTable }\n"]}
|
|
1
|
+
{"version":3,"sources":["../components/DataTable.tsx"],"names":[],"mappings":"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","file":"chunk-K4ALNUZI.js","sourcesContent":["'use client'\n\nimport { useState, useMemo, forwardRef, type ReactNode } from 'react'\nimport { ChevronDown, MoreHorizontal, Search, X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\nimport { Badge } from './Badge'\nimport { Button } from './Button'\nimport { Checkbox } from './Checkbox'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from './DropdownMenu'\nimport { Pagination } from './Pagination'\nimport { Segmented } from './Segmented'\nimport { Skeleton } from './Skeleton'\n\n/* ──────────────────── Sortable & Filterable Data Table ──────────────────── */\n\nexport interface Column<T> {\n key: string\n label: string\n sortable?: boolean\n filterable?: boolean\n align?: 'left' | 'center' | 'right'\n width?: string\n render?: (value: unknown, row: T) => ReactNode\n}\n\nexport interface DataTableFilter {\n key: string\n options?: string[]\n allLabel?: string\n}\n\nexport interface DataTableBulkAction {\n label: string\n variant?: 'primary' | 'secondary' | 'ghost' | 'destructive' | 'terminal'\n icon?: ReactNode\n onRun: (selectedIds: (string | number)[], clearSelection: () => void) => void\n}\n\nexport interface DataTableRowMenuItem {\n label: string\n onSelect?: () => void\n icon?: ReactNode\n sep?: boolean\n heading?: boolean\n}\n\nexport interface DataTableProps<T extends Record<string, unknown>> {\n columns: Column<T>[]\n /** Row data — use `data` or `rows` (alias). */\n data?: T[]\n rows?: T[]\n /** Row key extractor — defaults to `row.id` or `row.key` */\n rowKey?: keyof T | ((row: T) => string | number)\n onRowClick?: (row: T) => void\n className?: string\n emptyMessage?: string\n /** Global search across `searchKeys` (or all column keys). */\n searchable?: boolean\n searchKeys?: (keyof T | string)[]\n searchPlaceholder?: string\n /** Segmented filter on a single column value. */\n filter?: DataTableFilter\n selectable?: boolean\n pageSize?: number\n bulkActions?: DataTableBulkAction[]\n rowMenu?: (row: T) => DataTableRowMenuItem[]\n toolbarRight?: ReactNode\n emptyState?: ReactNode\n loading?: boolean\n skeletonRows?: number\n}\n\ninterface DataTableInnerProps<T extends Record<string, unknown>> extends DataTableProps<T> {\n forwardedRef?: React.Ref<HTMLDivElement>\n}\n\nfunction DataTableInner<T extends Record<string, unknown>>({\n columns,\n data,\n rows,\n rowKey,\n onRowClick,\n className,\n emptyMessage = 'No data',\n searchable = false,\n searchKeys,\n searchPlaceholder = 'Search…',\n filter,\n selectable = false,\n pageSize,\n bulkActions = [],\n rowMenu,\n toolbarRight,\n emptyState,\n loading = false,\n skeletonRows = 5,\n forwardedRef,\n}: DataTableInnerProps<T>) {\n const tableData = useMemo(() => rows ?? data ?? [], [rows, data])\n\n const isRich =\n searchable ||\n filter ||\n selectable ||\n pageSize !== undefined ||\n !!rowMenu ||\n !!toolbarRight ||\n bulkActions.length > 0 ||\n !!emptyState ||\n loading\n\n const [sortKey, setSortKey] = useState<string | null>(null)\n const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc')\n const [filters, setFilters] = useState<Record<string, string>>({})\n const [query, setQuery] = useState('')\n const [filterValue, setFilterValue] = useState('all')\n const [selected, setSelected] = useState<(string | number)[]>([])\n const [page, setPage] = useState(1)\n\n const getRowKey = (row: T, i: number): string | number => {\n if (typeof rowKey === 'function') return rowKey(row)\n if (rowKey) return row[rowKey] as string | number\n return (row.id ?? row.key ?? i) as string | number\n }\n\n const toggleSort = (key: string) => {\n if (sortKey === key) {\n setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'))\n } else {\n setSortKey(key)\n setSortDir('asc')\n }\n }\n\n const updateFilter = (key: string, value: string) => {\n setFilters((prev) => {\n const next = { ...prev }\n if (value.trim() === '') {\n delete next[key]\n } else {\n next[key] = value\n }\n return next\n })\n }\n\n const searchKeysResolved = searchKeys ?? columns.map((c) => c.key)\n const filterOptions = filter\n ? (filter.options ?? Array.from(new Set(tableData.map((r) => String(r[filter.key] ?? '')))))\n : []\n\n const filtered = useMemo(() => {\n let result = tableData\n\n if (isRich && filter && filterValue !== 'all') {\n result = result.filter((row) => String(row[filter.key] ?? '') === filterValue)\n }\n\n if (isRich && searchable && query.trim()) {\n const q = query.trim().toLowerCase()\n result = result.filter((row) =>\n searchKeysResolved.some((key) => String(row[key as keyof T] ?? '').toLowerCase().includes(q))\n )\n }\n\n if (!isRich) {\n const activeFilters = Object.entries(filters).filter(([, v]) => v.trim() !== '')\n if (activeFilters.length > 0) {\n result = result.filter((row) =>\n activeFilters.every(([key, filterVal]) => {\n const cellValue = String(row[key] ?? '').toLowerCase()\n return cellValue.includes(filterVal.toLowerCase())\n })\n )\n }\n }\n\n return result\n }, [tableData, filters, isRich, filter, filterValue, searchable, query, searchKeysResolved])\n\n const sorted = useMemo(() => {\n if (!sortKey) return filtered\n const col = columns.find((c) => c.key === sortKey)\n if (!col?.sortable) return filtered\n\n return [...filtered].sort((a, b) => {\n const aVal = a[sortKey]\n const bVal = b[sortKey]\n\n if (typeof aVal === 'number' && typeof bVal === 'number') {\n return sortDir === 'asc' ? aVal - bVal : bVal - aVal\n }\n\n const aStr = String(aVal ?? '')\n const bStr = String(bVal ?? '')\n const cmp = aStr.localeCompare(bStr, 'nb', { numeric: true })\n return sortDir === 'asc' ? cmp : -cmp\n })\n }, [filtered, sortKey, sortDir, columns])\n\n const pageCount = pageSize ? Math.max(1, Math.ceil(sorted.length / pageSize)) : 1\n const currentPage = Math.min(page, pageCount)\n const pageRows = pageSize\n ? sorted.slice((currentPage - 1) * pageSize, currentPage * pageSize)\n : sorted\n\n const clearSelection = () => setSelected([])\n const allOnPageSelected =\n pageRows.length > 0 && pageRows.every((row) => selected.includes(getRowKey(row, 0)))\n\n const toggleAllOnPage = () => {\n const pageIds = pageRows.map((row, i) => getRowKey(row, i))\n if (allOnPageSelected) {\n setSelected((prev) => prev.filter((id) => !pageIds.includes(id)))\n } else {\n setSelected((prev) => Array.from(new Set([...prev, ...pageIds])))\n }\n }\n\n const toggleRow = (id: string | number) => {\n setSelected((prev) => (prev.includes(id) ? prev.filter((x) => x !== id) : [...prev, id]))\n }\n\n const hasActiveFilters = Object.values(filters).some((v) => v.trim() !== '')\n const filterableColumns = columns.filter((c) => c.filterable)\n const colSpan = columns.length + (selectable ? 1 : 0) + (rowMenu ? 1 : 0)\n\n const sortIndicator = (key: string) => {\n const active = sortKey === key\n return (\n <ChevronDown\n size={12}\n className={cn(\n 'shrink-0 transition-transform duration-150',\n active ? 'text-tollerud-yellow opacity-100' : 'opacity-25',\n active && sortDir === 'desc' && 'rotate-180'\n )}\n aria-hidden\n />\n )\n }\n\n const headerCell = (col: Column<T>) => (\n <th\n key={col.key}\n className={cn(\n 'px-3 py-2.5 text-left text-xs font-semibold text-tollerud-text-muted uppercase tracking-wider',\n col.sortable && 'cursor-pointer select-none hover:text-tollerud-text-primary transition-colors',\n col.align === 'right' && 'text-right',\n col.align === 'center' && 'text-center',\n )}\n style={col.width ? { width: col.width } : undefined}\n onClick={() => col.sortable && toggleSort(col.key)}\n >\n <span\n className={cn(\n 'inline-flex items-center gap-1',\n col.align === 'right' && 'justify-end w-full',\n col.align === 'center' && 'justify-center w-full',\n )}\n >\n {col.label}\n {col.sortable && (isRich ? sortIndicator(col.key) : (\n <>\n {sortKey === col.key && (\n <span className=\"text-tollerud-accent\">{sortDir === 'asc' ? '↑' : '↓'}</span>\n )}\n {sortKey !== col.key && <span className=\"text-tollerud-text-muted/30\">↕</span>}\n </>\n ))}\n {!isRich && col.filterable && (\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('opacity-40', filters[col.key] && 'opacity-100 text-tollerud-yellow')}\n aria-hidden\n >\n <path d=\"M4 4h16v2.172a2 2 0 0 1-.586 1.414L15 12v7l-6 2v-8.5L4.52 7.53A2 2 0 0 1 4 6.16V4z\" />\n </svg>\n )}\n </span>\n </th>\n )\n\n const tableBody = () => {\n if (loading) {\n return (\n <tbody>\n {Array.from({ length: skeletonRows }).map((_, i) => (\n <tr key={i} className=\"border-b border-tollerud-border/20\">\n {selectable && (\n <td className=\"px-3 py-2.5 w-10\">\n <Skeleton className=\"h-4 w-4 rounded\" />\n </td>\n )}\n {columns.map((col, j) => (\n <td key={col.key} className={cn('px-3 py-2.5', col.align === 'right' && 'text-right')}>\n <Skeleton className={cn('h-3', j === 0 ? 'w-[70%]' : 'w-[55%]')} />\n </td>\n ))}\n {rowMenu && (\n <td className=\"px-3 py-2.5 w-11\">\n <Skeleton className=\"h-4 w-4 rounded\" />\n </td>\n )}\n </tr>\n ))}\n </tbody>\n )\n }\n\n if (sorted.length === 0) {\n if (isRich && emptyState) {\n return null\n }\n return (\n <tbody>\n <tr>\n <td colSpan={colSpan} className=\"px-3 py-8 text-center text-sm text-tollerud-text-muted\">\n {hasActiveFilters || query || filterValue !== 'all' ? 'No matching rows' : emptyMessage}\n </td>\n </tr>\n </tbody>\n )\n }\n\n return (\n <tbody>\n {pageRows.map((row, i) => {\n const id = getRowKey(row, i)\n const isSelected = selected.includes(id)\n return (\n <tr\n key={id}\n className={cn(\n 'border-b border-tollerud-border/20 transition-colors',\n onRowClick && 'cursor-pointer hover:bg-tollerud-surface-raised/50',\n isSelected && 'bg-tollerud-yellow/[0.05]',\n )}\n onClick={() => onRowClick?.(row)}\n >\n {selectable && (\n <td className=\"px-3 py-2.5 w-10\" onClick={(e) => e.stopPropagation()}>\n <Checkbox checked={isSelected} onChange={() => toggleRow(id)} aria-label={`Select row ${id}`} />\n </td>\n )}\n {columns.map((col) => {\n const value = row[col.key]\n return (\n <td\n key={col.key}\n className={cn(\n 'px-3 py-2.5 text-tollerud-text-secondary',\n col.align === 'right' && 'text-right',\n col.align === 'center' && 'text-center',\n !col.render && 'font-mono text-xs',\n )}\n >\n {col.render ? col.render(value, row) : String(value ?? '—')}\n </td>\n )\n })}\n {rowMenu && (\n <td className=\"px-2 py-2 w-11\" onClick={(e) => e.stopPropagation()}>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md text-tollerud-text-muted hover:text-tollerud-text-primary hover:bg-tollerud-surface-raised transition-colors tollerud-focus-ring\"\n aria-label=\"Row actions\"\n >\n <MoreHorizontal size={15} />\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n {rowMenu(row).map((item, index) => {\n if (item.sep) return <DropdownMenuSeparator key={index} />\n if (item.heading) return <DropdownMenuLabel key={index}>{item.label}</DropdownMenuLabel>\n return (\n <DropdownMenuItem key={index} onSelect={() => item.onSelect?.()}>\n {item.icon ? <span className=\"mr-2 inline-flex\">{item.icon}</span> : null}\n {item.label}\n </DropdownMenuItem>\n )\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n </td>\n )}\n </tr>\n )\n })}\n {isRich &&\n pageSize &&\n pageRows.length < pageSize &&\n Array.from({ length: pageSize - pageRows.length }).map((_, i) => (\n <tr key={`spacer-${i}`} aria-hidden className=\"h-[49px]\">\n <td colSpan={colSpan} />\n </tr>\n ))}\n </tbody>\n )\n }\n\n const table = (\n <table className=\"w-full min-w-[640px] text-sm\">\n <thead>\n <tr className=\"border-b border-tollerud-border/30 bg-tollerud-noir-900\">\n {selectable && (\n <th className=\"px-3 py-2.5 w-10\">\n <Checkbox\n checked={allOnPageSelected}\n onChange={toggleAllOnPage}\n aria-label=\"Select all rows on page\"\n />\n </th>\n )}\n {columns.map((col) => headerCell(col))}\n {rowMenu && <th className=\"w-11\" />}\n </tr>\n {!isRich && filterableColumns.length > 0 && (\n <tr className=\"border-b border-tollerud-border/20\">\n {columns.map((col) => (\n <th\n key={`filter-${col.key}`}\n className={cn('px-1.5 py-1', col.align === 'right' && 'text-right', col.align === 'center' && 'text-center')}\n >\n {col.filterable ? (\n <input\n type=\"text\"\n placeholder={`Filter ${col.label.toLowerCase()}…`}\n value={filters[col.key] ?? ''}\n onChange={(e) => updateFilter(col.key, e.target.value)}\n className={cn(\n 'w-full px-2 py-1 text-xs rounded border transition-colors outline-none',\n 'bg-tollerud-noir-900/50 border-tollerud-border/20 text-tollerud-text-primary placeholder:text-tollerud-text-muted/40',\n 'focus:border-tollerud-yellow/40 focus:ring-1 focus:ring-tollerud-yellow/20',\n )}\n />\n ) : null}\n </th>\n ))}\n </tr>\n )}\n </thead>\n {tableBody()}\n </table>\n )\n\n if (!isRich) {\n return (\n <div ref={forwardedRef} className={cn('overflow-x-auto rounded-lg border border-tollerud-border/30', className)}>\n {table}\n </div>\n )\n }\n\n const showEmpty = !loading && sorted.length === 0\n\n return (\n <div\n ref={forwardedRef}\n className={cn(\n 'overflow-hidden rounded-lg border border-tollerud-border/30 bg-tollerud-noir-900',\n className,\n )}\n >\n {(searchable || filter || toolbarRight) && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-b border-tollerud-border/30 px-4 py-3.5\">\n <div className=\"flex flex-wrap items-center gap-2.5\">\n {searchable && (\n <div className=\"flex h-9 w-[230px] max-w-full items-center gap-2 rounded-lg border border-tollerud-border/30 bg-tollerud-noir-950 px-3\">\n <Search size={15} className=\"shrink-0 text-tollerud-text-muted\" aria-hidden />\n <input\n value={query}\n onChange={(e) => {\n setQuery(e.target.value)\n setPage(1)\n }}\n placeholder={searchPlaceholder}\n className=\"min-w-0 flex-1 border-none bg-transparent text-sm text-tollerud-text-primary outline-none placeholder:text-tollerud-text-muted\"\n />\n {query && (\n <button\n type=\"button\"\n onClick={() => setQuery('')}\n className=\"text-tollerud-text-muted hover:text-tollerud-text-primary\"\n aria-label=\"Clear search\"\n >\n <X size={13} />\n </button>\n )}\n </div>\n )}\n {filter && (\n <Segmented\n size=\"sm\"\n value={filterValue}\n onChange={(value) => {\n setFilterValue(value)\n setPage(1)\n }}\n options={[\n { value: 'all', label: filter.allLabel ?? 'All' },\n ...filterOptions.map((opt) => ({ value: opt, label: opt })),\n ]}\n />\n )}\n </div>\n {toolbarRight}\n </div>\n )}\n\n {selectable && selected.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-b border-tollerud-border/30 bg-tollerud-yellow/[0.07] px-4 py-2.5\">\n <span className=\"flex items-center gap-2 text-sm text-tollerud-text-primary\">\n <Badge variant=\"accent\">{selected.length}</Badge>\n selected\n </span>\n <div className=\"flex flex-wrap items-center gap-2\">\n {bulkActions.map((action, index) => (\n <Button\n key={index}\n variant={action.variant ?? 'ghost'}\n size=\"sm\"\n onClick={() => action.onRun(selected, clearSelection)}\n >\n {action.icon}\n {action.label}\n </Button>\n ))}\n </div>\n </div>\n )}\n\n {showEmpty ? (\n <div className=\"p-2\">{emptyState ?? <div className=\"py-12 text-center text-sm text-tollerud-text-muted\">No results.</div>}</div>\n ) : (\n <div className=\"overflow-x-auto\">{table}</div>\n )}\n\n {!loading && sorted.length > 0 && (\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-t border-tollerud-border/30 px-4 py-3\">\n <span className=\"text-xs text-tollerud-text-muted\">\n {pageSize\n ? `Showing ${(currentPage - 1) * pageSize + 1}–${(currentPage - 1) * pageSize + pageRows.length} of ${sorted.length}`\n : `${sorted.length} row${sorted.length === 1 ? '' : 's'}`}\n </span>\n {pageSize && pageCount > 1 && (\n <Pagination page={currentPage} pageCount={pageCount} onChange={setPage} siblingCount={1} />\n )}\n </div>\n )}\n </div>\n )\n}\n\nconst DataTable = forwardRef(<T extends Record<string, unknown>>(\n props: DataTableProps<T>,\n ref: React.Ref<HTMLDivElement>\n) => <DataTableInner {...props} forwardedRef={ref} />)\n\nDataTable.displayName = 'DataTable'\n\nexport { DataTable }\n"]}
|
|
@@ -14,7 +14,7 @@ function BentoDashboard({
|
|
|
14
14
|
incidents = [],
|
|
15
15
|
className
|
|
16
16
|
}) {
|
|
17
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-
|
|
17
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("w-full space-y-6", className), children: [
|
|
18
18
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
19
19
|
/* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-tollerud-text-primary", children: title }),
|
|
20
20
|
/* @__PURE__ */ jsxs("p", { className: "text-xs text-tollerud-text-muted", children: [
|
|
@@ -29,26 +29,26 @@ function BentoDashboard({
|
|
|
29
29
|
/* @__PURE__ */ jsx("div", { className: "md:col-span-2 lg:col-span-1", children: /* @__PURE__ */ jsx(HostCard, { ...hosts[0] }) }),
|
|
30
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
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: [
|
|
32
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 items-start gap-4 lg:grid-cols-3 lg:gap-3", children: [
|
|
33
|
+
metrics.length > 0 && /* @__PURE__ */ jsxs("div", { className: "min-w-0 lg:col-span-2", children: [
|
|
34
34
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Metrics" }),
|
|
35
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 sm:grid-cols-4
|
|
35
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-4", children: metrics.map((m, i) => /* @__PURE__ */ jsx(StatCard, { ...m }, m.label ?? i)) })
|
|
36
36
|
] }),
|
|
37
|
-
services.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
37
|
+
services.length > 0 && /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
38
38
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Services" }),
|
|
39
39
|
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: services.slice(0, 4).map((s, i) => /* @__PURE__ */ jsx(ServiceHealthCard, { ...s }, s.service ?? i)) })
|
|
40
40
|
] })
|
|
41
41
|
] }),
|
|
42
|
-
incidents.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
42
|
+
incidents.length > 0 && /* @__PURE__ */ jsxs("div", { className: "min-w-0 pt-1", children: [
|
|
43
43
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Recent Incidents" }),
|
|
44
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-
|
|
44
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: incidents.slice(0, 4).map((inc, i) => /* @__PURE__ */ jsx(IncidentCard, { ...inc }, inc.title + i)) })
|
|
45
45
|
] })
|
|
46
46
|
] });
|
|
47
47
|
}
|
|
48
48
|
function SectionLabel({ children }) {
|
|
49
|
-
return /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-tollerud-text-muted
|
|
49
|
+
return /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wider text-tollerud-text-muted", children });
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export { BentoDashboard };
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-LGVXEWNB.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-LGVXEWNB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/BentoDashboard.tsx"],"names":[],"mappings":"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","file":"chunk-LGVXEWNB.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('w-full space-y-6', 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 items-start gap-4 lg:grid-cols-3 lg:gap-3\">\n {metrics.length > 0 && (\n <div className=\"min-w-0 lg:col-span-2\">\n <SectionLabel>Metrics</SectionLabel>\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-4\">\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 className=\"min-w-0\">\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 className=\"min-w-0 pt-1\">\n <SectionLabel>Recent Incidents</SectionLabel>\n <div className=\"space-y-2\">\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=\"mb-3 text-xs font-semibold uppercase tracking-wider text-tollerud-text-muted\">{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-BQWF5MP7.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-SNNMZ444.js.map
|
|
56
|
+
//# sourceMappingURL=chunk-SNNMZ444.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-SNNMZ444.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"]}
|
|
@@ -4,7 +4,7 @@ import { forwardRef, useId } from 'react';
|
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
6
6
|
var Checkbox = forwardRef(
|
|
7
|
-
({ className, label, id: idProp,
|
|
7
|
+
({ className, label, id: idProp, ...props }, ref) => {
|
|
8
8
|
const autoId = useId();
|
|
9
9
|
const id = idProp ?? autoId;
|
|
10
10
|
return /* @__PURE__ */ jsxs(
|
|
@@ -25,7 +25,6 @@ var Checkbox = forwardRef(
|
|
|
25
25
|
ref,
|
|
26
26
|
id,
|
|
27
27
|
type: "checkbox",
|
|
28
|
-
checked,
|
|
29
28
|
className: "peer sr-only",
|
|
30
29
|
...props
|
|
31
30
|
}
|
|
@@ -39,15 +38,13 @@ var Checkbox = forwardRef(
|
|
|
39
38
|
"bg-tollerud-surface-raised border-tollerud-border",
|
|
40
39
|
"peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow",
|
|
41
40
|
"peer-checked:bg-tollerud-yellow peer-checked:border-tollerud-yellow",
|
|
41
|
+
"peer-checked:[&_svg]:opacity-100",
|
|
42
42
|
"group-hover:border-tollerud-text-secondary"
|
|
43
43
|
),
|
|
44
44
|
children: /* @__PURE__ */ jsx(
|
|
45
45
|
"svg",
|
|
46
46
|
{
|
|
47
|
-
className:
|
|
48
|
-
"h-3 w-3 text-tollerud-noir-black transition-opacity duration-[150ms]",
|
|
49
|
-
checked ? "opacity-100" : "opacity-0"
|
|
50
|
-
),
|
|
47
|
+
className: "pointer-events-none h-3 w-3 text-tollerud-black opacity-0 transition-opacity duration-[150ms]",
|
|
51
48
|
viewBox: "0 0 12 12",
|
|
52
49
|
fill: "none",
|
|
53
50
|
"aria-hidden": "true",
|
|
@@ -75,5 +72,5 @@ var Checkbox = forwardRef(
|
|
|
75
72
|
Checkbox.displayName = "Checkbox";
|
|
76
73
|
|
|
77
74
|
export { Checkbox };
|
|
78
|
-
//# sourceMappingURL=chunk-
|
|
79
|
-
//# sourceMappingURL=chunk-
|
|
75
|
+
//# sourceMappingURL=chunk-TLEKK53J.js.map
|
|
76
|
+
//# sourceMappingURL=chunk-TLEKK53J.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/Checkbox.tsx"],"names":[],"mappings":";;;;AASA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,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,UAAA;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,wDAAA;AAAA,kBACA,kCAAA;AAAA,kBACA,mDAAA;AAAA,kBACA,yEAAA;AAAA,kBACA,qEAAA;AAAA,kBACA,kCAAA;AAAA,kBACA;AAAA,iBACF;AAAA,gBAGA,QAAA,kBAAA,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,+FAAA;AAAA,oBACV,OAAA,EAAQ,WAAA;AAAA,oBACR,IAAA,EAAK,MAAA;AAAA,oBACL,aAAA,EAAY,MAAA;AAAA,oBAEZ,QAAA,kBAAA,GAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,CAAA,EAAE,sBAAA;AAAA,wBACF,MAAA,EAAO,cAAA;AAAA,wBACP,WAAA,EAAa,CAAA;AAAA,wBACb,aAAA,EAAc,OAAA;AAAA,wBACd,cAAA,EAAe;AAAA;AAAA;AACjB;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,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-TLEKK53J.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n}\n\nconst Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\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=\"checkbox\"\n className=\"peer sr-only\"\n {...props}\n />\n {/* Custom box */}\n <span\n className={cn(\n 'h-4 w-4 rounded border transition-all duration-[150ms]',\n 'flex items-center justify-center',\n 'bg-tollerud-surface-raised border-tollerud-border',\n 'peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow',\n 'peer-checked:bg-tollerud-yellow peer-checked:border-tollerud-yellow',\n 'peer-checked:[&_svg]:opacity-100',\n 'group-hover:border-tollerud-text-secondary'\n )}\n >\n {/* Checkmark SVG — visible when checked (via peer on sibling input) */}\n <svg\n className=\"pointer-events-none h-3 w-3 text-tollerud-black opacity-0 transition-opacity duration-[150ms]\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M2.5 6l2.5 2.5 4.5-5\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nCheckbox.displayName = 'Checkbox'\n\nexport { Checkbox }"]}
|
package/dist/cta-band.js
CHANGED
package/dist/data-table.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { DataTable } from './chunk-
|
|
2
|
+
export { DataTable } from './chunk-K4ALNUZI.js';
|
|
3
3
|
import './chunk-AQT3FZRQ.js';
|
|
4
4
|
import './chunk-NSMU66ZX.js';
|
|
5
5
|
import './chunk-RJTDQOT2.js';
|
|
6
6
|
import './chunk-435JHF7G.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-TLEKK53J.js';
|
|
8
8
|
import './chunk-QEHTPQHL.js';
|
|
9
|
-
import './chunk-
|
|
9
|
+
import './chunk-BQWF5MP7.js';
|
|
10
10
|
import './chunk-WSQNPRGN.js';
|
|
11
11
|
//# sourceMappingURL=data-table.js.map
|
|
12
12
|
//# sourceMappingURL=data-table.js.map
|
package/dist/index.js
CHANGED
|
@@ -9,9 +9,9 @@ export { Sparkline } from './chunk-EVHZFYWX.js';
|
|
|
9
9
|
export { Stepper } from './chunk-2QWKOCWF.js';
|
|
10
10
|
export { Switch } from './chunk-YTU7BRDW.js';
|
|
11
11
|
export { Tabs, TabsContent, TabsList, TabsTrigger } from './chunk-T56TTOI6.js';
|
|
12
|
-
export { PricingCard } from './chunk-
|
|
12
|
+
export { PricingCard } from './chunk-SNNMZ444.js';
|
|
13
13
|
export { Progress } from './chunk-5GWHUJ5D.js';
|
|
14
|
-
export { Radio, RadioGroup } from './chunk-
|
|
14
|
+
export { Radio, RadioGroup } from './chunk-J2Z4ZFVX.js';
|
|
15
15
|
export { RollbackPlan } from './chunk-WDANALHD.js';
|
|
16
16
|
export { Select } from './chunk-GTM2DE4C.js';
|
|
17
17
|
export { Sheet, SheetClose, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from './chunk-ILADNTUB.js';
|
|
@@ -39,25 +39,25 @@ export { CodeBlock } from './chunk-DRCMGIQ6.js';
|
|
|
39
39
|
export { Combobox } from './chunk-H3ZVGTJM.js';
|
|
40
40
|
export { CommandMenu } from './chunk-RQ3RXKAZ.js';
|
|
41
41
|
export { Container } from './chunk-DNJI65VQ.js';
|
|
42
|
-
export { DataTable } from './chunk-
|
|
42
|
+
export { DataTable } from './chunk-K4ALNUZI.js';
|
|
43
43
|
export { Skeleton } from './chunk-AQT3FZRQ.js';
|
|
44
44
|
export { Segmented } from './chunk-NSMU66ZX.js';
|
|
45
45
|
export { Pagination } from './chunk-RJTDQOT2.js';
|
|
46
46
|
export { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from './chunk-435JHF7G.js';
|
|
47
|
-
export { Checkbox } from './chunk-
|
|
47
|
+
export { Checkbox } from './chunk-TLEKK53J.js';
|
|
48
48
|
export { DatePicker } from './chunk-Q54CVE3W.js';
|
|
49
49
|
export { Avatar, AvatarGroup } from './chunk-VFS3V3VY.js';
|
|
50
50
|
export { BackupStatusPanel } from './chunk-JRFSUVSO.js';
|
|
51
51
|
export { Badge } from './chunk-QEHTPQHL.js';
|
|
52
52
|
export { BarChart } from './chunk-4PA2ACNF.js';
|
|
53
|
-
export { BentoDashboard } from './chunk-
|
|
53
|
+
export { BentoDashboard } from './chunk-LGVXEWNB.js';
|
|
54
54
|
export { StatCard } from './chunk-LUM2YJBH.js';
|
|
55
55
|
export { ServiceHealthCard } from './chunk-7EP2T3OW.js';
|
|
56
56
|
export { HostCard } from './chunk-DOUDJU4P.js';
|
|
57
57
|
export { StatusDot } from './chunk-NHPISZWS.js';
|
|
58
58
|
export { Breadcrumb } from './chunk-7J5QXUQN.js';
|
|
59
|
-
export { Button, buttonVariants } from './chunk-
|
|
60
|
-
export { CTABand } from './chunk-
|
|
59
|
+
export { Button, buttonVariants } from './chunk-BQWF5MP7.js';
|
|
60
|
+
export { CTABand } from './chunk-FPFLOYIJ.js';
|
|
61
61
|
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './chunk-YYWODLER.js';
|
|
62
62
|
export { ActionDiff } from './chunk-3XTZPDNV.js';
|
|
63
63
|
export { ActionRow } from './chunk-OGVSZ7NV.js';
|
package/dist/pricing-card.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { PricingCard } from './chunk-
|
|
3
|
-
import './chunk-
|
|
2
|
+
export { PricingCard } from './chunk-SNNMZ444.js';
|
|
3
|
+
import './chunk-BQWF5MP7.js';
|
|
4
4
|
import './chunk-WSQNPRGN.js';
|
|
5
5
|
//# sourceMappingURL=pricing-card.js.map
|
|
6
6
|
//# sourceMappingURL=pricing-card.js.map
|
package/dist/radio-group.d.ts
CHANGED
|
@@ -6,6 +6,12 @@ interface RadioGroupProps {
|
|
|
6
6
|
label?: string;
|
|
7
7
|
/** Error message */
|
|
8
8
|
error?: string;
|
|
9
|
+
/** Controlled selected value */
|
|
10
|
+
value?: string;
|
|
11
|
+
/** Called with the selected option value */
|
|
12
|
+
onChange?: (value: string) => void;
|
|
13
|
+
/** Shared name for native radio grouping (auto-generated if omitted) */
|
|
14
|
+
name?: string;
|
|
9
15
|
children?: React.ReactNode;
|
|
10
16
|
className?: string;
|
|
11
17
|
}
|
package/dist/radio-group.js
CHANGED
package/globals-layers.css
CHANGED
|
@@ -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:
|
|
247
|
+
background: var(--surface-raised);
|
|
240
248
|
color: var(--foreground);
|
|
241
249
|
border-color: var(--border);
|
|
242
250
|
}
|
|
@@ -597,6 +605,24 @@
|
|
|
597
605
|
line-height: 1.1;
|
|
598
606
|
}
|
|
599
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
|
+
|
|
600
626
|
/* ═══ Status Indicator ═══ */
|
|
601
627
|
.tollerud-status {
|
|
602
628
|
display: inline-flex;
|
package/package.json
CHANGED
package/registry.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"version": "3.1.
|
|
4
|
-
"description": "
|
|
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": "
|
|
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
|
|
216
|
+
"description": "Severity-graded incident/alert card (critical → info)",
|
|
217
217
|
"files": [
|
|
218
218
|
"components/IncidentCard.tsx"
|
|
219
219
|
],
|
|
@@ -455,7 +455,7 @@
|
|
|
455
455
|
},
|
|
456
456
|
"bento-dashboard": {
|
|
457
457
|
"name": "BentoDashboard",
|
|
458
|
-
"description": "
|
|
458
|
+
"description": "Homelab mission-control bento grid — host cards, metrics, services, and recent incidents",
|
|
459
459
|
"files": [
|
|
460
460
|
"components/BentoDashboard.tsx"
|
|
461
461
|
],
|
|
@@ -463,7 +463,12 @@
|
|
|
463
463
|
"clsx",
|
|
464
464
|
"tailwind-merge"
|
|
465
465
|
],
|
|
466
|
-
"registryDependencies": [
|
|
466
|
+
"registryDependencies": [
|
|
467
|
+
"host-card",
|
|
468
|
+
"stat-card",
|
|
469
|
+
"service-health-card",
|
|
470
|
+
"incident-card"
|
|
471
|
+
],
|
|
467
472
|
"type": "components:ui"
|
|
468
473
|
},
|
|
469
474
|
"breadcrumb": {
|
|
@@ -890,7 +895,7 @@
|
|
|
890
895
|
},
|
|
891
896
|
"hero-block": {
|
|
892
897
|
"name": "HeroBlock",
|
|
893
|
-
"description": "Landing hero
|
|
898
|
+
"description": "Landing hero with noir glow background. Pass intense for live WebGL shader; optional media slot for two-column layout",
|
|
894
899
|
"files": [
|
|
895
900
|
"components/HeroBlock.tsx"
|
|
896
901
|
],
|
|
@@ -921,7 +926,7 @@
|
|
|
921
926
|
},
|
|
922
927
|
"cta-band": {
|
|
923
928
|
"name": "CTABand",
|
|
924
|
-
"description": "
|
|
929
|
+
"description": "Centered closing call-to-action with title, description, action row, and optional yellow accent bar",
|
|
925
930
|
"files": [
|
|
926
931
|
"components/CTABand.tsx"
|
|
927
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:
|
|
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 ── */
|
|
@@ -452,6 +460,22 @@ code, pre {
|
|
|
452
460
|
line-height: 0.95;
|
|
453
461
|
color: white;
|
|
454
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
|
+
}
|
|
455
479
|
|
|
456
480
|
/* ── Kbd (Keyboard Shortcut Chip) ── */
|
|
457
481
|
.tollerud-kbd { display: inline-flex; align-items: center; gap: 2px; }
|
|
@@ -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/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"]}
|
|
@@ -1 +0,0 @@
|
|
|
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"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../components/BentoDashboard.tsx"],"names":[],"mappings":"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","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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../components/Checkbox.tsx"],"names":[],"mappings":";;;;AASA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,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,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,UAAA;AAAA,gBACL,OAAA;AAAA,gBACA,SAAA,EAAU,cAAA;AAAA,gBACT,GAAG;AAAA;AAAA,aACN;AAAA,4BAEA,GAAA;AAAA,cAAC,MAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAW,EAAA;AAAA,kBACT,wDAAA;AAAA,kBACA,kCAAA;AAAA,kBACA,mDAAA;AAAA,kBACA,yEAAA;AAAA,kBACA,qEAAA;AAAA,kBACA;AAAA,iBACF;AAAA,gBAGA,QAAA,kBAAA,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,sEAAA;AAAA,sBACA,UAAU,aAAA,GAAgB;AAAA,qBAC5B;AAAA,oBACA,OAAA,EAAQ,WAAA;AAAA,oBACR,IAAA,EAAK,MAAA;AAAA,oBACL,aAAA,EAAY,MAAA;AAAA,oBAEZ,QAAA,kBAAA,GAAA;AAAA,sBAAC,MAAA;AAAA,sBAAA;AAAA,wBACC,CAAA,EAAE,sBAAA;AAAA,wBACF,MAAA,EAAO,cAAA;AAAA,wBACP,WAAA,EAAa,CAAA;AAAA,wBACb,aAAA,EAAc,OAAA;AAAA,wBACd,cAAA,EAAe;AAAA;AAAA;AACjB;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,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-T3TQPOVM.js","sourcesContent":["'use client'\n\nimport { type InputHTMLAttributes, forwardRef, useId } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n label?: string\n}\n\nconst Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(\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 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=\"checkbox\"\n checked={checked}\n className=\"peer sr-only\"\n {...props}\n />\n {/* Custom box */}\n <span\n className={cn(\n 'h-4 w-4 rounded border transition-all duration-[150ms]',\n 'flex items-center justify-center',\n 'bg-tollerud-surface-raised border-tollerud-border',\n 'peer-focus-visible:outline-2 peer-focus-visible:outline-tollerud-yellow',\n 'peer-checked:bg-tollerud-yellow peer-checked:border-tollerud-yellow',\n 'group-hover:border-tollerud-text-secondary'\n )}\n >\n {/* Checkmark SVG — visible when checked */}\n <svg\n className={cn(\n 'h-3 w-3 text-tollerud-noir-black transition-opacity duration-[150ms]',\n checked ? 'opacity-100' : 'opacity-0'\n )}\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M2.5 6l2.5 2.5 4.5-5\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </span>\n </span>\n {label && <span>{label}</span>}\n </label>\n )\n }\n)\nCheckbox.displayName = 'Checkbox'\n\nexport { Checkbox }"]}
|