import { useEffect, useRef, useState } from "react"; import ForceGraph2D, { ForceGraphMethods, LinkObject, NodeObject } from "react-force-graph-2d"; import { extractMemoIdFromName } from "@/helpers/resource-names"; import useNavigateTo from "@/hooks/useNavigateTo"; import { cn } from "@/lib/utils"; import { Memo, MemoRelation_Type } from "@/types/proto/api/v1/memo_service_pb"; import { LinkType, NodeType } from "./types"; import { convertMemoRelationsToGraphData } from "./utils"; interface Props { memo: Memo; className?: string; parentPage?: string; } const MAIN_NODE_COLOR = "#14b8a6"; const DEFAULT_NODE_COLOR = "#a1a1aa"; const MemoRelationForceGraph = ({ className, memo, parentPage }: Props) => { const navigateTo = useNavigateTo(); const [mode] = useState<"light">("light"); const containerRef = useRef(null); const graphRef = useRef, LinkObject> | undefined>(undefined); const [graphSize, setGraphSize] = useState({ width: 0, height: 0 }); useEffect(() => { if (!containerRef.current) return; setGraphSize(containerRef.current.getBoundingClientRect()); }, []); const onNodeClick = (node: NodeObject) => { if (node.memo.name === memo.name) return; navigateTo(`/${memo.name}`, { state: { from: parentPage, }, }); }; return (
(node.id === memo.name ? MAIN_NODE_COLOR : DEFAULT_NODE_COLOR)} nodeRelSize={3} nodeLabel={(node) => extractMemoIdFromName(node.memo.name).slice(0, 6).toLowerCase()} linkColor={() => (mode === "light" ? "#e4e4e7" : "#3f3f46")} graphData={convertMemoRelationsToGraphData(memo.relations.filter((r) => r.type === MemoRelation_Type.REFERENCE))} onNodeClick={onNodeClick} linkDirectionalArrowLength={3} linkDirectionalArrowRelPos={1} linkCurvature={0.25} />
); }; export default MemoRelationForceGraph;