import { Citation } from "@/lib/api"; import { displaySource } from "@/lib/format"; import { citationColor, scoreStrength, STRENGTH_META } from "@/lib/citations"; // Clean, user-facing locator (page / speaker+timestamp) — never raw char spans. function cleanLocator(c: Citation): string { if (c.speaker || c.start_s != null) { const t = (s?: number | null) => { if (s == null) return ""; const m = Math.floor(s / 60); const sec = Math.round(s % 60); return `${m}:${String(sec).padStart(2, "0")}`; }; const range = c.start_s != null ? `${t(c.start_s)}–${t(c.end_s)}` : ""; return [c.speaker, range].filter(Boolean).join(" · "); } if (c.page != null) return `p.${c.page}`; return ""; } function rgba(rgb: string, a: number): string { return rgb.replace("rgb(", "rgba(").replace(")", `,${a})`); } export function Citations({ citations, onOpenSource, }: { citations: Citation[]; onOpenSource?: (marker: number) => void; }) { if (!citations?.length) return null; return (
Sources · {citations.length}
    {citations.map((c) => { const loc = cleanLocator(c); const color = citationColor(c.marker); const strength = scoreStrength(c.score); const sm = strength ? STRENGTH_META[strength] : null; const clickable = !!onOpenSource; const Tag = clickable ? "button" : "div"; return (
  1. onOpenSource!(c.marker), "aria-label": `Open source ${c.marker}: ${displaySource(c.source)}`, } : {})} className={`flex w-full items-center gap-2.5 rounded-lg border border-edge bg-panel2 px-2.5 py-1.5 text-left text-sm transition ${ clickable ? "hover:border-edge2 hover:bg-panel" : "" }`} > {c.marker} {displaySource(c.source)} {loc && · {loc}} {sm && c.score != null && ( {c.score.toFixed(2)} )} {c.method && ( {c.method} )}
  2. ); })}
); }