@carbon/react
Version:
React components for the Carbon Design System
65 lines (63 loc) • 2.43 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import useIsomorphicEffect from "./useIsomorphicEffect.js";
import { useEffect, useRef, useState } from "react";
//#region src/internal/useResizeObserver.ts
/**
* Copyright IBM Corp. 2025, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const useResizeObserver = ({ ref, onResize }) => {
const [width, setWidth] = useState(-1);
const [height, setHeight] = useState(-1);
const entriesToHandle = useRef(null);
const cb = useRef(onResize);
useEffect(() => {
cb.current = onResize;
}, [onResize]);
useEffect(() => {
const getInitialSize = () => {
if (ref.current) {
const refComputedStyle = window.getComputedStyle(ref.current);
const initialWidth = (ref.current?.offsetWidth ?? 0) - (typeof refComputedStyle?.paddingLeft === "string" && refComputedStyle?.paddingLeft.length ? parseFloat(refComputedStyle?.paddingLeft) : 0) - (typeof refComputedStyle?.paddingRight === "string" && refComputedStyle?.paddingRight.length ? parseFloat(refComputedStyle?.paddingRight) : 0);
const initialHeight = (ref.current?.offsetHeight ?? 0) - (typeof refComputedStyle?.paddingTop === "string" && refComputedStyle?.paddingTop.length ? parseFloat(refComputedStyle?.paddingTop) : 0) - (typeof refComputedStyle?.paddingBottom === "string" && refComputedStyle?.paddingBottom.length ? parseFloat(refComputedStyle?.paddingBottom) : 0);
setWidth(initialWidth);
setHeight(initialHeight);
}
};
if (!ref?.current || width >= 0 && height >= 0) return;
getInitialSize();
}, [width, height]);
useIsomorphicEffect(() => {
if (!ref?.current) return;
const doCallbacks = () => {
if (!ref?.current || !Array.isArray(entriesToHandle?.current)) return;
const entry = entriesToHandle.current[0];
setWidth(entry.contentRect.width);
setHeight(entry.contentRect.height);
cb.current?.(entry.contentRect);
};
const observer = new ResizeObserver((entries) => {
entriesToHandle.current = entries;
window.requestAnimationFrame(() => {
doCallbacks();
});
});
observer.observe(ref.current);
return () => {
observer.disconnect();
};
}, []);
return {
width,
height
};
};
//#endregion
export { useResizeObserver };