forked from geist-org/geist-ui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
use-real-shape.ts
50 lines (40 loc) · 1.25 KB
/
use-real-shape.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
import { MutableRefObject, useEffect, useState } from 'react'
export type ShapeType = {
width: number
height: number
}
export const getRealShape = (el: HTMLElement | null): ShapeType => {
const defaultShape: ShapeType = { width: 0, height: 0 }
if (!el || typeof window === 'undefined') return defaultShape
const rect = el.getBoundingClientRect()
const { width, height } = window.getComputedStyle(el)
const getCSSStyleVal = (str: string, parentNum: number) => {
if (!str) return 0
const strVal = str.includes('px')
? +str.split('px')[0]
: str.includes('%')
? +str.split('%')[0] * parentNum * 0.01
: str
return Number.isNaN(+strVal) ? 0 : +strVal
}
return {
width: getCSSStyleVal(`${width}`, rect.width),
height: getCSSStyleVal(`${height}`, rect.height),
}
}
export type ShapeResult = [ShapeType, () => void]
const useRealShape = <T extends HTMLElement>(
ref: MutableRefObject<T | null>,
): ShapeResult => {
const [state, setState] = useState<ShapeType>({
width: 0,
height: 0,
})
const update = () => {
const { width, height } = getRealShape(ref.current)
setState({ width, height })
}
useEffect(() => update(), [ref.current])
return [state, update]
}
export default useRealShape