UNPKG

framer-motion

Version:

A simple and powerful JavaScript animation library

1 lines 3.26 kB
{"version":3,"file":"use-scroll.mjs","sources":["../../../src/value/use-scroll.ts"],"sourcesContent":["\"use client\"\n\nimport { motionValue } from \"motion-dom\"\nimport { invariant } from \"motion-utils\"\nimport { RefObject, useCallback, useEffect, useRef } from \"react\"\nimport { scroll } from \"../render/dom/scroll\"\nimport { ScrollInfoOptions } from \"../render/dom/scroll/types\"\nimport { useConstant } from \"../utils/use-constant\"\nimport { useIsomorphicLayoutEffect } from \"../utils/use-isomorphic-effect\"\n\nexport interface UseScrollOptions\n extends Omit<ScrollInfoOptions, \"container\" | \"target\"> {\n container?: RefObject<HTMLElement | null>\n target?: RefObject<HTMLElement | null>\n}\n\nconst createScrollMotionValues = () => ({\n scrollX: motionValue(0),\n scrollY: motionValue(0),\n scrollXProgress: motionValue(0),\n scrollYProgress: motionValue(0),\n})\n\nconst isRefPending = (ref?: RefObject<HTMLElement | null>) => {\n if (!ref) return false\n return !ref.current\n}\n\nexport function useScroll({\n container,\n target,\n ...options\n}: UseScrollOptions = {}) {\n const values = useConstant(createScrollMotionValues)\n const scrollAnimation = useRef<VoidFunction | null>(null)\n const needsStart = useRef(false)\n\n const start = useCallback(() => {\n scrollAnimation.current = scroll(\n (\n _progress: number,\n {\n x,\n y,\n }: {\n x: { current: number; progress: number }\n y: { current: number; progress: number }\n }\n ) => {\n values.scrollX.set(x.current)\n values.scrollXProgress.set(x.progress)\n values.scrollY.set(y.current)\n values.scrollYProgress.set(y.progress)\n },\n {\n ...options,\n container: container?.current || undefined,\n target: target?.current || undefined,\n }\n )\n\n return () => {\n scrollAnimation.current?.()\n }\n }, [container, target, JSON.stringify(options.offset)])\n\n useIsomorphicLayoutEffect(() => {\n needsStart.current = false\n\n if (isRefPending(container) || isRefPending(target)) {\n needsStart.current = true\n return\n } else {\n return start()\n }\n }, [start])\n\n useEffect(() => {\n if (needsStart.current) {\n invariant(\n !isRefPending(container),\n \"Container ref is defined but not hydrated\",\n \"use-scroll-ref\"\n )\n invariant(\n !isRefPending(target),\n \"Target ref is defined but not hydrated\",\n \"use-scroll-ref\"\n )\n return start()\n } else {\n return\n }\n }, [start])\n\n return values\n}\n"],"names":[],"mappings":";;;;;;;;AAgBA;AACI;AACA;AACA;AACA;AACH;AAED;AACI;AAAU;AACV;AACJ;AAEM;AAKF;AACA;AACA;AAEA;AACI;;;;;AAeI;AAEI;AACA;AACA;AACH;AAGL;AACI;AACJ;AACJ;;AAGI;;AAGI;;;;;;AAKR;;AAGI;;;;;;;;AAeJ;AAEA;AACJ;;"}