File size: 1,416 Bytes
7312c42 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | import { useEffect, useState, type RefObject } from 'react'
export const DEFAULT_LAZY_INTERSECTION_DELAY_MS = 180
const DEFAULT_INTERSECTION_OBSERVER_INIT: IntersectionObserverInit = { threshold: 0 }
interface UseDelayedIntersectionOptions {
delayMs?: number
observerInit?: IntersectionObserverInit
}
export function useDelayedIntersection<T extends Element>(
ref: RefObject<T | null>,
{
delayMs = DEFAULT_LAZY_INTERSECTION_DELAY_MS,
observerInit = DEFAULT_INTERSECTION_OBSERVER_INIT,
}: UseDelayedIntersectionOptions = {},
): boolean {
const [intersected, setIntersected] = useState(false)
useEffect(() => {
if (intersected) return
const element = ref.current
if (!element) return
if (typeof IntersectionObserver === 'undefined') {
setIntersected(true)
return
}
let timer: ReturnType<typeof setTimeout> | undefined
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
timer ??= setTimeout(() => {
setIntersected(true)
observer.disconnect()
}, delayMs)
return
}
if (timer) {
clearTimeout(timer)
timer = undefined
}
}, observerInit)
observer.observe(element)
return () => {
if (timer) clearTimeout(timer)
observer.disconnect()
}
}, [delayMs, intersected, observerInit, ref])
return intersected
}
|