21 lines · 827 B
import { useEffect, useState } from "react";
import { useReducedMotion } from "~/hooks/use-reduced-motion";

const HOLD_STEPS = 3;

/**
 * Steps a product demo from 0 to `steps`, holds on the final frame, then loops. Server render and
 * reduced-motion visitors always see the finished frame, so nothing is hidden without JavaScript.
 */
export function useDemoTimeline(steps: number, intervalMs: number): number {
  const reduced = useReducedMotion();
  const [tick, setTick] = useState<number | null>(null);
  useEffect(() => {
    if (reduced) return;
    const timer = setInterval(() => setTick((value) => ((value ?? -1) + 1) % (steps + 1 + HOLD_STEPS)), intervalMs);
    return () => clearInterval(timer);
  }, [reduced, steps, intervalMs]);
  if (reduced || tick === null) return steps;
  return Math.min(tick, steps);
}