-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
index.ts
90 lines (81 loc) · 2.5 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
import { tryOnMounted } from '@vueuse/shared'
import { computed, ref, watch } from 'vue-demi'
import type { MaybeComputedElementRef } from '../unrefElement'
import type { UseResizeObserverOptions } from '../useResizeObserver'
import { useResizeObserver } from '../useResizeObserver'
import { unrefElement } from '../unrefElement'
import { defaultWindow } from '../_configurable'
export interface ElementSize {
width: number
height: number
}
/**
* Reactive size of an HTML element.
*
* @see https://vueuse.org/useElementSize
*/
export function useElementSize(
target: MaybeComputedElementRef,
initialSize: ElementSize = { width: 0, height: 0 },
options: UseResizeObserverOptions = {},
) {
const { window = defaultWindow, box = 'content-box' } = options
const isSVG = computed(() => unrefElement(target)?.namespaceURI?.includes('svg'))
const width = ref(initialSize.width)
const height = ref(initialSize.height)
const { stop: stop1 } = useResizeObserver(
target,
([entry]) => {
const boxSize = box === 'border-box'
? entry.borderBoxSize
: box === 'content-box'
? entry.contentBoxSize
: entry.devicePixelContentBoxSize
if (window && isSVG.value) {
const $elem = unrefElement(target)
if ($elem) {
const styles = window.getComputedStyle($elem)
width.value = Number.parseFloat(styles.width)
height.value = Number.parseFloat(styles.height)
}
}
else {
if (boxSize) {
const formatBoxSize = Array.isArray(boxSize) ? boxSize : [boxSize]
width.value = formatBoxSize.reduce((acc, { inlineSize }) => acc + inlineSize, 0)
height.value = formatBoxSize.reduce((acc, { blockSize }) => acc + blockSize, 0)
}
else {
// fallback
width.value = entry.contentRect.width
height.value = entry.contentRect.height
}
}
},
options,
)
tryOnMounted(() => {
const ele = unrefElement(target)
if (ele) {
width.value = 'offsetWidth' in ele ? ele.offsetWidth : initialSize.width
height.value = 'offsetHeight' in ele ? ele.offsetHeight : initialSize.height
}
})
const stop2 = watch(
() => unrefElement(target),
(ele) => {
width.value = ele ? initialSize.width : 0
height.value = ele ? initialSize.height : 0
},
)
function stop() {
stop1()
stop2()
}
return {
width,
height,
stop,
}
}
export type UseElementSizeReturn = ReturnType<typeof useElementSize>