UNPKG

@14islands/r3f-scroll-rig

Version:

Progressively enhance any React website with WebGL using @react-three/fiber

1 lines 35.6 kB
{"version":3,"file":"scrollbar.cjs","sources":["../src/config.ts","../src/store.ts","../src/scrollbar/useScrollbar.ts","../src/hooks/useIsomorphicLayoutEffect.ts","../src/scrollbar/SmoothScrollbar.tsx","../src/hooks/useWindowSize.ts","../src/utils/math.ts","../src/hooks/useTracker.ts"],"sourcesContent":["// Global config\n\n// avoid Three types to ease tree shaking\ntype PreloadCallback = (gl: any, scene: any, camera: any) => void\n\nexport const config = {\n // Execution order for useFrames (highest = last render)\n PRIORITY_PRELOAD: 0,\n PRIORITY_SCISSORS: 1,\n PRIORITY_VIEWPORTS: 1,\n PRIORITY_GLOBAL: 1000,\n\n DEFAULT_SCALE_MULTIPLIER: 1,\n\n // Global rendering props\n preloadQueue: [] as PreloadCallback[],\n}\n","import create from 'zustand'\nimport { config } from './config'\nimport type Lenis from 'lenis'\n\nimport { ScrollCallback, ScrollData } from './scrollbar/SmoothScrollbarTypes'\n\ninterface ScrollRigStore {\n debug: boolean\n scaleMultiplier: number\n globalRender: boolean\n globalPriority: number\n globalClearDepth: boolean\n globalRenderQueue: false | any[]\n clearGlobalRenderQueue: () => void\n isCanvasAvailable: boolean\n hasSmoothScrollbar: boolean\n canvasChildren: Record<string, any | undefined>\n updateCanvas: (key: string, newProps: any) => void\n renderToCanvas: (key: string, mesh: any, props: any) => void\n removeFromCanvas: (key: string, dispose: boolean) => void\n pageReflow: number\n requestReflow: () => void\n scroll: ScrollData\n __lenis: Lenis | undefined\n scrollTo: (target: any) => void\n onScroll: (cb: ScrollCallback) => () => void\n}\n\nconst useCanvasStore = create<ScrollRigStore>((set) => ({\n // //////////////////////////////////////////////////////////////////////////\n // GLOBAL ScrollRig STATE\n // //////////////////////////////////////////////////////////////////////////\n debug: false,\n scaleMultiplier: config.DEFAULT_SCALE_MULTIPLIER,\n\n globalRender: true,\n globalPriority: config.PRIORITY_GLOBAL,\n globalClearDepth: false,\n\n globalRenderQueue: false,\n clearGlobalRenderQueue: () => set(() => ({ globalRenderQueue: false })),\n\n // true if WebGL initialized without errors\n isCanvasAvailable: false,\n\n // true if <VirtualScrollbar> is currently enabled\n hasSmoothScrollbar: false,\n\n // map of all components to render on the global canvas\n canvasChildren: {},\n\n // add component to canvas\n renderToCanvas: (key, mesh, props = {}) =>\n set(({ canvasChildren }) => {\n // check if already mounted\n if (Object.getOwnPropertyDescriptor(canvasChildren, key)) {\n // increase usage count\n canvasChildren[key].instances += 1\n canvasChildren[key].props.inactive = false\n return { canvasChildren }\n } else {\n // otherwise mount it\n const obj = { ...canvasChildren, [key]: { mesh, props, instances: 1 } }\n return { canvasChildren: obj }\n }\n }),\n\n // pass new props to a canvas component\n updateCanvas: (key, newProps) =>\n // @ts-ignore\n set(({ canvasChildren }) => {\n if (!canvasChildren[key]) return\n const {\n [key]: { mesh, props, instances },\n } = canvasChildren\n const obj = {\n ...canvasChildren,\n [key]: { mesh, props: { ...props, ...newProps }, instances },\n }\n // console.log('updateCanvas', key, { ...props, ...newProps })\n return { canvasChildren: obj }\n }),\n\n // remove component from canvas\n removeFromCanvas: (key, dispose = true) =>\n set(({ canvasChildren }) => {\n // check if remove or reduce instances\n if (canvasChildren[key]?.instances > 1) {\n // reduce usage count\n canvasChildren[key].instances -= 1\n return { canvasChildren }\n } else {\n if (dispose) {\n // unmount since no longer used\n const { [key]: _omit, ...obj } = canvasChildren // make a separate copy of the obj and omit\n return { canvasChildren: obj }\n } else {\n // or tell it that it is \"inactive\"\n canvasChildren[key].instances = 0\n canvasChildren[key].props.inactive = true\n return { canvasChildren: { ...canvasChildren } }\n }\n }\n }),\n\n // Used to ask components to re-calculate their positions after a layout reflow\n pageReflow: 0,\n requestReflow: () => {\n set((state) => {\n return { pageReflow: state.pageReflow + 1 }\n })\n },\n\n // keep track of scrollbar\n scroll: {\n y: 0,\n x: 0,\n limit: 0,\n velocity: 0,\n progress: 0,\n direction: 0,\n scrollDirection: undefined,\n },\n __lenis: undefined,\n scrollTo: () => {},\n onScroll: () => () => {},\n}))\n\nexport { useCanvasStore }\n","import { useCanvasStore } from '../store'\n\n/**\n * Public interface for ScrollRig\n */\nexport const useScrollbar = () => {\n const enabled = useCanvasStore((state) => state.hasSmoothScrollbar)\n const scroll = useCanvasStore((state) => state.scroll)\n const scrollTo = useCanvasStore((state) => state.scrollTo)\n const onScroll = useCanvasStore((state) => state.onScroll)\n const __lenis = useCanvasStore((state) => state.__lenis)\n\n return {\n enabled,\n scroll,\n scrollTo,\n onScroll,\n __lenis,\n }\n}\n","import { useEffect, useLayoutEffect as vanillaUseLayoutEffect } from 'react'\n\nexport const isBrowser = typeof window !== 'undefined'\n\nexport const useLayoutEffect = isBrowser ? vanillaUseLayoutEffect : useEffect\n","import { useEffect, useRef, useCallback, forwardRef, useImperativeHandle } from 'react'\nimport Lenis, { ScrollCallback, VirtualScrollCallback } from 'lenis'\n\nimport { useLayoutEffect } from '../hooks/useIsomorphicLayoutEffect'\nimport { useCanvasStore } from '../store'\nimport { ISmoothScrollbar, ScrollToTarget, ScrollToConfig } from './SmoothScrollbarTypes'\n\nconst POINTER_EVENTS_ENABLE_VELOCITY = 1\nconst POINTER_EVENTS_DISABLE_VELOCITY = 1.5\n\nconst SmoothScrollbarImpl = (\n {\n children,\n enabled = true,\n locked = false,\n scrollRestoration = 'auto',\n disablePointerOnScroll = true,\n horizontal = false,\n scrollInContainer = false,\n updateGlobalState = true,\n onScroll,\n config = {},\n invalidate = () => {},\n addEffect,\n }: ISmoothScrollbar,\n ref: any\n) => {\n const lenis = useRef<Lenis>()\n const preventPointer = useRef(false)\n const globalScrollState = useCanvasStore((s) => s.scroll)\n\n // Expose lenis imperative API\n useImperativeHandle(ref, () => ({\n start: () => lenis.current?.start(),\n stop: () => lenis.current?.stop(),\n on: (event: 'scroll' | 'virtual-scroll', cb: ScrollCallback | VirtualScrollCallback) =>\n // @ts-ignore\n lenis.current?.on(event, cb),\n scrollTo: (target: ScrollToTarget, props: ScrollToConfig) => lenis.current?.scrollTo(target, props),\n raf: (time: number) => lenis.current?.raf(time),\n __lenis: lenis.current,\n }))\n\n // disable pointer events while scrolling to avoid slow event handlers\n const preventPointerEvents = useCallback(\n (prevent: boolean) => {\n if (!disablePointerOnScroll) return\n if (preventPointer.current !== prevent) {\n preventPointer.current = prevent\n document.documentElement.style.pointerEvents = prevent ? 'none' : 'auto'\n }\n },\n [disablePointerOnScroll, preventPointer]\n )\n\n // apply chosen scroll restoration\n useLayoutEffect(() => {\n if ('scrollRestoration' in window.history) {\n window.history.scrollRestoration = scrollRestoration\n }\n }, [])\n\n // INIT LENIS\n useLayoutEffect(() => {\n // Set up scroll containers - allows scrolling without resizing window on iOS/mobile\n const html = document.documentElement\n const wrapper = document.body\n const content = document.body.firstElementChild\n\n html.classList.toggle('ScrollRig-scrollHtml', scrollInContainer)\n wrapper.classList.toggle('ScrollRig-scrollWrapper', scrollInContainer)\n\n if (scrollInContainer) {\n Object.assign(config, {\n smoothTouch: true,\n wrapper,\n content,\n })\n }\n\n lenis.current = new Lenis({\n orientation: horizontal ? 'horizontal' : 'vertical',\n ...config,\n // override and disable all smooth settings if scrollbar is disabled\n ...(!enabled ? { smoothWheel: false, syncTouch: false, smoothTouch: false } : {}),\n })\n\n // let r3f drive the frameloop\n let removeEffect: () => void\n if (addEffect) {\n removeEffect = addEffect((time: number) => lenis.current?.raf(time))\n } else {\n // manual animation frame\n // TODO use framer motion / popmotion render loop?\n let _raf: number\n function raf(time: number) {\n lenis.current?.raf(time)\n _raf = requestAnimationFrame(raf)\n }\n _raf = requestAnimationFrame(raf)\n removeEffect = () => cancelAnimationFrame(_raf)\n }\n\n return () => {\n removeEffect()\n lenis.current?.destroy()\n }\n }, [enabled])\n\n // BIND TO LENIS SCROLL EVENT\n useLayoutEffect(() => {\n const _lenis = lenis.current\n const _onScroll = ({ scroll, limit, velocity, direction, progress }: any) => {\n const y = !horizontal ? scroll : 0\n const x = horizontal ? scroll : 0\n\n // update global scroll store\n if (updateGlobalState) {\n globalScrollState.y = y\n globalScrollState.x = x\n globalScrollState.limit = limit\n globalScrollState.velocity = velocity\n globalScrollState.direction = direction\n globalScrollState.progress = progress || 0 // avoid NaN from Lenis\n }\n\n if (Math.abs(velocity) > POINTER_EVENTS_DISABLE_VELOCITY) {\n preventPointerEvents(true)\n }\n if (Math.abs(velocity) < POINTER_EVENTS_ENABLE_VELOCITY) {\n preventPointerEvents(false)\n }\n\n onScroll && onScroll({ scroll, limit, velocity, direction, progress })\n\n invalidate() // demand a R3F frame on scroll\n }\n\n _lenis?.on('scroll', _onScroll)\n\n // update global state\n if (updateGlobalState) {\n globalScrollState.scrollDirection = horizontal ? 'horizontal' : 'vertical'\n\n // expose global scrollTo and onScroll function to subscribe to scroll events\n useCanvasStore.setState({\n __lenis: _lenis,\n scrollTo: (...args) => {\n _lenis?.scrollTo(...args)\n },\n onScroll: (cb: ScrollCallback) => {\n _lenis?.on('scroll', cb)\n // @ts-ignore\n _lenis?.emit() // send current scroll to new subscriber\n return () => _lenis?.off('scroll', cb)\n },\n })\n\n // Set current scroll position on load in case reloaded further down\n useCanvasStore.getState().scroll.y = window.scrollY\n useCanvasStore.getState().scroll.x = window.scrollX\n }\n\n // fire our internal scroll callback to update globalState\n // @ts-ignore\n _lenis?.emit()\n return () => {\n _lenis?.off('scroll', _onScroll)\n // reset global store\n if (updateGlobalState)\n useCanvasStore.setState({\n __lenis: undefined,\n onScroll: () => () => {},\n scrollTo: () => {},\n })\n }\n }, [enabled])\n\n // Interaction events - invalidate R3F loop and enable pointer events\n useLayoutEffect(() => {\n const invalidateOnWheelEvent = () => invalidate()\n const onPointerInteraction = () => preventPointerEvents(false)\n window.addEventListener('pointermove', onPointerInteraction)\n window.addEventListener('pointerdown', onPointerInteraction)\n window.addEventListener('wheel', invalidateOnWheelEvent)\n return () => {\n window.removeEventListener('pointermove', onPointerInteraction)\n window.removeEventListener('pointerdown', onPointerInteraction)\n window.removeEventListener('wheel', invalidateOnWheelEvent)\n }\n }, [])\n\n // Mark as enabled in global state\n useEffect(() => {\n if (updateGlobalState) {\n document.documentElement.classList.toggle('js-smooth-scrollbar-enabled', enabled)\n document.documentElement.classList.toggle('js-smooth-scrollbar-disabled', !enabled)\n useCanvasStore.setState({ hasSmoothScrollbar: enabled })\n }\n return () => {\n // cleanup\n document.documentElement.classList.remove('js-smooth-scrollbar-enabled')\n document.documentElement.classList.remove('js-smooth-scrollbar-disabled')\n }\n }, [enabled])\n\n useEffect(() => {\n locked ? lenis.current?.stop() : lenis.current?.start()\n }, [locked])\n\n {\n /* Use function child so we can spread props\n - for instance disable pointer events while scrolling */\n }\n return children ? children({}) : null\n}\n\nexport const SmoothScrollbar = forwardRef<any, ISmoothScrollbar>(SmoothScrollbarImpl)\n","import { useState, useEffect } from 'react'\nimport { ResizeObserver as Polyfill } from '@juggle/resize-observer'\nimport pkg from 'debounce'\n\nconst isBrowser = typeof window !== 'undefined'\nexport interface WindowSize {\n width: number\n height: number\n}\n\ntype ConfigProps = {\n debounce?: number\n}\n\n/*\n * Triggers a resize only if the Canvas DOM element changed dimensions - not on window resize event\n *\n * This is to avoid costly re-renders when the URL bar is scrolled away on mobile\n *\n * Based on: https://usehooks.com/useWindowSize/\n */\n\nexport function useWindowSize({ debounce = 0 }: ConfigProps = {}) {\n // Initialize state with undefined width/height so server and client renders match\n // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/\n const [windowSize, setWindowSize] = useState<WindowSize>({\n width: isBrowser ? window.innerWidth : Infinity,\n height: isBrowser ? window.innerHeight : Infinity,\n })\n\n useEffect(() => {\n // check if we can find a canvas - if so, base size on canvas instead of window\n // since 100vh !== window.innerHeight on mobile\n const canvasEl = document.getElementById('ScrollRig-canvas')\n\n // Handler to call on window resize\n function handleResize() {\n const width = canvasEl ? canvasEl.clientWidth : window.innerWidth\n const height = canvasEl ? canvasEl.clientHeight : window.innerHeight\n\n if (width !== windowSize.width || height !== windowSize.height) {\n // Set window width/height to state\n setWindowSize({\n width,\n height,\n })\n }\n }\n\n const debouncedResize = pkg.debounce(handleResize, debounce)\n\n // Add event listener\n const ResizeObserver = window.ResizeObserver || Polyfill\n let observer: ResizeObserver\n if (canvasEl) {\n observer = new ResizeObserver(debouncedResize)\n observer.observe(canvasEl)\n } else {\n window.addEventListener('resize', debouncedResize)\n }\n // Call handler right away so state gets updated with initial window size\n handleResize()\n // Remove event listener on cleanup\n return () => {\n window.removeEventListener('resize', debouncedResize)\n observer?.disconnect()\n }\n }, [windowSize, setWindowSize])\n\n return windowSize\n}\n","// Linear mapping from range <a1, a2> to range <b1, b2>\nexport function mapLinear(x: number, a1: number, a2: number, b1: number, b2: number) {\n return b1 + ((x - a1) * (b2 - b1)) / (a2 - a1)\n}\n","// https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules\n/// <reference path=\"../types/global.ts\" />\n\nimport { useRef, useCallback, useEffect, useMemo, useState, MutableRefObject } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport { useWindowSize } from './useWindowSize'\nimport vecn from 'vecn'\n\nimport { useLayoutEffect } from '../hooks/useIsomorphicLayoutEffect'\nimport { mapLinear } from '../utils/math'\nimport { useCanvasStore } from '../store'\nimport { useScrollbar } from '../scrollbar/useScrollbar'\nimport type { ScrollData } from '../scrollbar/SmoothScrollbarTypes'\n\nimport type { Rect, Bounds, TrackerOptions, Tracker, ScrollState, UpdateCallback } from './useTrackerTypes'\n\nfunction updateBounds(bounds: Bounds, rect: Rect, scroll: ScrollData, size: any) {\n bounds.top = rect.top - (scroll.y || 0)\n bounds.bottom = rect.bottom - (scroll.y || 0)\n bounds.left = rect.left - (scroll.x || 0)\n bounds.right = rect.right - (scroll.x || 0)\n bounds.width = rect.width\n bounds.height = rect.height\n // move coordinate system so 0,0 is at center of screen\n bounds.x = bounds.left + rect.width * 0.5 - size.width * 0.5\n bounds.y = bounds.top + rect.height * 0.5 - size.height * 0.5\n bounds.positiveYUpBottom = size.height - bounds.bottom // inverse Y\n}\n\nfunction updatePosition(position: vec3, bounds: Bounds, scaleMultiplier: number) {\n position.x = bounds.x * scaleMultiplier\n position.y = -1 * bounds.y * scaleMultiplier\n}\n\n/**\n * Returns the current Scene position of the DOM element\n * based on initial getBoundingClientRect and scroll delta from start\n */\nfunction useTracker(track: MutableRefObject<HTMLElement>, options?: TrackerOptions): Tracker {\n const size = useWindowSize()\n const { scroll, onScroll } = useScrollbar()\n const scaleMultiplier = useCanvasStore((state) => state.scaleMultiplier)\n const pageReflow = useCanvasStore((state) => state.pageReflow)\n const debug = useCanvasStore((state) => state.debug)\n\n // extend defaults with optional options\n const { rootMargin, threshold, autoUpdate, wrapper } = useMemo(() => {\n const target = { rootMargin: '0%', threshold: 0, autoUpdate: true } as TrackerOptions\n const opts = options || {}\n Object.keys(opts).map((key: string, index) => {\n if (opts[key] !== undefined) target[key] = opts[key]\n })\n return target\n }, [options])\n\n // check if element is in viewport\n const { ref, inView: inViewport } = useInView({ rootMargin, threshold })\n\n // bind useInView ref to current tracking element\n useLayoutEffect(() => {\n ref(track.current)\n }, [track, track?.current])\n\n // Using state so it's reactive\n const [scale, setScale] = useState<vec3>(vecn.vec3(0, 0, 0))\n\n // Using ref because\n const scrollState: ScrollState = useRef({\n inViewport: false,\n progress: -1,\n visibility: -1,\n viewport: -1,\n }).current\n\n // DOM rect (initial position in pixels offset by scroll value on page load)\n // Using ref so we can calculate bounds & position without a re-render\n const rect = useRef({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n width: 0,\n height: 0,\n }).current\n\n // expose internal ref as a reactive state as well\n const [reactiveRect, setReactiveRect] = useState<Rect>(rect)\n\n // bounding rect in pixels - updated by scroll\n const bounds = useRef({\n top: 0,\n bottom: 0,\n left: 0,\n right: 0,\n width: 0,\n height: 0,\n x: 0,\n y: 0,\n positiveYUpBottom: 0,\n }).current\n\n // position in viewport units - updated by scroll\n const position = useRef(vecn.vec3(0, 0, 0)).current\n\n // Calculate bounding Rect as soon as it's available\n useLayoutEffect(() => {\n const _rect = track.current?.getBoundingClientRect()\n if (!_rect) return\n const initialY = wrapper ? (wrapper as HTMLElement).scrollTop : window.scrollY\n const initialX = wrapper ? (wrapper as HTMLElement).scrollLeft : window.scrollX\n rect.top = _rect.top + initialY\n rect.bottom = _rect.bottom + initialY\n rect.left = _rect.left + initialX\n rect.right = _rect.right + initialX\n rect.width = _rect.width\n rect.height = _rect.height\n setReactiveRect({ ...rect })\n setScale(vecn.vec3(rect?.width * scaleMultiplier, rect?.height * scaleMultiplier, 1))\n debug &&\n console.log(\n 'useTracker.getBoundingClientRect:',\n rect,\n 'intialScroll:',\n { initialY, initialX },\n 'size:',\n size,\n 'pageReflow:',\n pageReflow\n )\n }, [track, size, pageReflow, scaleMultiplier, debug])\n\n const update = useCallback(\n ({ onlyUpdateInViewport = false, scroll: overrideScroll }: UpdateCallback = {}) => {\n if (!track.current || (onlyUpdateInViewport && !scrollState.inViewport)) {\n return\n }\n\n const _scroll = overrideScroll || scroll\n\n updateBounds(bounds, rect, _scroll, size)\n updatePosition(position, bounds, scaleMultiplier)\n\n // scrollState setup based on scroll direction\n const isHorizontal = _scroll.scrollDirection === 'horizontal'\n const sizeProp = isHorizontal ? 'width' : 'height'\n const startProp = isHorizontal ? 'left' : 'top'\n\n // calculate progress of passing through viewport (0 = just entered, 1 = just exited)\n const pxInside = size[sizeProp] - bounds[startProp]\n scrollState.progress = mapLinear(pxInside, 0, size[sizeProp] + bounds[sizeProp], 0, 1) // percent of total visible distance\n scrollState.visibility = mapLinear(pxInside, 0, bounds[sizeProp], 0, 1) // percent of item height in view\n scrollState.viewport = mapLinear(pxInside, 0, size[sizeProp], 0, 1) // percent of window height scrolled since visible\n },\n [track, size, scaleMultiplier, scroll]\n )\n\n // update scrollState in viewport\n useLayoutEffect(() => {\n scrollState.inViewport = inViewport\n // update once more in case it went out of view\n update({ onlyUpdateInViewport: false })\n debug && console.log('useTracker.inViewport:', inViewport, 'update()')\n }, [inViewport])\n\n // re-run if the callback updated\n useLayoutEffect(() => {\n update({ onlyUpdateInViewport: false })\n debug && console.log('useTracker.update on resize/reflow')\n }, [update, pageReflow])\n\n // auto-update on scroll\n useEffect(() => {\n if (autoUpdate) return onScroll((_scroll) => update({ onlyUpdateInViewport: true }))\n }, [autoUpdate, update, onScroll])\n\n return {\n // Reactive props\n scale, // reactive scene scale - includes z-axis so it can be spread onto mesh directly\n inViewport, // reactive prop for when inside viewport\n // Non-reactive props (only updates on window resize)\n // Child values are updated on scroll\n rect: reactiveRect, // Dom rect\n bounds, // scrolled bounding rect in pixels\n position, // scrolled element position in viewport units\n scrollState, // scroll progress stats - not reactive\n // Utilities\n update, // optional - manually update tracker\n }\n}\n\nexport { useTracker }\n"],"names":["useCanvasStore","create","set","debug","scaleMultiplier","globalRender","globalPriority","globalClearDepth","globalRenderQueue","clearGlobalRenderQueue","isCanvasAvailable","hasSmoothScrollbar","canvasChildren","renderToCanvas","key","mesh","props","_ref","_extends2","Object","getOwnPropertyDescriptor","instances","inactive","_extends","updateCanvas","newProps","_ref2","_extends3","_canvasChildren$key","removeFromCanvas","dispose","_ref3","_canvasChildren$key2","_objectWithoutPropertiesLoose","map","_toPropertyKey","pageReflow","requestReflow","state","scroll","y","x","limit","velocity","progress","direction","scrollDirection","undefined","__lenis","scrollTo","onScroll","useScrollbar","enabled","useLayoutEffect","window","vanillaUseLayoutEffect","useEffect","SmoothScrollbar","forwardRef","ref","children","_ref$enabled","_ref$locked","locked","_ref$scrollRestoratio","scrollRestoration","_ref$disablePointerOn","disablePointerOnScroll","_ref$horizontal","horizontal","_ref$scrollInContaine","scrollInContainer","_ref$updateGlobalStat","updateGlobalState","_ref$config","config","_ref$invalidate","invalidate","addEffect","lenis","useRef","preventPointer","globalScrollState","s","useImperativeHandle","start","_lenis$current","current","stop","_lenis$current2","on","event","cb","_lenis$current3","target","_lenis$current4","raf","time","_lenis$current5","preventPointerEvents","useCallback","prevent","document","documentElement","style","pointerEvents","history","removeEffect","_raf","html","wrapper","body","content","firstElementChild","classList","toggle","assign","smoothTouch","Lenis","orientation","smoothWheel","syncTouch","_lenis$current6","requestAnimationFrame","_lenis$current7","cancelAnimationFrame","_lenis$current8","destroy","_lenis","_onScroll","Math","abs","setState","apply","slice","call","arguments","emit","off","getState","scrollY","scrollX","invalidateOnWheelEvent","onPointerInteraction","addEventListener","removeEventListener","remove","_lenis$current9","_lenis$current10","isBrowser","mapLinear","a1","a2","b1","b2","track","options","size","_temp","_ref$debounce","debounce","_useState","useState","width","innerWidth","Infinity","height","innerHeight","windowSize","setWindowSize","canvasEl","getElementById","handleResize","clientWidth","clientHeight","observer","debouncedResize","pkg","ResizeObserver","Polyfill","observe","_observer","disconnect","useWindowSize","_useScrollbar","_useMemo","useMemo","rootMargin","threshold","autoUpdate","opts","keys","index","_useInView","useInView","inViewport","inView","vecn","vec3","scale","setScale","scrollState","visibility","viewport","rect","top","bottom","left","right","_useState2","reactiveRect","setReactiveRect","bounds","positiveYUpBottom","position","_track$current","_rect","getBoundingClientRect","initialY","scrollTop","initialX","scrollLeft","console","log","update","_ref$onlyUpdateInView","onlyUpdateInViewport","_scroll","updateBounds","updatePosition","isHorizontal","sizeProp","pxInside"],"mappings":"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"}