"use client"; import { Handle, Position } from "@xyflow/react"; import { Check, Copy } from "lucide-react"; import type { MouseEvent, ReactNode } from "react"; import { useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/cn"; import type { HealthStatus } from "@/lib/topology-types"; const healthLabels: Record = { healthy: "Healthy", degraded: "Degraded", unhealthy: "Unhealthy", unknown: "Unknown", }; const solidHealthClasses: Record, string> = { healthy: "bg-green-500 hover:bg-green-600", degraded: "bg-yellow-500 hover:bg-yellow-600", unhealthy: "bg-red-500 hover:bg-red-600", }; interface HealthBadgeProps { status: HealthStatus; appearance?: "solid" | "summary" | "detail"; children?: ReactNode; className?: string; } export function HealthBadge({ status, appearance = "solid", children, className, }: HealthBadgeProps) { const content = children ?? healthLabels[status]; if (appearance === "summary") { const indicatorClasses = { healthy: "bg-green-500", degraded: "bg-yellow-500", unhealthy: "bg-red-500", unknown: "bg-gray-400", }[status]; return ( {content} ); } if (appearance === "detail") { return ( {content} ); } if (status === "unknown") { return ( {content} ); } return {content}; } interface TopologyNodeCardProps { selected: boolean; icon: ReactNode; iconClassName: string; title: ReactNode; description?: ReactNode; health: HealthStatus; children: ReactNode; } export function TopologyNodeCard({ selected, icon, iconClassName, title, description, health, children, }: TopologyNodeCardProps) { return (
{icon}

{title}

{description && (

{description}

)}
{children}
); } interface CompactRowProps { label: ReactNode; icon?: ReactNode; children?: ReactNode; className?: string; valueClassName?: string; } export function CompactRow({ label, icon, children, className, valueClassName }: CompactRowProps) { return (
{icon} {label} {children !== undefined && ( {children} )}
); } interface MetricRowProps { label: string; icon: ReactNode; usage?: string; limit: ReactNode; } export function MetricRow({ label, icon, usage, limit }: MetricRowProps) { return ( {usage && {usage} / } {limit} ); } export function DetailSection({ title, children }: { title: string; children: ReactNode }) { return (

{title}

{children}
); } export function DetailRow({ label, value }: { label: string; value: ReactNode }) { return (
{label}: {value}
); } interface CopyableCodeProps { value: string; title?: string; } export function CopyableCode({ value, title = "Copy address" }: CopyableCodeProps) { const [copied, setCopied] = useState(false); const handleCopy = async (event: MouseEvent) => { event.stopPropagation(); await navigator.clipboard.writeText(value); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (
{value}
); }