"use client"; // Adapted from Kokonut UI (@dorianbaffier), MIT. See THIRD_PARTY_NOTICES.md. import { useEffect, useImperativeHandle, useRef, useState, type ComponentProps, } from "react"; export interface ScrollTextProps extends Omit< ComponentProps<"div">, "children" > { texts: readonly string[]; label: string; } export function ScrollText({ texts, label, className = "", onScroll, ref: forwardedRef, ...props }: ScrollTextProps) { const ref = useRef(null); useImperativeHandle(forwardedRef, () => ref.current!, []); const [active, setActive] = useState(0); const update = () => { const el = ref.current; if (!el) return; const center = el.scrollTop + el.clientHeight / 2; let nearest = 0, distance = Infinity; Array.from(el.children).forEach((child, i) => { const node = child as HTMLElement; const d = Math.abs(node.offsetTop + node.offsetHeight / 2 - center); if (d < distance) { distance = d; nearest = i; } }); setActive(nearest); }; useEffect(() => { update(); const observer = new ResizeObserver(update); if (ref.current) observer.observe(ref.current); return () => observer.disconnect(); }, [texts]); return (
{ update(); onScroll?.(event); }} > {texts.map((text, i) => (
{text}
))}
); }