'use client'; import { useEffect, useRef, useState } from 'react'; import { ForceGraph } from './ForceGraph'; import { GraphFilterSidebar } from './GraphFilterSidebar'; import { SectionDrawer } from './SectionDrawer'; import type { UseGraphExplorerReturn } from '@/hooks/useGraphExplorer'; interface Props extends UseGraphExplorerReturn { onChatAboutSection: ( sectionId: string, title: string, docName: string, jurisdiction: string, ) => void; } export function GraphExplorer({ topology, isLoading, error, selectedNode, hoveredNode, sectionContent, isSectionLoading, filters, setSelectedNode, setHoveredNode, setFilters, navigateToNode, onChatAboutSection, }: Props) { const containerRef = useRef(null); const [dims, setDims] = useState({ width: 0, height: 0 }); useEffect(() => { if (!containerRef.current) { return; } const ro = new ResizeObserver(entries => { for (const entry of entries) { const { width, height } = entry.contentRect; setDims({ width: Math.floor(width), height: Math.floor(height) }); } }); ro.observe(containerRef.current); return () => ro.disconnect(); }, []); const nodes = topology?.nodes ?? []; const edges = topology?.edges ?? []; return (

Graph Explorer

{nodes.length} sections / {edges.length} relationships

Live topology
{isLoading ? (
{[0, 1, 2].map(i => ( ))} Loading graph
) : null} {error ? (

Graph unavailable

{error}

) : null} {!isLoading && !error && nodes.length === 0 ? (

No section relationships found

Run ingestion to populate the graph.

) : null} {dims.width > 0 && dims.height > 0 && nodes.length > 0 ? ( setSelectedNode(node)} onNodeHover={setHoveredNode} width={dims.width} height={dims.height} /> ) : null} setSelectedNode(null)} onNodeNavigate={navigateToNode} onChatAboutSection={onChatAboutSection} />
); }