feat: size observer

This commit is contained in:
EnixCoda 2019-08-11 12:22:16 +08:00
parent 781c706137
commit 60c16da490
No known key found for this signature in database
GPG key ID: 0C1A07377913A1DD
2 changed files with 113 additions and 0 deletions

View file

@ -0,0 +1,45 @@
import * as React from 'react'
type Size = {
width: number
height: number
}
type Props = {
type?: string | React.ComponentType
children(size: Partial<Size>): React.ReactNode
} & React.HTMLAttributes<HTMLElement>
export default function SizeObserver({
type = 'div',
children,
...rest
}: React.PropsWithChildren<Props>) {
const ref = React.useRef<any>()
const [size, setSize] = React.useState<Partial<Size>>({
width: undefined,
height: undefined,
})
React.useEffect(() => {
const observer = new window.ResizeObserver(entries => {
for (let entry of entries) {
const rect = entry.contentRect
console.log('Element:', entry.target)
console.log(`Element size: ${rect.width}px x ${rect.height}px`)
console.log(`Element padding: ${rect.top}px ; ${rect.left}px`)
setSize({
width: rect.width,
height: rect.height,
})
}
})
if (ref.current) observer.observe(ref.current)
}, [])
const props: any = { ...rest, ref } // :)
return React.createElement(type, props, children(size))
}

68
src/resize-observer.d.ts vendored Normal file
View file

@ -0,0 +1,68 @@
interface Window {
ResizeObserver: ResizeObserver
}
/**
* The ResizeObserver interface is used to observe changes to Element's content
* rect.
*
* It is modeled after MutationObserver and IntersectionObserver.
*/
interface ResizeObserver {
new (callback: ResizeObserverCallback): ResizeObserver
/**
* Adds target to the list of observed elements.
*/
observe: (target: Element) => void
/**
* Removes target from the list of observed elements.
*/
unobserve: (target: Element) => void
/**
* Clears both the observationTargets and activeTargets lists.
*/
disconnect: () => void
}
/**
* This callback delivers ResizeObserver's notifications. It is invoked by a
* broadcast active observations algorithm.
*/
interface ResizeObserverCallback {
(entries: ResizeObserverEntry[], observer: ResizeObserver): void
}
interface ResizeObserverEntry {
/**
* @param target The Element whose size has changed.
*/
new (target: Element): void
/**
* The Element whose size has changed.
*/
readonly target: Element
/**
* Element's content rect when ResizeObserverCallback is invoked.
*/
readonly contentRect: DOMRectReadOnly
}
interface DOMRectReadOnly {
// static fromRect(other: DOMRectInit | undefined): DOMRectReadOnly;
readonly x: number
readonly y: number
readonly width: number
readonly height: number
readonly top: number
readonly right: number
readonly bottom: number
readonly left: number
toJSON: () => any
}