import { useColorScheme } from "@mui/joy"; import { useEffect, useRef, useState } from "react"; import ForceGraph2D, { ForceGraphMethods, LinkObject, NodeObject } from "react-force-graph-2d"; import useNavigateTo from "@/hooks/useNavigateTo"; import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service"; import { Memo } from "@/types/proto/api/v1/memo_service"; import { cn } from "@/utils"; import { memoLink } from "@/utils/memo"; 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 } = useColorScheme(); 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(memoLink(memo.name), { state: { from: parentPage, }, }); }; return (
(node.id === memo.name ? MAIN_NODE_COLOR : DEFAULT_NODE_COLOR)} nodeRelSize={3} nodeLabel={(node) => node.memo.uid.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;