-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.ts
62 lines (54 loc) · 1.74 KB
/
index.ts
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
58
59
60
61
62
import type { MaybeComputedRef } from '@vueuse/shared'
import { tryOnScopeDispose } from '@vueuse/shared'
import { ref, watch } from 'vue-demi'
import type { MaybeComputedElementRef } from '../unrefElement'
import { unrefElement } from '../unrefElement'
import { useEventListener } from '../useEventListener'
import type { ConfigurableWindow } from '../_configurable'
import { defaultWindow } from '../_configurable'
export interface UseElementVisibilityOptions extends ConfigurableWindow {
scrollTarget?: MaybeComputedRef<HTMLElement | undefined | null>
}
/**
* Tracks the visibility of an element within the viewport.
*
* @see https://vueuse.org/useElementVisibility
* @param element
* @param options
*/
export function useElementVisibility(
element: MaybeComputedElementRef,
{ window = defaultWindow, scrollTarget }: UseElementVisibilityOptions = {},
) {
const elementIsVisible = ref(false)
const testBounding = () => {
if (!window)
return
const document = window.document
const el = unrefElement(element)
if (!el) {
elementIsVisible.value = false
}
else {
const rect = (el as HTMLElement).getBoundingClientRect()
elementIsVisible.value = (
rect.top <= (window.innerHeight || document.documentElement.clientHeight)
&& rect.left <= (window.innerWidth || document.documentElement.clientWidth)
&& rect.bottom >= 0
&& rect.right >= 0
)
}
}
const stop = watch(
() => unrefElement(element),
() => testBounding(),
{ immediate: true, flush: 'post' },
)
if (window) {
useEventListener(scrollTarget || window, 'scroll', testBounding, {
capture: false, passive: true,
})
}
tryOnScopeDispose(() => stop())
return elementIsVisible
}