// components/mdx/TableOfContents.client.tsx "use client"; import { useEffect, useState } from 'react'; interface TableOfContentsItem { id: string; text: string; level: number; } interface TableOfContentsProps { items: TableOfContentsItem[]; title?: string; } export default function TableOfContents({ items = [], title = "目录" }: TableOfContentsProps) { const [activeId, setActiveId] = useState(""); useEffect(() => { if (items.length === 0) return; const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { setActiveId(entry.target.id); } }); }, { rootMargin: "0% 0% -80% 0%" } ); // 观察所有标题元素 items.forEach((item) => { const element = document.getElementById(item.id); if (element) { observer.observe(element); } }); return () => { items.forEach((item) => { const element = document.getElementById(item.id); if (element) { observer.unobserve(element); } }); }; }, [items]); const handleClick = (e: React.MouseEvent, id: string) => { e.preventDefault(); const element = document.getElementById(id); if (element) { element.scrollIntoView({ behavior: "smooth" }); window.history.pushState(null, "", `#${id}`); setActiveId(id); } }; if (!items || items.length === 0) { return null; } return ( ); }