"use client"; import { Background, BackgroundVariant, Controls, MiniMap, Panel, ReactFlow } from "@xyflow/react"; import { useTheme } from "next-themes"; import { useCallback, useMemo, useState } from "react"; import "@xyflow/react/dist/style.css"; import { useGraphLayout } from "@/hooks/use-graph-layout"; import type { TopologyFilters, TopologyGraph, TopologyNodeData } from "@/lib/topology-types"; import { filterEdges, filterNodes } from "@/lib/topology-utils"; import { NodeDetailsPanel } from "./controls/node-details-panel"; import { TopologyToolbar } from "./controls/topology-toolbar"; import { nodeTypes } from "./nodes/node-types"; interface TopologyCanvasProps { graph: TopologyGraph; } export function TopologyCanvas({ graph }: TopologyCanvasProps) { const { resolvedTheme } = useTheme(); const [selectedNode, setSelectedNode] = useState(null); const [filters, setFilters] = useState({ showServers: true, showProxies: true, showK8sNodes: true, showConnections: true, searchQuery: "", }); const filteredNodes = useMemo(() => { return filterNodes(graph.nodes, filters); }, [graph.nodes, filters]); const filteredEdges = useMemo(() => { if (!filters.showConnections) return []; const visibleNodeIds = new Set(filteredNodes.map((node) => node.id)); return filterEdges(graph.edges, visibleNodeIds); }, [graph.edges, filteredNodes, filters.showConnections]); const { nodes, edges } = useGraphLayout({ nodes: filteredNodes, edges: filteredEdges, }); const onNodeClick = useCallback((_event: React.MouseEvent, node: any) => { setSelectedNode(node.data as TopologyNodeData); }, []); const onPaneClick = useCallback(() => { setSelectedNode(null); }, []); const handleCloseDetails = useCallback(() => { setSelectedNode(null); }, []); return (
{ const data = node.data as TopologyNodeData; const colors = { healthy: "var(--success)", degraded: "var(--warning)", unhealthy: "var(--destructive)", unknown: "var(--muted-foreground)", }; return colors[data.status] || "var(--muted-foreground)"; }} maskColor="color-mix(in oklch, var(--foreground) 8%, transparent)" className="border bg-card/95 shadow-md backdrop-blur-sm" />
); }