Fork of atp.tools as a universal profile for people on the ATmosphere
at main 83 lines 2.1 kB view raw
1import { useEffect, useState, useCallback } from "react"; 2import { confetti } from "@tsparticles/confetti"; 3 4export default function Component({ 5 isAnimating, 6 setIsAnimating, 7}: { 8 isAnimating: boolean; 9 setIsAnimating: (value: boolean) => void; 10}) { 11 const [isBlocked, setIsBlocked] = useState(false); 12 13 const startConfetti = useCallback(() => { 14 const duration = 15 * 1000; 15 const animationEnd = Date.now() + duration; 16 const defaults = { startVelocity: 30, spread: 360, ticks: 60, zIndex: 0 }; 17 18 const randomInRange = (min: number, max: number) => { 19 return Math.random() * (max - min) + min; 20 }; 21 22 const interval = setInterval(() => { 23 const timeLeft = animationEnd - Date.now(); 24 25 if (timeLeft <= 0) { 26 setIsAnimating(false); 27 clearInterval(interval); 28 return; 29 } 30 31 const particleCount = 25 * (timeLeft / duration); 32 33 // Launch confetti from the left and right edges 34 confetti({ 35 ...defaults, 36 particleCount, 37 origin: { x: randomInRange(0.1, 0.3), y: Math.random() - 0.2 }, 38 }); 39 40 confetti({ 41 ...defaults, 42 particleCount, 43 origin: { x: randomInRange(0.7, 0.9), y: Math.random() - 0.2 }, 44 }); 45 }, 250); 46 47 return interval; 48 }, [setIsAnimating]); 49 50 useEffect(() => { 51 // Check if confetti is blocked 52 try { 53 const testConfetti = confetti; 54 if (!testConfetti) { 55 setIsBlocked(true); 56 } 57 } catch (e) { 58 setIsBlocked(true); 59 } 60 }, []); 61 // turn off confetti in 10 seconds 62 useEffect(() => { 63 if (!isAnimating) return; 64 65 const interval = setInterval(() => { 66 // if not blocked, start confetti 67 if (!isBlocked) { 68 startConfetti(); 69 } 70 if (Date.now() > 10000) { 71 setIsAnimating(false); 72 clearInterval(interval); 73 } 74 }, 1000); 75 76 return () => clearInterval(interval); 77 }, [isAnimating, setIsAnimating]); 78 79 // cover the whole page 80 return ( 81 <div className="fixed top-0 left-0 right-0 bottom-0 -z-20 bg-transparent"></div> 82 ); 83}