import { useEffect, useMemo, useState } from "react"; function OutlineBody({ groups, complete, count, total, active, showTitle }) { return ( <>

{count}/{total} Try-its complete

{showTitle ?

In this chapter

: null} {groups.map((g) => (

{g.label}

))} ); } export default function ChapterOutline({ groups, complete = {}, count = 0, total = 0, variant = "desktop", }) { const ids = useMemo( () => groups.flatMap((g) => g.items.map((item) => item.id)), [groups] ); const [active, setActive] = useState(ids[0] || ""); useEffect(() => { const els = ids.map((id) => document.getElementById(id)).filter(Boolean); if (!els.length || typeof IntersectionObserver === "undefined") return; const observer = new IntersectionObserver( (entries) => { const visible = entries .filter((e) => e.isIntersecting) .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top); if (visible[0]?.target?.id) setActive(visible[0].target.id); }, { rootMargin: "-88px 0px -55% 0px", threshold: [0, 0.1, 0.25, 0.5, 1] } ); els.forEach((el) => observer.observe(el)); return () => observer.disconnect(); }, [ids]); if (variant === "mobile") { return (
In this chapter
); } return ( ); }