{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "smooth-scroll",
  "title": "Smooth Scroll",
  "description": "Lenis smooth scrolling synced with GSAP ScrollTrigger, on the window or inside any scroll container, with a useLenis() hook.",
  "dependencies": [
    "lenis",
    "gsap"
  ],
  "registryDependencies": [
    "https://trytweenly.vercel.app/r/use-reduced-motion.json"
  ],
  "files": [
    {
      "path": "registry/new-york/smooth-scroll/smooth-scroll.tsx",
      "content": "\"use client\"\n\nimport { createContext, useContext, useEffect, useState } from \"react\"\nimport Lenis from \"lenis\"\nimport gsap from \"gsap\"\nimport { ScrollTrigger } from \"gsap/ScrollTrigger\"\nimport { useReducedMotion } from \"@/registry/new-york/hooks/use-reduced-motion\"\n\ngsap.registerPlugin(ScrollTrigger)\n\nconst LenisContext = createContext<Lenis | null>(null)\n\n/** The active Lenis instance, or null when smooth scrolling is off (e.g. reduced motion). */\nexport function useLenis() {\n  return useContext(LenisContext)\n}\n\nexport interface SmoothScrollProps {\n  /** Content that can read the Lenis instance with useLenis(). */\n  children?: React.ReactNode\n  /** Scroll container to smooth. Omit to smooth the whole page. Default: window */\n  wrapper?: HTMLElement | null\n  /** Linear interpolation per frame; lower is smoother but lags behind the wheel. Default: 0.12 */\n  lerp?: number\n  /** Multiplier for mouse wheel distance. Default: 1 */\n  wheelMultiplier?: number\n  /** Smooth touch scrolling too. Usually best left off on phones. Default: false */\n  syncTouch?: boolean\n  /** Smooth-scroll to in-page #anchors. Default: true */\n  anchors?: boolean\n  /** Turn smoothing on or off without unmounting. Default: true */\n  enabled?: boolean\n}\n\n/**\n * Lenis smooth scrolling driven by the GSAP ticker, so every ScrollTrigger stays\n * perfectly in sync. Works on the window or inside any scroll container.\n */\nexport function SmoothScroll({\n  children,\n  wrapper,\n  lerp = 0.12,\n  wheelMultiplier = 1,\n  syncTouch = false,\n  anchors = true,\n  enabled = true,\n}: SmoothScrollProps) {\n  const reduced = useReducedMotion()\n  const [lenis, setLenis] = useState<Lenis | null>(null)\n\n  useEffect(() => {\n    // A wrapper prop that is still null means the container hasn't mounted yet\n    if (!enabled || reduced || wrapper === null) return\n\n    const instance = new Lenis({\n      lerp,\n      wheelMultiplier,\n      syncTouch,\n      anchors,\n      ...(wrapper ? { wrapper, content: wrapper, eventsTarget: wrapper } : {}),\n    })\n    instance.on(\"scroll\", ScrollTrigger.update)\n    const tick = (time: number) => instance.raf(time * 1000)\n    gsap.ticker.add(tick)\n    gsap.ticker.lagSmoothing(0)\n    // Hand the instance to consumers after mount without setting state synchronously\n    queueMicrotask(() => setLenis(instance))\n    ScrollTrigger.refresh()\n\n    return () => {\n      gsap.ticker.remove(tick)\n      gsap.ticker.lagSmoothing(500, 33)\n      instance.destroy()\n      setLenis((current) => (current === instance ? null : current))\n    }\n  }, [enabled, reduced, wrapper, lerp, wheelMultiplier, syncTouch, anchors])\n\n  return <LenisContext.Provider value={lenis}>{children}</LenisContext.Provider>\n}\n",
      "type": "registry:component"
    }
  ],
  "docs": "Docs, live playground and every prop: https://trytweenly.vercel.app/docs/components/smooth-scroll",
  "type": "registry:component"
}