"use client"; import { useEffect } from "react"; import Lenis from "lenis"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; gsap.registerPlugin(ScrollTrigger); /** * App-wide smooth scrolling, wired for GSAP: * - Lenis is driven from GSAP's ticker (single rAF loop). * - ScrollTrigger.update fires on every Lenis scroll, so pinned/scrubbed * sections (projects showcase, AI video takeover) track perfectly. * - ScrollTrigger.refresh() after load/layout settle prevents stale trigger * positions (the old "section stays blank" bug). * Elements that scroll internally should set `data-lenis-prevent`. */ export default function SmoothScroll({ children }) { useEffect(() => { const lenis = new Lenis({ duration: 1.1, smoothWheel: true, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), }); lenis.on("scroll", ScrollTrigger.update); // Expose the instance so in-page anchors can trigger a smooth, offset-aware // scroll (Lenis forces `scroll-behavior: auto`, so native #hash jumps are // instant). Consumers call window.lenis?.scrollTo(target, { offset }). window.lenis = lenis; const raf = (time) => lenis.raf(time * 1000); gsap.ticker.add(raf); gsap.ticker.lagSmoothing(0); const refresh = () => ScrollTrigger.refresh(); const t = setTimeout(refresh, 400); window.addEventListener("load", refresh); return () => { clearTimeout(t); window.removeEventListener("load", refresh); gsap.ticker.remove(raf); lenis.off("scroll", ScrollTrigger.update); lenis.destroy(); if (window.lenis === lenis) delete window.lenis; }; }, []); return children; }