"use client"; import React, { useEffect } from "react"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; /** * AnimationProvider * Initializes GSAP + ScrollTrigger globally, refreshes on route changes, * and provides smooth defaults. */ export default function AnimationProvider({ children }: { children: React.ReactNode }) { useEffect(() => { gsap.registerPlugin(ScrollTrigger); // Global GSAP defaults for buttery animations gsap.defaults({ ease: "power3.out", duration: 0.8, }); const initDecorativeBlocks = () => { // Clean up previous block triggers to avoid duplicates ScrollTrigger.getAll().forEach((t) => { if (t.vars && (t.vars as any).id === "block-deco") { t.kill(); } }); const decorativeBlocks = document.querySelectorAll(".block-decoration"); decorativeBlocks.forEach((block) => { ScrollTrigger.create({ id: "block-deco", trigger: block, start: "top 92%", onEnter: () => { setTimeout(() => { block.classList.add("animated"); }, 150); }, onEnterBack: () => { setTimeout(() => { block.classList.add("animated"); }, 150); }, onLeave: () => { block.classList.remove("animated"); }, onLeaveBack: () => { block.classList.remove("animated"); }, }); }); }; // Run initializations initDecorativeBlocks(); // Refresh ScrollTrigger at staggered intervals to account for lazy-loaded assets/images over the network const timeouts = [ setTimeout(() => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }, 100), setTimeout(() => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }, 500), setTimeout(() => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }, 1500), setTimeout(() => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }, 3000), ]; // Refresh on full window load (when all images, styles, and fonts are in place) const handleLoad = () => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }; window.addEventListener("load", handleLoad); // Also refresh on window resize const handleResize = () => { initDecorativeBlocks(); ScrollTrigger.refresh(true); }; window.addEventListener("resize", handleResize); return () => { timeouts.forEach(clearTimeout); window.removeEventListener("load", handleLoad); window.removeEventListener("resize", handleResize); ScrollTrigger.getAll().forEach((t) => t.kill()); }; }, []); return <>{children}; }