import React from "react"; import { useEffect, useState } from "react"; let navulliStyle = { marginBottom: "15px", } as React.CSSProperties; const getClassName = (level) => { switch (level) { case 1: navulliStyle = { ...navulliStyle, }; return "head1"; case 2: navulliStyle = { ...navulliStyle, marginLeft: "10px", }; return "head2"; case 3: navulliStyle = { ...navulliStyle, marginLeft: "20px", }; return "head3"; case 4: navulliStyle = { ...navulliStyle, marginLeft: "30px", }; return "head4"; default: return undefined; } }; const navStyle = { width: "220px", minWidth: "220px", padding: "16px", alignSelf: "flex-start", position: "-webkit-sticky", top: "48px", maxHeight: "calc(100vh - 70px)", overflow: "auto", marginTop: "150px", } as React.CSSProperties; interface Props { children?: React.ReactNode; className?: string; } const Toc = (props: Props) => { const { children, className = "" } = props; const [headings, setHeadings] = useState<any>([]); useEffect(() => { const elements = Array.from( document.querySelectorAll("h1, h2, h3, h4") ).map((elem) => ({ id: Math.random().toString(16).slice(-4), text: elem.textContent, level: Number(elem.nodeName.charAt(1)), })); console.log(elements); setHeadings(elements); }, []); return ( <nav style={navStyle} className={`absolute inset-y-0 right-0 w-16 ${className}`} > <ul style={navulliStyle}> {headings.map((heading) => ( <li key={heading.id} className={getClassName(heading.level)} style={navulliStyle} > <a href={`#${heading.id}`} onClick={(e) => { e.preventDefault(); document.querySelector(`#${heading.id}`)?.scrollIntoView({ behavior: "smooth", }); }} > {children} {heading.text} </a> </li> ))} </ul> </nav> ); }; export default Toc;