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>
104 lines
6.0 KiB
TypeScript
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>
|
|
);
|
|
}
|