"use client"; import { type ReactNode, useEffect, useRef } from "react"; interface CinematicSectionProps { children: ReactNode; className?: string; effect?: "fade-scale" | "clip-reveal" | "parallax-depth" | "rotate-in"; id?: string; } export default function CinematicSection({ children, className = "", effect = "fade-scale", id, }: CinematicSectionProps) { const sectionRef = useRef(null); useEffect(() => { const el = sectionRef.current; if (!el) return; // Check reduced motion preference if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return; let cleanup: (() => void) | undefined; const setup = async () => { const [{ gsap }, { ScrollTrigger }] = await Promise.all([ import("gsap"), import("gsap/ScrollTrigger"), ]); gsap.registerPlugin(ScrollTrigger); switch (effect) { case "fade-scale": { gsap.set(el, { opacity: 0, scale: 0.92, transformOrigin: "center center", }); const tl = gsap.timeline({ scrollTrigger: { trigger: el, start: "top 85%", end: "top 20%", scrub: 0.8, }, }); tl.to(el, { opacity: 1, scale: 1, ease: "power2.out", }); cleanup = () => { tl.scrollTrigger?.kill(); tl.kill(); }; break; } case "clip-reveal": { gsap.set(el, { clipPath: "inset(15% 5% 15% 5%)", opacity: 0.3, }); const tl = gsap.timeline({ scrollTrigger: { trigger: el, start: "top 80%", end: "top 15%", scrub: 1, }, }); tl.to(el, { clipPath: "inset(0% 0% 0% 0%)", opacity: 1, ease: "power3.out", }); cleanup = () => { tl.scrollTrigger?.kill(); tl.kill(); }; break; } case "parallax-depth": { gsap.set(el, { y: 80, opacity: 0, rotateX: 4, transformPerspective: 1200, transformOrigin: "center bottom", }); const tl = gsap.timeline({ scrollTrigger: { trigger: el, start: "top 90%", end: "top 30%", scrub: 0.6, }, }); tl.to(el, { y: 0, opacity: 1, rotateX: 0, ease: "power2.out", }); cleanup = () => { tl.scrollTrigger?.kill(); tl.kill(); }; break; } case "rotate-in": { gsap.set(el, { opacity: 0, rotateY: -5, x: -60, transformPerspective: 1000, transformOrigin: "left center", }); const tl = gsap.timeline({ scrollTrigger: { trigger: el, start: "top 80%", end: "top 25%", scrub: 0.8, }, }); tl.to(el, { opacity: 1, rotateY: 0, x: 0, ease: "power3.out", }); cleanup = () => { tl.scrollTrigger?.kill(); tl.kill(); }; break; } } }; void setup(); return () => { cleanup?.(); }; }, [effect]); return (
{children}
); }