framer-motion
Version:
A simple and powerful JavaScript animation library
1 lines • 2.13 kB
Source Map (JSON)
{"version":3,"file":"use-in-view.mjs","sources":["../../../src/utils/use-in-view.ts"],"sourcesContent":["\"use client\"\n\nimport { RefObject, useEffect, useState } from \"react\"\nimport { inView, InViewOptions } from \"../render/dom/viewport\"\n\nexport interface UseInViewOptions\n extends Omit<InViewOptions, \"root\" | \"amount\"> {\n root?: RefObject<Element | null>\n once?: boolean\n amount?: \"some\" | \"all\" | number\n initial?: boolean\n}\n\nexport function useInView(\n ref: RefObject<Element | null>,\n {\n root,\n margin,\n amount,\n once = false,\n initial = false,\n }: UseInViewOptions = {}\n) {\n const [isInView, setInView] = useState(initial)\n /**\n * Holds the element the observer was last set up with. Replacing the\n * object (rather than using a ref) re-runs the observer effect.\n */\n const [observed, observe] = useState<{ current?: Element | null }>({})\n\n useEffect(() => {\n const element = (observed.current = ref.current)\n if (!element || (once && isInView)) return\n\n const onEnter = () => {\n setInView(true)\n\n return once ? undefined : () => setInView(false)\n }\n\n const options: InViewOptions = {\n root: (root && root.current) || undefined,\n margin,\n amount,\n }\n\n return inView(element, onEnter, options)\n }, [root, ref, margin, once, amount, observed])\n\n /**\n * The ref object never changes, so if the element is attached, swapped\n * or removed after mount (e.g. conditional rendering) the effect above\n * won't re-run by itself. Check after every commit and re-observe,\n * resetting to false as the new element (if any) hasn't been seen yet.\n */\n useEffect(() => {\n if (ref.current !== observed.current) {\n once || setInView(false)\n observe({})\n }\n })\n\n return isInView\n}\n"],"names":[],"mappings":";;;;AAaM;;AAWF;;;AAGG;;;;AAKC;;;;AAKI;AACJ;AAEA;;;;;;AAOJ;AAEA;;;;;AAKG;;;AAGK;;;AAGR;AAEA;AACJ;;"}