diff --git a/src/components/SizeObserver.tsx b/src/components/SizeObserver.tsx new file mode 100644 index 0000000..5a207d3 --- /dev/null +++ b/src/components/SizeObserver.tsx @@ -0,0 +1,45 @@ +import * as React from 'react' + +type Size = { + width: number + height: number +} + +type Props = { + type?: string | React.ComponentType + children(size: Partial): React.ReactNode +} & React.HTMLAttributes + +export default function SizeObserver({ + type = 'div', + children, + ...rest +}: React.PropsWithChildren) { + const ref = React.useRef() + + const [size, setSize] = React.useState>({ + 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)) +} diff --git a/src/resize-observer.d.ts b/src/resize-observer.d.ts new file mode 100644 index 0000000..45f7831 --- /dev/null +++ b/src/resize-observer.d.ts @@ -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 +}