import { ExternalLink } from "lucide-react"; export type ContainerPort = { container: string; host_ip?: string; host_port?: string | null; }; const WILDCARD_IPS = new Set(["", "0.0.0.0", "::"]); /** Pick the host to link to: an explicit override, the bound * host IP if it's a concrete address, otherwise the host we're viewing from. */ function linkHost(hostIp: string | undefined, override?: string): string { if (override) return override; if (hostIp && !WILDCARD_IPS.has(hostIp)) return hostIp; return window.location.hostname; } /** Best-effort scheme guess — most homelab services are http; common TLS * ports get https. */ function scheme(hostPort: string, container: string): "http" | "https" { if (hostPort === "443" || hostPort === "8443") return "https"; if (container.startsWith("443/")) return "https"; return "http"; } /** Clickable chips for a container's published ports. `host` overrides the * link target. Renders nothing if unpublished. */ export function ContainerPorts({ ports, host, }: { ports: ContainerPort[]; host?: string; }) { const seen = new Set(); const published = ports.filter((p) => { if (!p.host_port || seen.has(p.host_port)) return false; seen.add(p.host_port); return true; }); if (published.length === 0) return null; return ( {published.map((p) => { const url = `${scheme(p.host_port!, p.container)}://${linkHost( p.host_ip, host )}:${p.host_port}`; return ( e.stopPropagation()} title={`Open ${url}`} className="inline-flex items-center gap-1 rounded-md bg-slate-100 px-2 py-0.5 font-mono text-xs text-accent hover:underline dark:bg-slate-700 dark:text-accent-dark" > {p.host_port} →{p.container} ); })} ); }