UNPKG

alouette

Version:

A modern, customizable design system built on top of NativeWind v5 with configurable defaults

76 lines (63 loc) 2.15 kB
import { useEffect, useState } from "react"; import { animationDurationsMs } from "../../animationDurationsMs"; const startDelayMs = 100; const stepIntervalMs = 500; const completeDelayMs = 500; const resetDelayMs = 1000; /** * Time from `loading` going false until the ring has finished completing to * 100% and faded out — how long a consumer must keep the component mounted * to see the finish animation instead of cutting it off. */ export const indeterminateExitDurationMs = resetDelayMs + animationDurationsMs.fade; const random = (): number => Math.ceil(Math.random() * 100) / 100; /** * Advances toward 100 in decreasing increments so the bar appears to slow * down as it approaches completion, without ever reaching it on its own * (e.g. ~20% at 100ms, ~40% at 1s, ~60% at 2s, ~80% at 3s). */ function nextSimulatedProgress(progress: number): number { if (progress < 60) return progress + random() * 10 + 5; if (progress < 70) return progress + random() * 10 + 3; if (progress < 80) return progress + random() + 5; if (progress < 90) return progress + random() + 1; if (progress < 95) return progress + 0.1; return progress; } export function useSimulatedProgress(loading: boolean): { progress: number; hidden: boolean; } { const [progress, setProgress] = useState(1); const [hidden, setHidden] = useState(!loading); useEffect(() => { if (!loading) return undefined; setHidden(false); const startTimer = setTimeout(() => { setProgress(20); }, startDelayMs); const stepTimer = setInterval(() => { setProgress(nextSimulatedProgress); }, stepIntervalMs); return () => { clearTimeout(startTimer); clearInterval(stepTimer); }; }, [loading]); useEffect(() => { if (loading) return undefined; const completeTimer = setTimeout(() => { setProgress(100); }, completeDelayMs); const resetTimer = setTimeout(() => { setHidden(true); setProgress(1); }, resetDelayMs); return () => { clearTimeout(completeTimer); clearTimeout(resetTimer); }; }, [loading]); return { progress, hidden }; }