import type { ReactNode } from 'react'; import { Evidence } from '@/components/evidence/evidence'; import { cn } from '@/lib/cn'; import { fmtValue } from '@/lib/format'; import { propertyLabel, URL_KEYS } from '@/lib/site'; import type { Provenance } from '@/lib/types'; import { ProvenanceInline } from './provenance'; import { Missing } from './unavailable'; export type KVRow = { key: string; label?: ReactNode; value?: ReactNode; raw?: unknown; hint?: ReactNode; unit?: string | null }; /** * Dense spec list (
): label column + value + optional per-field provenance. Pass `provenance` (from EntityDetail) * to render "Source · tier · observed" under each value when known. Values fall back to `fmtValue(raw, key)`. * Pass `slug` (+ optional `entity`) to make every value with provenance an **evidence trigger** that opens the drawer * (`components/evidence`). Existing call sites without `slug` render exactly as before. */ export function KeyValue({ rows, provenance, className, dense = false, showMissing = false, slug, entity, }: { rows: KVRow[]; provenance?: Provenance; className?: string; dense?: boolean; showMissing?: boolean; slug?: string; entity?: { name?: string; entity_type?: string } | null; }) { const shown = rows.filter((r) => showMissing || r.value !== undefined || (r.raw !== undefined && r.raw !== null && r.raw !== '')); if (shown.length === 0) return

No structured attributes yet.

; return (
div]:py-1.5', className)}> {shown.map((r) => { const p = provenance?.[r.key]; const raw = r.raw; let value: ReactNode = r.value; let display: string | undefined; if (value === undefined) { if (raw === null || raw === undefined || raw === '') value = ; else if (URL_KEYS.has(r.key) && typeof raw === 'string' && /^https?:\/\//.test(raw)) value = ( {raw.replace(/^https?:\/\/(www\.)?/, '').replace(/\/$/, '')} ); else { display = fmtValue(raw, r.key); value = {display}; } } const canOpen = !!slug && !!p && raw !== null && raw !== undefined && raw !== '' && !(URL_KEYS.has(r.key) && typeof raw === 'string'); return (
{r.label ?? propertyLabel(r.key)}
{canOpen ? ( {value} ) : ( value )}
{r.hint &&
{r.hint}
} {p && }
); })}
); }