: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
y: win.visualViewport.offsetTop
function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
if (isFixed === void 0) {
if (!floatingOffsetParent || isFixed && floatingOffsetParent !== floating_ui_utils_dom_getWindow(element)) {
function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
if (includeScale === void 0) {
if (isFixedStrategy === void 0) {
const clientRect = element.getBoundingClientRect();
const domElement = unwrapElement(element);
let scale = floating_ui_utils_createCoords(1);
if (isElement(offsetParent)) {
scale = getScale(offsetParent);
scale = getScale(element);
const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : floating_ui_utils_createCoords(0);
let x = (clientRect.left + visualOffsets.x) / scale.x;
let y = (clientRect.top + visualOffsets.y) / scale.y;
let width = clientRect.width / scale.x;
let height = clientRect.height / scale.y;
const win = floating_ui_utils_dom_getWindow(domElement);
const offsetWin = offsetParent && isElement(offsetParent) ? floating_ui_utils_dom_getWindow(offsetParent) : offsetParent;
let currentIFrame = currentWin.frameElement;
while (currentIFrame && offsetParent && offsetWin !== currentWin) {
const iframeScale = getScale(currentIFrame);
const iframeRect = currentIFrame.getBoundingClientRect();
const css = floating_ui_utils_dom_getComputedStyle(currentIFrame);
const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
currentWin = floating_ui_utils_dom_getWindow(currentIFrame);
currentIFrame = currentWin.frameElement;
return floating_ui_utils_rectToClientRect({
const topLayerSelectors = [':popover-open', ':modal'];
function isTopLayer(floating) {
return topLayerSelectors.some(selector => {
return floating.matches(selector);
function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
const isFixed = strategy === 'fixed';
const documentElement = getDocumentElement(offsetParent);
const topLayer = elements ? isTopLayer(elements.floating) : false;
if (offsetParent === documentElement || topLayer && isFixed) {
let scale = floating_ui_utils_createCoords(1);
const offsets = floating_ui_utils_createCoords(0);
const isOffsetParentAnElement = isHTMLElement(offsetParent);
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
scroll = getNodeScroll(offsetParent);
if (isHTMLElement(offsetParent)) {
const offsetRect = getBoundingClientRect(offsetParent);
scale = getScale(offsetParent);
offsets.x = offsetRect.x + offsetParent.clientLeft;
offsets.y = offsetRect.y + offsetParent.clientTop;
width: rect.width * scale.x,
height: rect.height * scale.y,
x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,
y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y
function getClientRects(element) {
return Array.from(element.getClientRects());
function getWindowScrollBarX(element) {
// If <html> has a CSS width greater than the viewport, then this will be
return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
// Gets the entire size of the scrollable document area, even extending outside
// of the `<html>` and `<body>` rect bounds if horizontally scrollable.
function getDocumentRect(element) {
const html = getDocumentElement(element);
const scroll = getNodeScroll(element);
const body = element.ownerDocument.body;
const width = dist_floating_ui_utils_max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
const height = dist_floating_ui_utils_max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
let x = -scroll.scrollLeft + getWindowScrollBarX(element);
const y = -scroll.scrollTop;
if (floating_ui_utils_dom_getComputedStyle(body).direction === 'rtl') {
x += dist_floating_ui_utils_max(html.clientWidth, body.clientWidth) - width;
function getViewportRect(element, strategy) {
const win = floating_ui_utils_dom_getWindow(element);
const html = getDocumentElement(element);
const visualViewport = win.visualViewport;
let width = html.clientWidth;
let height = html.clientHeight;
width = visualViewport.width;
height = visualViewport.height;
const visualViewportBased = isWebKit();
if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
x = visualViewport.offsetLeft;
y = visualViewport.offsetTop;
// Returns the inner client rect, subtracting scrollbars if present.
function getInnerBoundingClientRect(element, strategy) {
const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
const top = clientRect.top + element.clientTop;
const left = clientRect.left + element.clientLeft;
const scale = isHTMLElement(element) ? getScale(element) : floating_ui_utils_createCoords(1);
const width = element.clientWidth * scale.x;
const height = element.clientHeight * scale.y;
const x = left * scale.x;
function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
if (clippingAncestor === 'viewport') {
rect = getViewportRect(element, strategy);
} else if (clippingAncestor === 'document') {
rect = getDocumentRect(getDocumentElement(element));
} else if (isElement(clippingAncestor)) {
rect = getInnerBoundingClientRect(clippingAncestor, strategy);
const visualOffsets = getVisualOffsets(element);
x: clippingAncestor.x - visualOffsets.x,
y: clippingAncestor.y - visualOffsets.y
return floating_ui_utils_rectToClientRect(rect);
function hasFixedPositionAncestor(element, stopNode) {
const parentNode = getParentNode(element);
if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
return floating_ui_utils_dom_getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
// A "clipping ancestor" is an `overflow` element with the characteristic of
// clipping (or hiding) child elements. This returns all clipping ancestors
// of the given element up the tree.
function getClippingElementAncestors(element, cache) {
const cachedResult = cache.get(element);
let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
let currentContainingBlockComputedStyle = null;
const elementIsFixed = floating_ui_utils_dom_getComputedStyle(element).position === 'fixed';
let currentNode = elementIsFixed ? getParentNode(element) : element;
// https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
const computedStyle = floating_ui_utils_dom_getComputedStyle(currentNode);
const currentNodeIsContaining = isContainingBlock(currentNode);
if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
currentContainingBlockComputedStyle = null;
const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
if (shouldDropCurrentNode) {
// Drop non-containing blocks.
result = result.filter(ancestor => ancestor !== currentNode);
// Record last containing block for next iteration.
currentContainingBlockComputedStyle = computedStyle;
currentNode = getParentNode(currentNode);
cache.set(element, result);
// Gets the maximum area that the element is visible in due to any number of
function getClippingRect(_ref) {
const elementClippingAncestors = boundary === 'clippingAncestors' ? getClippingElementAncestors(element, this._c) : [].concat(boundary);
const clippingAncestors = [...elementClippingAncestors, rootBoundary];
const firstClippingAncestor = clippingAncestors[0];
const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
accRect.top = dist_floating_ui_utils_max(rect.top, accRect.top);
accRect.right = dist_floating_ui_utils_min(rect.right, accRect.right);
accRect.bottom = dist_floating_ui_utils_min(rect.bottom, accRect.bottom);
accRect.left = dist_floating_ui_utils_max(rect.left, accRect.left);
}, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
width: clippingRect.right - clippingRect.left,
height: clippingRect.bottom - clippingRect.top,
function getDimensions(element) {
} = getCssDimensions(element);
function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
const isOffsetParentAnElement = isHTMLElement(offsetParent);
const documentElement = getDocumentElement(offsetParent);
const isFixed = strategy === 'fixed';
const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
const offsets = floating_ui_utils_createCoords(0);
if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
scroll = getNodeScroll(offsetParent);
if (isOffsetParentAnElement) {
const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
offsets.x = offsetRect.x + offsetParent.clientLeft;
offsets.y = offsetRect.y + offsetParent.clientTop;
} else if (documentElement) {
offsets.x = getWindowScrollBarX(documentElement);
const x = rect.left + scroll.scrollLeft - offsets.x;
const y = rect.top + scroll.scrollTop - offsets.y;
function getTrueOffsetParent(element, polyfill) {
if (!isHTMLElement(element) || floating_ui_utils_dom_getComputedStyle(element).position === 'fixed') {
return polyfill(element);
return element.offsetParent;
// Gets the closest ancestor positioned element. Handles some edge cases,
// such as table ancestors and cross browser bugs.
function getOffsetParent(element, polyfill) {
const window = floating_ui_utils_dom_getWindow(element);
if (!isHTMLElement(element) || isTopLayer(element)) {
let offsetParent = getTrueOffsetParent(element, polyfill);
while (offsetParent && isTableElement(offsetParent) && floating_ui_utils_dom_getComputedStyle(offsetParent).position === 'static') {
offsetParent = getTrueOffsetParent(offsetParent, polyfill);
if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && floating_ui_utils_dom_getComputedStyle(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
return offsetParent || getContainingBlock(element) || window;
const getElementRects = async function (data) {
const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
const getDimensionsFn = this.getDimensions;
reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
...(await getDimensionsFn(data.floating))
function isRTL(element) {
return floating_ui_utils_dom_getComputedStyle(element).direction === 'rtl';
convertOffsetParentRelativeRectToViewportRelativeRect,
getDocumentElement: getDocumentElement,
// https://samthor.au/2021/observing-dom/
function observeMove(element, onMove) {
const root = getDocumentElement(element);
(_io = io) == null || _io.disconnect();
function refresh(skip, threshold) {
if (threshold === void 0) {
} = element.getBoundingClientRect();
const insetTop = floating_ui_utils_floor(top);
const insetRight = floating_ui_utils_floor(root.clientWidth - (left + width));
const insetBottom = floating_ui_utils_floor(root.clientHeight - (top + height));
const insetLeft = floating_ui_utils_floor(left);
const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
threshold: dist_floating_ui_utils_max(0, dist_floating_ui_utils_min(1, threshold)) || 1
let isFirstUpdate = true;
function handleObserve(entries) {
const ratio = entries[0].intersectionRatio;
if (ratio !== threshold) {
timeoutId = setTimeout(() => {
// Older browsers don't support a `document` as the root and will throw an
io = new IntersectionObserver(handleObserve, {
io = new IntersectionObserver(handleObserve, options);
* Automatically updates the position of the floating element when necessary.
* Should only be called when the floating element is mounted on the DOM or
* @returns cleanup function that should be invoked when the floating element is
* removed from the DOM or hidden from the screen.
* @see https://floating-ui.com/docs/autoUpdate
function autoUpdate(reference, floating, update, options) {
if (options === void 0) {
elementResize = typeof ResizeObserver === 'function',
layoutShift = typeof IntersectionObserver === 'function',
const referenceEl = unwrapElement(reference);
const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
ancestors.forEach(ancestor => {
ancestorScroll && ancestor.addEventListener('scroll', update, {
ancestorResize && ancestor.addEventListener('resize', update);
const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
let resizeObserver = null;
resizeObserver = new ResizeObserver(_ref => {
if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
// Prevent update loops when using the `size` middleware.
// https://github.com/floating-ui/floating-ui/issues/1740
resizeObserver.unobserve(floating);
cancelAnimationFrame(reobserveFrame);
reobserveFrame = requestAnimationFrame(() => {
(_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
if (referenceEl && !animationFrame) {
resizeObserver.observe(referenceEl);