"use client"; import { useCallback, useEffect, useId, useState, useSyncExternalStore } from "react"; import { QuoteMark } from "@/components/ui/Icons"; type Item = { quote: string; author: string; role: string }; const INTERVAL_MS = 8000; const RM_QUERY = "(prefers-reduced-motion: reduce)"; function subscribeReducedMotion(cb: () => void) { const mq = window.matchMedia(RM_QUERY); mq.addEventListener("change", cb); return () => mq.removeEventListener("change", cb); } function getReducedMotion() { return window.matchMedia(RM_QUERY).matches; } export function TestimonialSlider({ items }: { items: Item[] }) { const [index, setIndex] = useState(0); const [paused, setPaused] = useState(false); const reduced = useSyncExternalStore(subscribeReducedMotion, getReducedMotion, () => false); const regionId = useId(); const go = useCallback( (n: number) => setIndex((i) => (i + n + items.length) % items.length), [items.length], ); useEffect(() => { if (items.length < 2 || paused || reduced) return; const t = setInterval(() => go(1), INTERVAL_MS); return () => clearInterval(t); }, [go, items.length, paused, reduced]); const current = items[index]; const multiple = items.length > 1; return (
setPaused(true)} onMouseLeave={() => setPaused(false)} onFocusCapture={() => setPaused(true)} onBlurCapture={(e) => { if (!e.currentTarget.contains(e.relatedTarget as Node)) setPaused(false); }} onKeyDown={(e) => { if (!multiple) return; if (e.key === "ArrowRight") go(1); if (e.key === "ArrowLeft") go(-1); }} >

{current.quote}

{current.author} {current.role ? , {current.role} : null}
{multiple ? (
    {items.map((_, i) => (
  • ))}
) : null}
); }