mirror of
https://github.com/EnixCoda/Gitako.git
synced 2026-03-11 08:54:44 +00:00
55 lines
1.4 KiB
TypeScript
55 lines
1.4 KiB
TypeScript
import * as React from 'react'
|
|
import * as features from 'utils/features'
|
|
|
|
type Size = {
|
|
width: number
|
|
height: number
|
|
}
|
|
|
|
type Props = {
|
|
type?: string | React.ComponentType
|
|
children(size: Partial<Size>): React.ReactNode
|
|
} & React.HTMLAttributes<HTMLElement>
|
|
|
|
export function SizeObserver({ type = 'div', children, ...rest }: Props) {
|
|
const ref = React.useRef<any>()
|
|
|
|
const [size, setSize] = React.useState<Partial<Size>>({
|
|
width: undefined,
|
|
height: undefined,
|
|
})
|
|
|
|
const safeSetSize = React.useCallback(function safeSetSize(rect: DOMRectReadOnly) {
|
|
// requestAnimationFrame fixes "ResizeObserver loop limit exceeded" error
|
|
requestAnimationFrame(() =>
|
|
setSize({
|
|
width: rect.width,
|
|
height: rect.height,
|
|
}),
|
|
)
|
|
}, [])
|
|
|
|
React.useEffect(() => {
|
|
if (ref.current) {
|
|
if (features.resize) {
|
|
const observer = new window.ResizeObserver(entries => {
|
|
const entry = entries[0]
|
|
if (!entry) return
|
|
const rect = entry.contentRect
|
|
safeSetSize(rect)
|
|
})
|
|
observer.observe(ref.current)
|
|
return () => observer.disconnect()
|
|
} else {
|
|
if ('getBoundingClientRect' in ref.current) {
|
|
const rect = ref.current.getBoundingClientRect()
|
|
setSize(rect)
|
|
}
|
|
}
|
|
}
|
|
}, [])
|
|
|
|
const props: any = { ...rest, ref } // :)
|
|
|
|
return React.createElement(type, props, children(size))
|
|
}
|