"use client"; import clsx from "clsx"; import type { ReactNode } from "react"; import { TYPE_COLORS } from "@/lib/format"; export function Panel({ title, sub, right, children, className, pad = true }: { title?: ReactNode; sub?: ReactNode; right?: ReactNode; children: ReactNode; className?: string; pad?: boolean }) { return (
{(title || right) && (
{title &&

{title}

} {sub &&

{sub}

}
{right &&
{right}
}
)}
{children}
); } export function Kpi({ label, value, hint, accent = "cyan", spark }: { label: string; value: ReactNode; hint?: ReactNode; accent?: "cyan" | "amber" | "green" | "violet" | "pink" | "red" | "fg"; spark?: number[] }) { const color = { cyan: "text-cyan", amber: "text-amber", green: "text-green", violet: "text-violet", pink: "text-pink", red: "text-red", fg: "text-fg" }[accent]; return (
{label}
{value}
{hint &&
{hint}
} {spark && spark.length > 1 && }
); } export function Spark({ values, className, color = "currentColor" }: { values: number[]; className?: string; color?: string }) { const max = Math.max(1, ...values); const w = 100; const h = 30; const pts = values.map((v, i) => `${(i / Math.max(1, values.length - 1)) * w},${h - (v / max) * (h - 2) - 1}`).join(" "); return ( ); } export function Tag({ children, color, className, title }: { children: ReactNode; color?: string; className?: string; title?: string }) { const c = color ?? "#6b7a8c"; return ( {children} ); } export function TypeTag({ type }: { type: string }) { return {type}; } export function SurfaceChips({ provenance }: { provenance?: { surface: string; confidence: number; detail?: string }[] | null }) { if (!provenance?.length) return —; const best = new Map(); for (const p of provenance) if (!best.has(p.surface) || best.get(p.surface)!.confidence < p.confidence) best.set(p.surface, p); const colors: Record = { network: "#38e1ff", dom: "#43e69a", visual: "#ff7ad9", media: "#9d7bff", accessibility: "#ffb347", navigation: "#6b7a8c" }; return ( {[...best.entries()].map(([s, p]) => ( {s} {Math.round(p.confidence * 100)} ))} ); } export function Bar({ value, color = "#38e1ff", className }: { value: number; color?: string; className?: string }) { return (
); } export function Empty({ children }: { children: ReactNode }) { return
{children}
; } export function Skeleton({ rows = 4 }: { rows?: number }) { return (
{Array.from({ length: rows }).map((_, i) => (
))}
); } export function Table({ head, children, dense }: { head: ReactNode[]; children: ReactNode; dense?: boolean }) { return (
{head.map((h, i) => ( ))} {children}
{h}
); } export function Metric({ label, value }: { label: string; value: ReactNode }) { return (
{label} {value}
); } export function StatusPill({ status }: { status: string }) { const map: Record = { running: "#ffb347", healthy: "#ffb347", queued: "#6b7a8c", done: "#43e69a", stopped: "#6b7a8c", failed: "#ff5c7a", auth_required: "#ff5c7a", crashed: "#ff5c7a", degraded: "#ff5c7a" }; return ( {status === "running" || status === "healthy" ? : null} {status} ); }