@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
JavaScript
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 });
};