72 lines
3.4 KiB
JavaScript
72 lines
3.4 KiB
JavaScript
import * as React from 'react';
|
|
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
|
|
/**
|
|
* Provides a way of reporting element width.
|
|
* Returns
|
|
* `width` - current element width (0 by default),
|
|
* `measureElementRef` - a ref function to be passed as `ref` to the element you want to measure
|
|
*/ export function useMeasureElement() {
|
|
const [width, setWidth] = React.useState(0);
|
|
const container = React.useRef(undefined);
|
|
// TODO: exclude types from this lint rule: https://github.com/microsoft/fluentui/issues/31286
|
|
// eslint-disable-next-line no-restricted-globals
|
|
const resizeObserverRef = React.useRef(null);
|
|
const { targetDocument } = useFluent();
|
|
// the handler for resize observer
|
|
const handleResize = React.useCallback(()=>{
|
|
var _container_current;
|
|
const containerWidth = (_container_current = container.current) === null || _container_current === void 0 ? void 0 : _container_current.getBoundingClientRect().width;
|
|
setWidth(containerWidth || 0);
|
|
}, []);
|
|
const measureElementRef = React.useCallback((el)=>{
|
|
if (!targetDocument) {
|
|
return;
|
|
}
|
|
// if the element is removed, stop observing it
|
|
if (!el && resizeObserverRef.current && container.current) {
|
|
resizeObserverRef.current.unobserve(container.current);
|
|
}
|
|
container.current = undefined;
|
|
if (el === null || el === void 0 ? void 0 : el.parentElement) {
|
|
var _resizeObserverRef_current;
|
|
container.current = el.parentElement;
|
|
handleResize();
|
|
(_resizeObserverRef_current = resizeObserverRef.current) === null || _resizeObserverRef_current === void 0 ? void 0 : _resizeObserverRef_current.observe(container.current);
|
|
}
|
|
}, [
|
|
targetDocument,
|
|
handleResize
|
|
]);
|
|
React.useEffect(()=>{
|
|
resizeObserverRef.current = createResizeObserverFromDocument(targetDocument, handleResize);
|
|
if (!container.current || !resizeObserverRef.current) {
|
|
return;
|
|
}
|
|
resizeObserverRef.current.observe(container.current);
|
|
return ()=>{
|
|
var _resizeObserverRef_current;
|
|
(_resizeObserverRef_current = resizeObserverRef.current) === null || _resizeObserverRef_current === void 0 ? void 0 : _resizeObserverRef_current.disconnect();
|
|
};
|
|
}, [
|
|
handleResize,
|
|
targetDocument
|
|
]);
|
|
return {
|
|
width,
|
|
measureElementRef
|
|
};
|
|
}
|
|
/**
|
|
* FIXME - TS 3.8/3.9 don't have ResizeObserver types by default, move this to a shared utility once we bump the minbar
|
|
* A utility method that creates a ResizeObserver from a target document
|
|
* @param targetDocument - document to use to create the ResizeObserver
|
|
* @param callback - https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver#callback
|
|
* @returns a ResizeObserver instance or null if the global does not exist on the document
|
|
*/ export function createResizeObserverFromDocument(targetDocument, callback) {
|
|
var _targetDocument_defaultView;
|
|
if (!(targetDocument === null || targetDocument === void 0 ? void 0 : (_targetDocument_defaultView = targetDocument.defaultView) === null || _targetDocument_defaultView === void 0 ? void 0 : _targetDocument_defaultView.ResizeObserver)) {
|
|
return null;
|
|
}
|
|
return new targetDocument.defaultView.ResizeObserver(callback);
|
|
}
|