"use client"; import type { SourceKind } from "@dci/core"; import { Archive, ExternalLink } from "lucide-react"; import { fmtDate } from "@/lib/format"; import { SOURCE_KIND_LABEL } from "@/lib/labels"; import { Badge } from "./badge"; import { cn } from "./cn"; import { Tooltip } from "./popover"; /** * Provenance / source-kind badge (OPERATOR · GOVERNMENT · UTILITY · REGULATORY · FILING · DATASET · NEWS · COMMUNITY…). * Primary kinds (operator, government, utility, filing, cloud provider, registry) get a filled dot; secondary kinds * (news, secondary, dataset, community) a hollow one. Hover / focus shows the source, published & retrieved dates and * whether an archived copy exists (documentId). */ export interface SourceBadgeProps { kind: SourceKind; name?: string | null; url?: string | null; publishedAt?: string | null; retrievedAt?: string | null; /** an archived document id means the page was captured and can be reprocessed */ documentId?: string | null; size?: "xs" | "sm"; /** show the source name next to the kind */ withName?: boolean; className?: string; } const PRIMARY: ReadonlySet = new Set(["operator", "government", "utility", "filing", "cloud_provider", "registry"]); /** Short upper-case kind label used in dense tables ("REGULATORY" for government filings when the source says so). */ export const SOURCE_KIND_CAPS: Record = { operator: "OPERATOR", government: "GOVERNMENT", filing: "FILING", utility: "UTILITY", dataset: "DATASET", community: "COMMUNITY", secondary: "SECONDARY", news: "NEWS", cloud_provider: "CLOUD", registry: "REGISTRY", }; export function SourceBadge({ kind, name, url, publishedAt, retrievedAt, documentId, size = "xs", withName, className }: SourceBadgeProps) { const primary = PRIMARY.has(kind); const inner = ( {SOURCE_KIND_CAPS[kind]} {withName && name && {name}} ); const details = (
{name ?? SOURCE_KIND_LABEL[kind]}
{SOURCE_KIND_LABEL[kind]} · {primary ? "primary source" : "secondary source"}
{publishedAt &&
Published {fmtDate(publishedAt)}
} {retrievedAt &&
Retrieved {fmtDate(retrievedAt)}
}
{documentId ? "Archived copy on file" : "No archived copy recorded"}
{url && (
{safeHost(url)}
)}
); return {inner}; } function safeHost(url: string): string { try { return new URL(url).host.replace(/^www\./, ""); } catch { return url; } }