UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

95 lines (94 loc) 3.16 kB
import * as React from 'react'; import { useMemo, useRef, useEffect, useLayoutEffect, useCallback } from 'react'; import { getResizeObserverObject } from './getResizeObserverObject'; export const setupResizeObserver = (node, callback) => { const RO = getResizeObserverObject(); if (!RO) { return () => { }; } const observer = new RO((entries) => { const entry = entries[0]; let { width, height } = entry.contentRect; if (entry.borderBoxSize?.[0]) { height = entry.borderBoxSize[0].blockSize; width = entry.borderBoxSize[0].inlineSize; } else { // this is needed for Safari and other browsers that don't have borderBoxSize on the entry object const rect = node.getBoundingClientRect(); height = rect.height; width = rect.width; } callback({ width, height }); }); observer.observe(node); return () => { observer.disconnect(); }; }; /** * A hook that notifies you when a certain DOM element has changed it's size * * @param ref A React ref to a DOM element * @param callback The function to be called when the element is resized. */ export const useResizeObserver = (ref, callback, config = { earlyAttach: false }) => { const sizeRef = useRef({ width: 0, height: 0, }); const effectFn = (callback) => { let disconnect; if (ref.current) { disconnect = setupResizeObserver(ref.current, (size) => { size = { width: Math.round(size.width), height: Math.round(size.height), }; const prevSize = sizeRef.current; if (prevSize.width !== size.width || prevSize.height !== size.height) { sizeRef.current = size; callback(size); } }); } return () => { if (disconnect) { disconnect(); } }; }; useEffect(() => { if (!config.earlyAttach) { return effectFn(callback); } return () => { }; }, [ref.current, callback, config.earlyAttach]); useLayoutEffect(() => { if (config.earlyAttach) { return effectFn(callback); } return () => { }; }, [ref.current, callback, config.earlyAttach]); }; export const ReactResizeObserver = ({ notifyOnMount = true, earlyAttach = false, ...props }) => { const style = useMemo(() => ({ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', boxSizing: 'border-box', }), []); const firstTime = useRef(true); const ref = useRef(null); const onResize = useCallback((size) => { if (firstTime.current && !notifyOnMount) { firstTime.current = false; return; } props.onResize(size); }, [props.onResize]); useResizeObserver(ref, onResize, { earlyAttach: earlyAttach || false }); return React.createElement("div", { ref: ref, style: style }); };