"use client" import 'lenis/dist/lenis.css' import { ReactLenis } from "lenis/react" import type { LenisRef } from "lenis/react" import React, { useEffect, useMemo, useRef } from "react" /** * LenisRoot mounts a Lenis instance at the document root. * - Runs only on the client ("use client") * - Uses reasonable defaults for desktop wheel/touch * - Respects prefers-reduced-motion by disabling smoothing * * Notes: * - The ReactLenis component exposes a ref (LenisRef) when you need to call methods * such as scrollTo or raf yourself. We attach a ref here so the instance can be * inspected during development and is ready for any future integrations. * - Importing 'lenis/dist/lenis.css' ensures the optional CSS required by Lenis is loaded. */ export function LenisRoot() { const lenisRef = useRef(null) const prefersReducedMotion = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches const options = useMemo( () => ({ // Let Lenis drive its own RAF loop (recommended for ReactLenis) autoRaf: true, // Enable smooth wheel scrolling when the user hasn't requested reduced motion smoothWheel: !prefersReducedMotion, // Enable a gentle smoothing for touch devices (set true to get smoothing on mobile) // You can change this to `false` if you prefer native touch scrolling. smoothTouch: !prefersReducedMotion, // Enable anchor handling so links to #ids are handled by Lenis anchors: true as const, // Interpolation factor (0..1) - lower = more smoothing. When reduced motion is requested, disable smoothing. lerp: prefersReducedMotion ? 1 : 0.08, }), [prefersReducedMotion] ) useEffect(() => { // Poll a few times until the ReactLenis ref is populated, then expose the instance let checks = 0 const maxChecks = 20 const interval = setInterval(() => { checks += 1 if (lenisRef.current?.lenis) { // eslint-disable-next-line no-console console.debug("Lenis initialized", lenisRef.current.lenis) // Expose on window for quick debugging in devtools try { // @ts-expect-error - dev-only debugging helper window.__lenis = lenisRef.current.lenis } catch (e) { /* ignore */ } // Ensure the instance is running try { lenisRef.current.lenis.start?.() } catch (e) { /* ignore */ } clearInterval(interval) return } if (checks >= maxChecks) { // eslint-disable-next-line no-console console.warn("Lenis did not initialize within expected time") clearInterval(interval) } }, 100) return () => { clearInterval(interval) } }, []) React.useEffect(() => { const instance = lenisRef.current?.lenis if (!instance) return const onScroll = (e: any) => { // eslint-disable-next-line no-console console.debug("lenis:scroll", e) } instance.on?.("scroll", onScroll) return () => { instance.off?.("scroll", onScroll) } }, []) return } export default LenisRoot