"use client"; import { List, ChevronDown, ChevronUp } from "lucide-react"; import TocObserver from "./toc-observer"; import * as React from "react"; import { useRef, useMemo } from "react"; import { usePathname } from "next/navigation"; import { Button } from "./ui/button"; import { motion, AnimatePresence } from "framer-motion"; import { useScrollPosition, useActiveSection } from "@/hooks"; import { TocItem } from "@/lib/toc"; interface MobTocProps { tocs: TocItem[]; } const useClickOutside = (ref: React.RefObject, callback: () => void) => { const handleClick = React.useCallback((event: MouseEvent) => { if (ref.current && !ref.current.contains(event.target as Node)) { callback(); } }, [ref, callback]); React.useEffect(() => { document.addEventListener('mousedown', handleClick); return () => { document.removeEventListener('mousedown', handleClick); }; }, [handleClick]); }; export default function MobToc({ tocs }: MobTocProps) { const pathname = usePathname(); const [isExpanded, setIsExpanded] = React.useState(false); const tocRef = useRef(null); const contentRef = useRef(null); // Use custom hooks const { activeId, setActiveId } = useActiveSection(tocs); // Only show on /docs pages const isDocsPage = useMemo(() => pathname?.startsWith('/docs'), [pathname]); // Toggle expanded state const toggleExpanded = React.useCallback((e: React.MouseEvent) => { e.stopPropagation(); setIsExpanded(prev => !prev); }, []); // Close TOC when clicking outside useClickOutside(tocRef, () => { if (isExpanded) { setIsExpanded(false); } }); // Handle body overflow when TOC is expanded React.useEffect(() => { if (isExpanded) { document.body.style.overflow = 'hidden'; } else { document.body.style.overflow = ''; } return () => { document.body.style.overflow = ''; }; }, [isExpanded]); // Don't render anything if not on docs page or no TOC items if (!isDocsPage || !tocs?.length) return null; const chevronIcon = isExpanded ? ( ) : ( ); return (
{isExpanded && ( )}
); }