import { cn } from "@/lib/utils"; import { flags } from "@/lib/site"; import { isPlaceholder, splitPlaceholders } from "@/lib/legal"; import type { FactItem } from "@/content/home"; export type { FactItem }; export interface FactsProps { items: readonly FactItem[]; /** * `stack` = mono lines with gold ticks (hero, top right). * `table` = two-column label / value table on bone with a hairline frame (Rahmen). */ variant?: "stack" | "table"; /** Table heading (DM Mono caps), e.g. „Rahmen“. */ title?: string; className?: string; } /** * Renders „[…]“ segments in the accent colour (`--gold-deep` on light, `--gold` on dark). * * Deliberately flag-agnostic: cutting a placeholder out of a running sentence leaves * fragments („Auswertungsgespräch .“), so the launch switch is a build guard, not a * strip – `assertNoPlaceholders` in every content module aborts the build while a * placeholder is still open (src/lib/legal.ts, list in CONTENT_TODO). */ export function PlaceholderText({ text }: { text: string }) { return ( <> {splitPlaceholders(text).map((seg, i) => seg.placeholder ? ( {seg.text} ) : ( {seg.text} ), )} > ); } /** Drops whole placeholder ROWS when `flags.showPlaceholders` is off (inline placeholders inside a value are the build guard's job, not this filter's – see PlaceholderText). */ export function visibleFacts(items: readonly FactItem[]): FactItem[] { return items.filter((f) => flags.showPlaceholders || !(f.placeholder || isPlaceholder(f.value))); } /** * Facts stack (Format · Sprache · Ort · Dauer): DM Mono 12 px, one gold tick * per line, label muted, value in the foreground colour. Both variants are * ledgers – tick / label / value are columns with one left edge each, not an * inline run that starts the value at a different x on every row. */ export function Facts({ items, variant = "stack", title, className }: FactsProps) { const rows = visibleFacts(items); if (!rows.length) return null; if (variant === "table") { return (
{title}
}