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 && }
);
})}
);
}