import { useMemo, useState } from 'react'; import type { SurfaceMap } from '@/api/types'; import { adaptSurfaceMap } from '../adapters/surface'; import { useElkLayout } from '../hooks/useElkLayout'; import { collectSearchMatches, extractNeighborhoodSubgraph, } from '../reduction/neighborhood'; import { SigmaGraph } from '../rendering/sigma/SigmaGraph'; interface SurfaceGraphCanvasProps { data: SurfaceMap; selectedNodeId: number | null; onSelectNode: (id: number) => void; } export function SurfaceGraphCanvas({ data, selectedNodeId, onSelectNode, }: SurfaceGraphCanvasProps) { const [searchQuery, setSearchQuery] = useState(''); const [neighborhoodOnly, setNeighborhoodOnly] = useState(false); const [radius, setRadius] = useState(2); const fullGraph = useMemo(() => adaptSurfaceMap(data), [data]); const selectedNodeKey = selectedNodeId == null ? null : String(selectedNodeId); const matches = useMemo( () => collectSearchMatches(fullGraph, searchQuery, 60), [fullGraph, searchQuery], ); const matchKeys = useMemo( () => new Set(matches.map((node) => node.key)), [matches], ); const visibleGraph = useMemo(() => { if (!neighborhoodOnly || !selectedNodeKey) return fullGraph; return extractNeighborhoodSubgraph(fullGraph, selectedNodeKey, radius); }, [fullGraph, neighborhoodOnly, radius, selectedNodeKey]); const { graph, isLoading, error } = useElkLayout(visibleGraph); if (error) { return (
Failed to compute the surface layout.
); } if (!graph) { return
Preparing surface graph…
; } const extras = ( <> ); return ( onSelectNode(Number(key))} searchMatchKeys={matchKeys} toolbarExtras={extras} loading={isLoading} /> ); }