@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
1 lines • 10.7 kB
Source Map (JSON)
{"version":3,"file":"use-infinite-scroll.cjs","names":["useEnvironment","useCallbackRef","options: IntersectionObserverInit","root","el"],"sources":["../../../../src/components/infinite-scroll-area/use-infinite-scroll.ts"],"sourcesContent":["\"use client\"\n\nimport type { RefObject } from \"react\"\nimport type { Orientation } from \"../../core\"\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { useEnvironment } from \"../../core\"\nimport { assignRef, useCallbackRef } from \"../../utils\"\n\nconst isScrollable = (el: HTMLElement, vertical: boolean) => {\n const style = getComputedStyle(el)\n\n if ([\"auto\", \"overlay\", \"scroll\"].includes(style.overflow)) return true\n\n if (vertical) {\n return [\"auto\", \"overlay\", \"scroll\"].includes(style.overflowY)\n } else {\n return [\"auto\", \"overlay\", \"scroll\"].includes(style.overflowX)\n }\n}\n\nexport interface UseInfiniteScrollProps\n extends Omit<IntersectionObserverInit, \"root\"> {\n /**\n * Determines whether scrolling is instant or animates smoothly.\n */\n behavior?: ScrollBehavior\n /**\n * If `true`, the infinite scroll is disabled.\n *\n * @default false\n */\n disabled?: boolean\n /**\n * Ref to a reset index function.\n */\n indexRef?: RefObject<(index: number) => void>\n /**\n * If `true`, invoke `onLoad` function for the first time.\n *\n * @default false\n */\n initialLoad?: boolean\n /**\n * The orientation of the infinite scroll.\n *\n * @default 'vertical'\n */\n orientation?: Orientation\n /**\n * Ref to a reset function.\n */\n resetRef?: RefObject<(index?: number, runScroll?: boolean) => void>\n /**\n * If `true`, reverse direction.\n *\n * @default false\n */\n reverse?: boolean\n /**\n * Margin around the root. Can have values similar to the CSS margin property,\n * e.g. \"10px 20px 30px 40px\" (top, right, bottom, left).\n */\n rootMargin?: string\n /**\n * The element that is used as the viewport for checking visibility of the target.\n * Defaults to the browser viewport if not specified or if `null`.\n */\n rootRef?: RefObject<HTMLElement | null>\n /**\n * If set the `onLoad` function will start from the given index.\n * If `initialLoad` is `true`, index starts from `0`.\n *\n * @default 1\n */\n startIndex?: number\n /**\n * Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.\n */\n threshold?: number | number[]\n /**\n * The callback invoked when trigger is intersect.\n */\n onLoad?: ({\n entry,\n finish,\n index,\n }: {\n finish: () => void\n index: number\n entry?: IntersectionObserverEntry\n }) => Promise<void> | void\n}\n\n/**\n * `useInfiniteScroll` is a custom hook for providing infinite scroll functionality.\n *\n * @see https://yamada-ui.com/docs/hooks/use-infinite-scroll\n */\nexport const useInfiniteScroll = <Y extends HTMLElement = HTMLDivElement>({\n behavior,\n disabled = false,\n indexRef: indexRefProp,\n initialLoad = false,\n orientation = \"vertical\",\n resetRef,\n reverse = false,\n rootMargin,\n rootRef,\n startIndex = initialLoad ? 0 : 1,\n threshold,\n onLoad: onLoadProp,\n}: UseInfiniteScrollProps = {}) => {\n const ref = useRef<Y>(null)\n const { getDocument, getWindow } = useEnvironment()\n const indexRef = useRef<number>(startIndex)\n const processingRef = useRef<boolean>(false)\n const observerRef = useRef<IntersectionObserver | undefined>(undefined)\n const [finish, setFinish] = useState<boolean>(false)\n const onLoad = useCallbackRef(onLoadProp)\n const vertical = orientation === \"vertical\"\n const direction = vertical ? \"top\" : \"left\"\n const options: IntersectionObserverInit = useMemo(() => {\n const root = rootRef?.current\n\n return { root, rootMargin, threshold }\n }, [rootMargin, rootRef, threshold])\n\n const onReset = useCallback(\n (index = 1, runScroll = true) => {\n indexRef.current = index\n\n setFinish(false)\n\n if (runScroll) {\n const root = rootRef?.current\n const body = getDocument()?.body\n const el = root && isScrollable(root, vertical) ? root : body\n\n if (el) {\n const target = el === body ? getWindow() : el\n const position = reverse\n ? vertical\n ? el.scrollHeight\n : el.scrollWidth\n : 0\n\n target?.scrollTo({ behavior, [direction]: position })\n }\n }\n\n if (disabled) return\n\n setTimeout(() => {\n const observer = observerRef.current\n const el = ref.current\n\n if (el) observer?.observe(el)\n })\n },\n [\n disabled,\n rootRef,\n getDocument,\n vertical,\n getWindow,\n reverse,\n behavior,\n direction,\n ],\n )\n\n const onFinish = useCallback(() => {\n const observer = observerRef.current\n const el = ref.current\n\n if (el) observer?.unobserve(el)\n\n setFinish(true)\n }, [])\n\n const createObserver = useCallback(() => {\n const observer = new IntersectionObserver(async ([entry]) => {\n const root = rootRef?.current\n const body = getDocument()?.body\n const el = root && isScrollable(root, vertical) ? root : body\n\n if (!entry?.isIntersecting || processingRef.current || !el) return\n\n const props = { entry, finish: onFinish, index: indexRef.current }\n\n processingRef.current = true\n\n if (root) root.ariaBusy = \"true\"\n\n let prevScrollPosition = 0\n\n if (reverse)\n prevScrollPosition = vertical ? el.scrollHeight : el.scrollWidth\n\n await onLoad(props)\n\n if (reverse)\n setTimeout(() => {\n const target = el === body ? getWindow() : el\n const position =\n (vertical ? el.scrollHeight : el.scrollWidth) - prevScrollPosition\n\n target?.scrollTo({ [direction]: position })\n })\n\n indexRef.current += 1\n processingRef.current = false\n\n if (root) root.ariaBusy = \"false\"\n }, options)\n\n return observer\n }, [\n options,\n rootRef,\n getDocument,\n vertical,\n onFinish,\n reverse,\n onLoad,\n getWindow,\n direction,\n ])\n\n useEffect(() => {\n const setupObserver = async () => {\n const el = ref.current\n const index = indexRef.current\n const root = rootRef?.current\n\n if (initialLoad) {\n processingRef.current = true\n\n if (root) root.ariaBusy = \"true\"\n\n await onLoad({ finish: onFinish, index })\n\n indexRef.current += 1\n processingRef.current = false\n\n if (root) root.ariaBusy = \"false\"\n }\n\n if (disabled) return\n\n observerRef.current = createObserver()\n\n const observer = observerRef.current\n\n if (reverse) {\n const root = rootRef?.current\n const body = getDocument()?.body\n const el = root && isScrollable(root, vertical) ? root : body\n\n if (el) {\n const target = el === body ? getWindow() : el\n const position = vertical ? el.scrollHeight : el.scrollWidth\n\n target?.scrollTo({ [direction]: position })\n }\n }\n\n setTimeout(() => {\n if (el) observer.observe(el)\n })\n\n return () => {\n if (el) observer.unobserve(el)\n }\n }\n\n setupObserver()\n }, [\n createObserver,\n initialLoad,\n disabled,\n reverse,\n vertical,\n onFinish,\n onLoad,\n rootRef,\n getDocument,\n getWindow,\n direction,\n ])\n\n assignRef(resetRef, onReset)\n assignRef(indexRefProp, (index) => (indexRef.current = index))\n\n return { ref, finish }\n}\n"],"mappings":"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"}