Private
Public Access
1
0
Files
power-apps-codeapps-blog-part2/node_modules/@fluentui/react-message-bar/lib/components/MessageBar/useMessageBarReflow.js

85 lines
4.1 KiB
JavaScript

'use client';
import * as React from 'react';
import { useFluent_unstable as useFluent } from '@fluentui/react-shared-contexts';
import { isHTMLElement } from '@fluentui/react-utilities';
export function useMessageBarReflow(enabled = false) {
const { targetDocument } = useFluent();
const forceUpdate = React.useReducer(()=>({}), {})[1];
const reflowingRef = React.useRef(false);
// TODO: exclude types from this lint rule: https://github.com/microsoft/fluentui/issues/31286
const resizeObserverRef = React.useRef(null);
const prevInlineSizeRef = React.useRef(-1);
const handleResize = React.useCallback((entries)=>{
var _entry_borderBoxSize_, _entry_borderBoxSize;
// Resize observer is only owned by this component - one resize observer entry expected
// No need to support multiple fragments - one border box entry expected
if (process.env.NODE_ENV !== 'production' && entries.length > 1) {
// eslint-disable-next-line no-console
console.error([
'useMessageBarReflow: Resize observer should only have one entry. ',
'If multiple entries are observed, the first entry will be used.',
'This is a bug, please report it to the Fluent UI team.'
].join(' '));
}
const entry = entries[0];
var _entry_borderBoxSize__inlineSize;
// `borderBoxSize` is not supported before Chrome 84, Firefox 92, nor Safari 15.4
const inlineSize = (_entry_borderBoxSize__inlineSize = entry === null || entry === void 0 ? void 0 : (_entry_borderBoxSize = entry.borderBoxSize) === null || _entry_borderBoxSize === void 0 ? void 0 : (_entry_borderBoxSize_ = _entry_borderBoxSize[0]) === null || _entry_borderBoxSize_ === void 0 ? void 0 : _entry_borderBoxSize_.inlineSize) !== null && _entry_borderBoxSize__inlineSize !== void 0 ? _entry_borderBoxSize__inlineSize : entry === null || entry === void 0 ? void 0 : entry.target.getBoundingClientRect().width;
if (inlineSize === undefined || !entry) {
return;
}
const { target } = entry;
if (!isHTMLElement(target)) {
return;
}
let nextReflowing;
// No easy way to really determine when the single line layout will fit
// Just keep try to set single line layout as long as the size is growing
// Will cause flickering when size is being adjusted gradually (i.e. drag) - but this should not be a common case
if (reflowingRef.current) {
if (prevInlineSizeRef.current < inlineSize) {
nextReflowing = false;
}
} else {
const scrollWidth = target.scrollWidth;
if (inlineSize < scrollWidth) {
nextReflowing = true;
}
}
prevInlineSizeRef.current = inlineSize;
if (typeof nextReflowing !== 'undefined' && reflowingRef.current !== nextReflowing) {
reflowingRef.current = nextReflowing;
forceUpdate();
}
}, [
forceUpdate
]);
const ref = React.useCallback((el)=>{
var _resizeObserverRef_current;
if (!enabled || !el || !(targetDocument === null || targetDocument === void 0 ? void 0 : targetDocument.defaultView)) {
return;
}
(_resizeObserverRef_current = resizeObserverRef.current) === null || _resizeObserverRef_current === void 0 ? void 0 : _resizeObserverRef_current.disconnect();
const win = targetDocument.defaultView;
const resizeObserver = new win.ResizeObserver(handleResize);
resizeObserverRef.current = resizeObserver;
resizeObserver.observe(el, {
box: 'border-box'
});
}, [
targetDocument,
handleResize,
enabled
]);
React.useEffect(()=>{
return ()=>{
var _resizeObserverRef_current;
(_resizeObserverRef_current = resizeObserverRef.current) === null || _resizeObserverRef_current === void 0 ? void 0 : _resizeObserverRef_current.disconnect();
};
}, []);
return {
ref,
reflowing: reflowingRef.current
};
}