/
index.ts
118 lines (104 loc) · 2.32 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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { ref, watch } from 'vue-demi'
import { tryOnMounted } from '@vueuse/shared'
import { useEventListener } from '../useEventListener'
import type { MaybeComputedElementRef } from '../unrefElement'
import { unrefElement } from '../unrefElement'
import { useResizeObserver } from '../useResizeObserver'
export interface UseElementBoundingOptions {
/**
* Reset values to 0 on component unmounted
*
* @default true
*/
reset?: boolean
/**
* Listen to window resize event
*
* @default true
*/
windowResize?: boolean
/**
* Listen to window scroll event
*
* @default true
*/
windowScroll?: boolean
/**
* Immediately call update on component mounted
*
* @default true
*/
immediate?: boolean
}
/**
* Reactive bounding box of an HTML element.
*
* @see https://vueuse.org/useElementBounding
* @param target
*/
export function useElementBounding(
target: MaybeComputedElementRef,
options: UseElementBoundingOptions = {},
) {
const {
reset = true,
windowResize = true,
windowScroll = true,
immediate = true,
} = options
const height = ref(0)
const bottom = ref(0)
const left = ref(0)
const right = ref(0)
const top = ref(0)
const width = ref(0)
const x = ref(0)
const y = ref(0)
function update() {
const el = unrefElement(target)
if (!el) {
if (reset) {
height.value = 0
bottom.value = 0
left.value = 0
right.value = 0
top.value = 0
width.value = 0
x.value = 0
y.value = 0
}
return
}
const rect = el.getBoundingClientRect()
height.value = rect.height
bottom.value = rect.bottom
left.value = rect.left
right.value = rect.right
top.value = rect.top
width.value = rect.width
x.value = rect.x
y.value = rect.y
}
useResizeObserver(target, update)
watch(() => unrefElement(target), ele => !ele && update())
if (windowScroll)
useEventListener('scroll', update, { capture: true, passive: true })
if (windowResize)
useEventListener('resize', update, { passive: true })
tryOnMounted(() => {
if (immediate)
update()
})
return {
height,
bottom,
left,
right,
top,
width,
x,
y,
update,
}
}
export type UseElementBoundingReturn = ReturnType<typeof useElementBounding>