Files
Compass/web/hooks/use-is-visible.ts
Martin Braquet ba9b3cfb06 Add pretty formatting (#29)
* Test

* Add pretty formatting

* Fix Tests

* Fix Tests

* Fix Tests

* Fix

* Add pretty formatting fix

* Fix

* Test

* Fix tests

* Clean typeckech

* Add prettier check

* Fix api tsconfig

* Fix api tsconfig

* Fix tsconfig

* Fix

* Fix

* Prettier
2026-02-20 17:32:27 +01:00

48 lines
1.3 KiB
TypeScript

import {useEffect, useRef} from 'react'
import {useEvent} from 'web/hooks/use-event'
export function useIsVisible(
onSeenStart: () => void,
triggerOnce = false,
isLoaded = true,
onSeenEnd?: () => void,
) {
const ref = useRef<HTMLDivElement | null>(null)
const seenOnce = useRef(false)
const eventOnVisible = useEvent(onSeenStart)
const eventOnInvisible = useEvent(onSeenEnd)
useEffect(() => {
const element = ref.current
if (!element || !isLoaded) return
const innerHeight = window.innerHeight * 0.9
const elementHeight = element.getBoundingClientRect().height
const threshold = elementHeight >= innerHeight ? 0.01 : 0.9
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
eventOnVisible()
seenOnce.current = true
if (triggerOnce && !onSeenEnd) observer.unobserve(element)
} else if (seenOnce.current) {
if (onSeenEnd) eventOnInvisible()
if (triggerOnce) observer.unobserve(element)
}
})
},
{threshold},
)
if (!triggerOnce || (triggerOnce && !seenOnce.current)) observer.observe(element)
return () => {
observer.unobserve(element)
}
}, [ref, triggerOnce, eventOnVisible, eventOnInvisible, isLoaded])
return {ref}
}