Files
0pt/components/data-artifact.tsx
adminandClaude Opus 4.8 f4beca3f76 feat(i18n): localize all remaining in-file data arrays — English base fully complete
Converts every last bare-Swedish const array across landing sections
(STATS, TILES, CHAIN, PIPELINE, MODELS, DATASETS, PRINCIPLES, COLUMNS)
and shared components (data-artifact, provenance-badge) to {en,sv} Loc
objects consumed via useT(). Verified by per-file verify agent: 10/10
clean, zero remaining bare-Swedish display text. tsc 0 + build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 11:58:54 +02:00

104 lines
6.0 KiB
TypeScript

"use client";
import { useReveal } from "@/hooks/use-reveal";
import { useT } from "@/components/locale-provider";
type Variant = "table" | "map" | "schema" | "chart" | "grid";
type Loc = { en: string; sv: string };
const PROV = ["var(--prov-0)", "var(--prov-1)", "var(--prov-2)", "var(--prov-3)"];
const TABLE_ROWS: [string | Loc, string | Loc, 0 | 1 | 2 | 3][] = [
["Volvo Group", "GLEIF", 3],
["Equinor ASA", "Brreg", 3],
["Maersk A/S", "CVR", 2],
["Nokia Oyj", "PRH", 2],
[{ en: "Email (FI)", sv: "E-post (FI)" }, { en: "license", sv: "licens" }, 0],
];
const MAP_CELLS: [string, number][] = [
["SE", 98], ["NO", 96], ["DK", 94], ["FI", 89],
["IS", 0], ["NL", 0], ["DE", 0], ["FR", 0],
];
const CHART_BARS = [42, 61, 38, 74, 55, 88];
/**
* The generative, photo-free visual primitive. Every "image" surface uses it.
* Animates on scroll-into-view; settles to a complete static state under
* prefers-reduced-motion. Color discipline: mono + provenance squares + ONE red.
*/
export function DataArtifact({ variant, className = "" }: { variant: Variant; className?: string }) {
const ref = useReveal<HTMLDivElement>();
const t = useT();
// Resolve a value that may be a plain string (literal token) or a {en,sv} map.
const tx = (v: string | Loc): string => (typeof v === "string" ? v : t(v));
return (
<div ref={ref} className={`group grain-overlay relative overflow-hidden border border-border bg-background ${className}`}>
{variant === "table" ? (
<div>
<div className="flex items-center justify-between border-b border-border px-4 py-2.5">
<span className="font-mono text-[10px] uppercase tracking-[0.18em] text-foreground">dim_company</span>
<span className="font-mono text-[10px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "provenance", sv: "härkomst" })}</span>
</div>
{TABLE_ROWS.map((r, i) => (
<div key={i} className={`reveal-left delay-${i + 1} flex items-center justify-between border-b border-border px-4 py-3 transition-colors duration-200 last:border-b-0 hover:bg-secondary`}>
<span className="truncate text-[15px] tracking-tight">{tx(r[0])}</span>
<span className="ml-3 inline-flex items-center gap-2 font-mono text-[10px] uppercase tracking-[0.08em] text-muted-foreground">
<span className="inline-block h-2 w-2" style={{ backgroundColor: r[2] === 0 ? "transparent" : PROV[r[2]], border: r[2] === 0 ? `1px solid ${PROV[0]}` : "none" }} />
{tx(r[1])}
</span>
</div>
))}
</div>
) : null}
{variant === "map" ? (
<div className="grid grid-cols-4 gap-px bg-border">
{MAP_CELLS.map((c, i) => (
<div key={c[0]} className={`reveal-scale delay-${(i % 6) + 1} group/cell relative bg-background p-4 transition-colors duration-200 hover:bg-secondary`}>
<p className="font-mono text-lg font-semibold leading-none tracking-tight">{c[0]}</p>
<p className="mt-1 font-mono text-[10px] tracking-[0.08em] text-muted-foreground">{c[1] ? `${c[1]}%` : "—"}</p>
<div className="mt-3 h-px w-full bg-border">
<div className="h-full" style={{ width: `${c[1]}%`, backgroundColor: c[1] >= 95 ? "var(--prov-3)" : c[1] > 0 ? "var(--prov-2)" : "transparent" }} />
</div>
</div>
))}
</div>
) : null}
{variant === "schema" ? (
<div className="grid grid-cols-3 gap-4 p-5" style={{ backgroundImage: "linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px)", backgroundSize: "16px 16px" }}>
{[
{ n: "dim_company", key: true },
{ n: "fact_financials", key: false },
{ n: "bridge_provenance", key: true },
].map((e, i) => (
<div key={e.n} className={`reveal-scale delay-${i + 1} bg-background transition-transform duration-200 hover:-translate-y-0.5`} style={{ borderTop: e.key ? "2px solid var(--accent-red)" : "2px solid var(--foreground)", borderLeft: "1px solid var(--border)", borderRight: "1px solid var(--border)", borderBottom: "1px solid var(--border)" }}>
<div className="border-b border-border px-2.5 py-1.5 font-mono text-[10px] tracking-tight">{e.n}</div>
<div className="px-2.5 py-2 font-mono text-[9px] tracking-[0.08em] text-muted-foreground">id · key · src</div>
</div>
))}
</div>
) : null}
{variant === "chart" ? (
<div className="relative">
<span className="pointer-events-none absolute left-4 top-3 select-none font-mono text-[10px] uppercase tracking-[0.18em] text-muted-foreground">{t({ en: "coverage", sv: "täckning" })}</span>
<span className="pointer-events-none absolute right-4 top-3 select-none font-mono text-5xl font-semibold leading-none tracking-tighter text-border">06</span>
<div className="flex h-44 items-end gap-2.5 px-4 pb-4 pt-12">
{CHART_BARS.map((h, i) => (
<div key={i} className={`reveal delay-${(i % 6) + 1} flex-1 transition-opacity duration-200 ${i === CHART_BARS.length - 1 ? "" : "group-hover:opacity-60"}`} style={{ height: `${h}%`, backgroundColor: i === CHART_BARS.length - 1 ? "var(--accent-red)" : "var(--foreground)" }} />
))}
</div>
</div>
) : null}
{variant === "grid" ? (
<div className="relative flex h-44 items-center justify-center overflow-hidden" style={{ backgroundImage: "linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px)", backgroundSize: "18px 18px" }}>
<span className="select-none text-7xl font-semibold tracking-tighter text-border transition-colors duration-300 group-hover:text-muted-foreground">0pt</span>
<span className="animate-float absolute right-6 top-6 inline-block h-3 w-3" style={{ backgroundColor: "var(--accent-red)" }} />
</div>
) : null}
</div>
);
}