import type { Ref } from 'react'; import React, { useEffect, useState } from 'react'; import { LoadingSpinner } from '@growi/ui/dist/components'; import type { SWRInfiniteResponse } from 'swr/infinite'; type Props = { swrInifiniteResponse: SWRInfiniteResponse children: React.ReactNode, loadingIndicator?: React.ReactNode endingIndicator?: React.ReactNode isReachingEnd?: boolean offset?: number } const useIntersection = (): [boolean, Ref] => { const [intersecting, setIntersecting] = useState(false); const [element, setElement] = useState(); useEffect(() => { if (element != null) { const observer = new IntersectionObserver((entries) => { setIntersecting(entries[0]?.isIntersecting); }); observer.observe(element); return () => observer.unobserve(element); } return; }, [element]); return [intersecting, el => el && setElement(el)]; }; const LoadingIndicator = (): React.ReactElement => { return (
); }; const InfiniteScroll = (props: Props): React.ReactElement> => { const { swrInifiniteResponse: { setSize, isValidating, }, children, loadingIndicator, endingIndicator, isReachingEnd, offset = 0, } = props; const [intersecting, ref] = useIntersection(); useEffect(() => { if (intersecting && !isValidating && !isReachingEnd) { setSize(size => size + 1); } }, [setSize, intersecting, isValidating, isReachingEnd]); return ( <> {children}
{isReachingEnd ? endingIndicator : loadingIndicator || }
); }; export default InfiniteScroll;