"use client"; import { ReactNode, useEffect } from "react"; import Lenis from "@studio-freight/lenis"; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; interface LenisProviderProps { children: ReactNode; root?: boolean; // If true, applies to the window scroll. If false, applies to a specific div. className?: string; // Only relevant if root is false } /** * Provides smooth scrolling using Lenis. * This component should ideally wrap the entire application in layout.tsx. * If `root` is false, it can be applied to a specific scrollable div. */ export function LenisSmoothScroll({ children, root = true, className }: LenisProviderProps) { useEffect(() => { const lenis = new Lenis({ duration: 1.2, easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), // https://www.desmos.com/calculator/brs54l4xgi orientation: "vertical", gestureOrientation: "vertical", smoothWheel: true, wheelMultiplier: 1, smoothTouch: false, touchMultiplier: 2, syncTouch: false, infinite: false, }); function raf(time: DOMHighResTimeStamp) { lenis.raf(time); requestAnimationFrame(raf); } requestAnimationFrame(raf); // Integrate with GSAP ScrollTrigger // This is crucial for GSAP ScrollTrigger to work correctly with Lenis. // Ensure GSAP and ScrollTrigger are already registered globally or imported locally. const syncScroll = () => { // Check if GSAP and ScrollTrigger are available globally or imported. // If using GSAP context, pass the context. if (typeof window !== 'undefined' && window.innerWidth > 768) { // Example: only enable for larger screens lenis.on('scroll', ScrollTrigger.update); gsap.ticker.add((time) => { lenis.raf(time * 1000) }) gsap.ticker.lagSmoothing(0) } }; // Delay syncScroll to ensure ScrollTrigger is registered if it's external const timeout = setTimeout(syncScroll, 0); return () => { clearTimeout(timeout); lenis.destroy(); // Remove the listener for GSAP ScrollTrigger if it was added if (typeof window !== 'undefined' && window.innerWidth > 768) { gsap.ticker.remove(lenis.raf) // lenis.off('scroll', ScrollTrigger.update); // Lenis handles removing its own listeners } }; }, []); if (root) { return <>{children}>; } else { // If not root, apply to a specific div return (