tahamajs/IE / Projects /front /src /components /discovery /KnowledgeGraphExplorer.tsx
tahamajs's picture
download
raw
2.61 kB
// src/components/discovery/KnowledgeGraphExplorer.tsx
import { useRef, useCallback, useEffect, useState } from "react";
import { useKnowledgeGraph } from "@/hooks/useKnowledgeGraph";
import ForceGraph2D from "react-force-graph-2d";
import { Loader2, ZoomIn, ZoomOut, Maximize2, Search } from "lucide-react";
const NODE_COLORS: Record<string, string> = {
paper: "#0d9488", author: "#7c3aed", concept: "#ea580c", citation: "#2563eb",
};
export function KnowledgeGraphExplorer() {
const { graph, loading, centerNodeId, setCenterNodeId } = useKnowledgeGraph();
const fgRef = useRef<any>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [dimensions, setDimensions] = useState({ width: 800, height: 600 });
useEffect(() => {
const resize = () => {
if (containerRef.current) {
setDimensions({ width: containerRef.current.offsetWidth, height: containerRef.current.offsetHeight });
}
};
resize();
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
}, []);
if (loading || !graph) {
return <div className="flex justify-center py-12"><Loader2 className="w-6 h-6 animate-spin text-gray-400"/></div>;
}
return (
<div className="space-y-3">
<h2 className="text-xl font-bold flex items-center gap-2">Knowledge Graph Explorer</h2>
<div className="flex gap-2">
<input type="text" placeholder="Focus on a paper or author..." className="input flex-1 text-sm"
onKeyDown={e => { if (e.key === "Enter") setCenterNodeId(e.currentTarget.value); }} />
<button onClick={() => fgRef.current?.zoomToFit(400)} className="btn btn-ghost btn-sm"><Maximize2 className="w-4 h-4"/></button>
<button onClick={() => fgRef.current?.zoom(1.5)} className="btn btn-ghost btn-sm"><ZoomIn className="w-4 h-4"/></button>
<button onClick={() => fgRef.current?.zoom(0.75)} className="btn btn-ghost btn-sm"><ZoomOut className="w-4 h-4"/></button>
</div>
<div ref={containerRef} className="glass rounded-xl overflow-hidden" style={{ height: 500 }}>
<ForceGraph2D
ref={fgRef}
graphData={graph}
width={dimensions.width}
height={dimensions.height}
nodeLabel="label"
nodeColor={node => NODE_COLORS[(node as any).type] || "#999"}
nodeVal={node => (node as any).size ?? 3}
linkWidth={link => (link as any).strength ?? 1}
linkDirectionalArrowLength={3}
onNodeClick={node => setCenterNodeId((node as any).id)}
/>
</div>
</div>
);
}

Xet Storage Details

Size:
2.61 kB
·
Xet hash:
a3a43c1cfc9643c631aef72d1bf67906b44a28d5dc638405612415de867f6f3f

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.