export interface UseIntersectionObserverOptions { threshold?: number rootMargin?: string once?: boolean } export function useIntersectionObserver( target: Ref, options: UseIntersectionObserverOptions = {} ) { const { threshold = 0.1, rootMargin = '0px', once = true } = options const isVisible = ref(false) if (import.meta.client) { let observer: IntersectionObserver | null = null const cleanup = () => { if (observer) { observer.disconnect() observer = null } } watch( target, (el) => { cleanup() if (!el) return observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { isVisible.value = true if (once && observer) { observer.unobserve(entry.target) } } else if (!once) { isVisible.value = false } }) }, { threshold, rootMargin } ) observer.observe(el) }, { immediate: true } ) onUnmounted(cleanup) } return { isVisible: readonly(isVisible) } }