import React, { useState, useEffect } from 'react'; import { TocItem } from '@/lib/toc'; import { cn } from '@/lib/utils'; import { ChevronRight, ChevronDown, Circle } from 'lucide-react'; interface TableOfContentsListProps { toc: TocItem[]; depth?: number; isMobile?: boolean; activeId?: string; defaultOpen?: boolean; } export function TableOfContentsList({ toc, depth = 0, isMobile = false, activeId, defaultOpen = false }: TableOfContentsListProps) { if (!toc || toc.length === 0) return null; return ( ); } function TocItemRenderer({ heading, depth, isMobile, activeId, defaultOpen }: { heading: TocItem, depth: number, isMobile: boolean, activeId?: string, defaultOpen: boolean }) { const [isOpen, setIsOpen] = useState(defaultOpen || depth < 1); // Expand root items by default const hasChildren = heading.children.length > 0; // Check if this item matches active ID directly const isActive = activeId === heading.slug; const itemRef = React.useRef(null); React.useEffect(() => { if (isActive && itemRef.current) { itemRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } }, [isActive]); // Check if any child is active (to auto-expand) const isChildActive = React.useMemo(() => { const checkActive = (items: TocItem[]): boolean => { return items.some(item => item.slug === activeId || checkActive(item.children)); }; return checkActive(heading.children); }, [heading.children, activeId]); useEffect(() => { if (isChildActive || defaultOpen) { setIsOpen(true); } }, [isChildActive, defaultOpen]); const handleToggle = (e: React.MouseEvent) => { if (hasChildren) { e.preventDefault(); e.stopPropagation(); setIsOpen(!isOpen); } }; return (
  • {/* Active Indicator Line (Left Overlay) */} {isActive && (
    )} {isActive && !isMobile && (
    )} {/* Indent / Icon */} isMobile && e.stopPropagation()} > {heading.text}
    {hasChildren && isOpen && ( )}
  • ); }