import React from "react"; import clsx from "clsx"; import { useLocation, useHistory } from "@docusaurus/router"; import { Tags } from "@site/src/components/blog"; export const BlogTOCItem = ({ id, value, level, activeId, onIdChange, }: { id: string; value: string; level: number; activeId: string; onIdChange?: (id: string) => void; }) => { React.useEffect(() => { const targetElement = document.getElementById(id); if (targetElement) { const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { onIdChange(id); } }); }, { rootMargin: "0px 0px -80% 0px", }, ); observer.observe(targetElement); return () => { observer.unobserve(targetElement); }; } }, [id]); return ( ); }; export const BlogTOC = (props) => { const history = useHistory(); const location = useLocation(); const { toc, hasTOC, activeId, setActiveId } = useTOC(props.toc); const onIdChange = (id) => { if (id !== `${location.hash ?? ""}`.replace("#", "")) { setActiveId(id); window.history.replaceState({}, "", `#${id}`); } }; return (
    {toc.map((item) => { return (
  • ); })}
); }; export const useTOC = (toc) => { const { hash } = useLocation(); const baseActiveId = `${hash}`.replace("#", ""); const [activeId, setActiveId] = React.useState( baseActiveId, ); React.useEffect(() => { setActiveId(baseActiveId); }, [baseActiveId]); const hasTOC = toc?.length > 0; return { toc, activeId, setActiveId, hasTOC, }; };