Spaces:
Running
Running
| import { rectToClientRect, arrow as arrow$1, autoPlacement as autoPlacement$1, detectOverflow as detectOverflow$1, flip as flip$1, hide as hide$1, inline as inline$1, limitShift as limitShift$1, offset as offset$1, shift as shift$1, size as size$1, computePosition as computePosition$1 } from '@floating-ui/core'; | |
| /** | |
| * Custom positioning reference element. | |
| * @see https://floating-ui.com/docs/virtual-elements | |
| */ | |
| const min = Math.min; | |
| const max = Math.max; | |
| const round = Math.round; | |
| const floor = Math.floor; | |
| const createCoords = v => ({ | |
| x: v, | |
| y: v | |
| }); | |
| function hasWindow() { | |
| return typeof window !== 'undefined'; | |
| } | |
| function getNodeName(node) { | |
| if (isNode(node)) { | |
| return (node.nodeName || '').toLowerCase(); | |
| } | |
| // Mocked nodes in testing environments may not be instances of Node. By | |
| // returning `#document` an infinite loop won't occur. | |
| // https://github.com/floating-ui/floating-ui/issues/2317 | |
| return '#document'; | |
| } | |
| function getWindow(node) { | |
| var _node$ownerDocument; | |
| return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window; | |
| } | |
| function getDocumentElement(node) { | |
| var _ref; | |
| return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement; | |
| } | |
| function isNode(value) { | |
| if (!hasWindow()) { | |
| return false; | |
| } | |
| return value instanceof Node || value instanceof getWindow(value).Node; | |
| } | |
| function isElement(value) { | |
| if (!hasWindow()) { | |
| return false; | |
| } | |
| return value instanceof Element || value instanceof getWindow(value).Element; | |
| } | |
| function isHTMLElement(value) { | |
| if (!hasWindow()) { | |
| return false; | |
| } | |
| return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement; | |
| } | |
| function isShadowRoot(value) { | |
| if (!hasWindow() || typeof ShadowRoot === 'undefined') { | |
| return false; | |
| } | |
| return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot; | |
| } | |
| function isOverflowElement(element) { | |
| const { | |
| overflow, | |
| overflowX, | |
| overflowY, | |
| display | |
| } = getComputedStyle(element); | |
| return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display); | |
| } | |
| function isTableElement(element) { | |
| return ['table', 'td', 'th'].includes(getNodeName(element)); | |
| } | |
| function isTopLayer(element) { | |
| return [':popover-open', ':modal'].some(selector => { | |
| try { | |
| return element.matches(selector); | |
| } catch (_e) { | |
| return false; | |
| } | |
| }); | |
| } | |
| function isContainingBlock(elementOrCss) { | |
| const webkit = isWebKit(); | |
| const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss; | |
| // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block | |
| // https://drafts.csswg.org/css-transforms-2/#individual-transforms | |
| return ['transform', 'translate', 'scale', 'rotate', 'perspective'].some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value)); | |
| } | |
| function getContainingBlock(element) { | |
| let currentNode = getParentNode(element); | |
| while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) { | |
| if (isContainingBlock(currentNode)) { | |
| return currentNode; | |
| } else if (isTopLayer(currentNode)) { | |
| return null; | |
| } | |
| currentNode = getParentNode(currentNode); | |
| } | |
| return null; | |
| } | |
| function isWebKit() { | |
| if (typeof CSS === 'undefined' || !CSS.supports) return false; | |
| return CSS.supports('-webkit-backdrop-filter', 'none'); | |
| } | |
| function isLastTraversableNode(node) { | |
| return ['html', 'body', '#document'].includes(getNodeName(node)); | |
| } | |
| function getComputedStyle(element) { | |
| return getWindow(element).getComputedStyle(element); | |
| } | |
| function getNodeScroll(element) { | |
| if (isElement(element)) { | |
| return { | |
| scrollLeft: element.scrollLeft, | |
| scrollTop: element.scrollTop | |
| }; | |
| } | |
| return { | |
| scrollLeft: element.scrollX, | |
| scrollTop: element.scrollY | |
| }; | |
| } | |
| function getParentNode(node) { | |
| if (getNodeName(node) === 'html') { | |
| return node; | |
| } | |
| const result = | |
| // Step into the shadow DOM of the parent of a slotted node. | |
| node.assignedSlot || | |
| // DOM Element detected. | |
| node.parentNode || | |
| // ShadowRoot detected. | |
| isShadowRoot(node) && node.host || | |
| // Fallback. | |
| getDocumentElement(node); | |
| return isShadowRoot(result) ? result.host : result; | |
| } | |
| function getNearestOverflowAncestor(node) { | |
| const parentNode = getParentNode(node); | |
| if (isLastTraversableNode(parentNode)) { | |
| return node.ownerDocument ? node.ownerDocument.body : node.body; | |
| } | |
| if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) { | |
| return parentNode; | |
| } | |
| return getNearestOverflowAncestor(parentNode); | |
| } | |
| function getOverflowAncestors(node, list, traverseIframes) { | |
| var _node$ownerDocument2; | |
| if (list === void 0) { | |
| list = []; | |
| } | |
| if (traverseIframes === void 0) { | |
| traverseIframes = true; | |
| } | |
| const scrollableAncestor = getNearestOverflowAncestor(node); | |
| const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body); | |
| const win = getWindow(scrollableAncestor); | |
| if (isBody) { | |
| const frameElement = getFrameElement(win); | |
| return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []); | |
| } | |
| return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); | |
| } | |
| function getFrameElement(win) { | |
| return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; | |
| } | |
| function getCssDimensions(element) { | |
| const css = getComputedStyle(element); | |
| // In testing environments, the `width` and `height` properties are empty | |
| // strings for SVG elements, returning NaN. Fallback to `0` in this case. | |
| let width = parseFloat(css.width) || 0; | |
| let height = parseFloat(css.height) || 0; | |
| const hasOffset = isHTMLElement(element); | |
| const offsetWidth = hasOffset ? element.offsetWidth : width; | |
| const offsetHeight = hasOffset ? element.offsetHeight : height; | |
| const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight; | |
| if (shouldFallback) { | |
| width = offsetWidth; | |
| height = offsetHeight; | |
| } | |
| return { | |
| width, | |
| height, | |
| $: shouldFallback | |
| }; | |
| } | |
| function unwrapElement(element) { | |
| return !isElement(element) ? element.contextElement : element; | |
| } | |
| function getScale(element) { | |
| const domElement = unwrapElement(element); | |
| if (!isHTMLElement(domElement)) { | |
| return createCoords(1); | |
| } | |
| const rect = domElement.getBoundingClientRect(); | |
| const { | |
| width, | |
| height, | |
| $ | |
| } = getCssDimensions(domElement); | |
| let x = ($ ? round(rect.width) : rect.width) / width; | |
| let y = ($ ? round(rect.height) : rect.height) / height; | |
| // 0, NaN, or Infinity should always fallback to 1. | |
| if (!x || !Number.isFinite(x)) { | |
| x = 1; | |
| } | |
| if (!y || !Number.isFinite(y)) { | |
| y = 1; | |
| } | |
| return { | |
| x, | |
| y | |
| }; | |
| } | |
| const noOffsets = /*#__PURE__*/createCoords(0); | |
| function getVisualOffsets(element) { | |
| const win = getWindow(element); | |
| if (!isWebKit() || !win.visualViewport) { | |
| return noOffsets; | |
| } | |
| return { | |
| x: win.visualViewport.offsetLeft, | |
| y: win.visualViewport.offsetTop | |
| }; | |
| } | |
| function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) { | |
| if (isFixed === void 0) { | |
| isFixed = false; | |
| } | |
| if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) { | |
| return false; | |
| } | |
| return isFixed; | |
| } | |
| function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { | |
| if (includeScale === void 0) { | |
| includeScale = false; | |
| } | |
| if (isFixedStrategy === void 0) { | |
| isFixedStrategy = false; | |
| } | |
| const clientRect = element.getBoundingClientRect(); | |
| const domElement = unwrapElement(element); | |
| let scale = createCoords(1); | |
| if (includeScale) { | |
| if (offsetParent) { | |
| if (isElement(offsetParent)) { | |
| scale = getScale(offsetParent); | |
| } | |
| } else { | |
| scale = getScale(element); | |
| } | |
| } | |
| const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : 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; | |
| if (domElement) { | |
| const win = getWindow(domElement); | |
| const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent; | |
| let currentWin = win; | |
| let currentIFrame = getFrameElement(currentWin); | |
| while (currentIFrame && offsetParent && offsetWin !== currentWin) { | |
| const iframeScale = getScale(currentIFrame); | |
| const iframeRect = currentIFrame.getBoundingClientRect(); | |
| const css = getComputedStyle(currentIFrame); | |
| const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x; | |
| const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y; | |
| x *= iframeScale.x; | |
| y *= iframeScale.y; | |
| width *= iframeScale.x; | |
| height *= iframeScale.y; | |
| x += left; | |
| y += top; | |
| currentWin = getWindow(currentIFrame); | |
| currentIFrame = getFrameElement(currentWin); | |
| } | |
| } | |
| return rectToClientRect({ | |
| width, | |
| height, | |
| x, | |
| y | |
| }); | |
| } | |
| // If <html> has a CSS width greater than the viewport, then this will be | |
| // incorrect for RTL. | |
| function getWindowScrollBarX(element, rect) { | |
| const leftScroll = getNodeScroll(element).scrollLeft; | |
| if (!rect) { | |
| return getBoundingClientRect(getDocumentElement(element)).left + leftScroll; | |
| } | |
| return rect.left + leftScroll; | |
| } | |
| function getHTMLOffset(documentElement, scroll, ignoreScrollbarX) { | |
| if (ignoreScrollbarX === void 0) { | |
| ignoreScrollbarX = false; | |
| } | |
| const htmlRect = documentElement.getBoundingClientRect(); | |
| const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 : | |
| // RTL <body> scrollbar. | |
| getWindowScrollBarX(documentElement, htmlRect)); | |
| const y = htmlRect.top + scroll.scrollTop; | |
| return { | |
| x, | |
| y | |
| }; | |
| } | |
| function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) { | |
| let { | |
| elements, | |
| rect, | |
| offsetParent, | |
| strategy | |
| } = _ref; | |
| const isFixed = strategy === 'fixed'; | |
| const documentElement = getDocumentElement(offsetParent); | |
| const topLayer = elements ? isTopLayer(elements.floating) : false; | |
| if (offsetParent === documentElement || topLayer && isFixed) { | |
| return rect; | |
| } | |
| let scroll = { | |
| scrollLeft: 0, | |
| scrollTop: 0 | |
| }; | |
| let scale = createCoords(1); | |
| const offsets = 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; | |
| } | |
| } | |
| const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0); | |
| return { | |
| width: rect.width * scale.x, | |
| height: rect.height * scale.y, | |
| x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x, | |
| y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y | |
| }; | |
| } | |
| function getClientRects(element) { | |
| return Array.from(element.getClientRects()); | |
| } | |
| // 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 = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth); | |
| const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight); | |
| let x = -scroll.scrollLeft + getWindowScrollBarX(element); | |
| const y = -scroll.scrollTop; | |
| if (getComputedStyle(body).direction === 'rtl') { | |
| x += max(html.clientWidth, body.clientWidth) - width; | |
| } | |
| return { | |
| width, | |
| height, | |
| x, | |
| y | |
| }; | |
| } | |
| function getViewportRect(element, strategy) { | |
| const win = getWindow(element); | |
| const html = getDocumentElement(element); | |
| const visualViewport = win.visualViewport; | |
| let width = html.clientWidth; | |
| let height = html.clientHeight; | |
| let x = 0; | |
| let y = 0; | |
| if (visualViewport) { | |
| width = visualViewport.width; | |
| height = visualViewport.height; | |
| const visualViewportBased = isWebKit(); | |
| if (!visualViewportBased || visualViewportBased && strategy === 'fixed') { | |
| x = visualViewport.offsetLeft; | |
| y = visualViewport.offsetTop; | |
| } | |
| } | |
| return { | |
| width, | |
| height, | |
| x, | |
| y | |
| }; | |
| } | |
| // 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) : createCoords(1); | |
| const width = element.clientWidth * scale.x; | |
| const height = element.clientHeight * scale.y; | |
| const x = left * scale.x; | |
| const y = top * scale.y; | |
| return { | |
| width, | |
| height, | |
| x, | |
| y | |
| }; | |
| } | |
| function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) { | |
| let rect; | |
| if (clippingAncestor === 'viewport') { | |
| rect = getViewportRect(element, strategy); | |
| } else if (clippingAncestor === 'document') { | |
| rect = getDocumentRect(getDocumentElement(element)); | |
| } else if (isElement(clippingAncestor)) { | |
| rect = getInnerBoundingClientRect(clippingAncestor, strategy); | |
| } else { | |
| const visualOffsets = getVisualOffsets(element); | |
| rect = { | |
| x: clippingAncestor.x - visualOffsets.x, | |
| y: clippingAncestor.y - visualOffsets.y, | |
| width: clippingAncestor.width, | |
| height: clippingAncestor.height | |
| }; | |
| } | |
| return rectToClientRect(rect); | |
| } | |
| function hasFixedPositionAncestor(element, stopNode) { | |
| const parentNode = getParentNode(element); | |
| if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) { | |
| return false; | |
| } | |
| return 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); | |
| if (cachedResult) { | |
| return cachedResult; | |
| } | |
| let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body'); | |
| let currentContainingBlockComputedStyle = null; | |
| const elementIsFixed = 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 = 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); | |
| } else { | |
| // Record last containing block for next iteration. | |
| currentContainingBlockComputedStyle = computedStyle; | |
| } | |
| currentNode = getParentNode(currentNode); | |
| } | |
| cache.set(element, result); | |
| return result; | |
| } | |
| // Gets the maximum area that the element is visible in due to any number of | |
| // clipping ancestors. | |
| function getClippingRect(_ref) { | |
| let { | |
| element, | |
| boundary, | |
| rootBoundary, | |
| strategy | |
| } = _ref; | |
| const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : 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 = max(rect.top, accRect.top); | |
| accRect.right = min(rect.right, accRect.right); | |
| accRect.bottom = min(rect.bottom, accRect.bottom); | |
| accRect.left = max(rect.left, accRect.left); | |
| return accRect; | |
| }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy)); | |
| return { | |
| width: clippingRect.right - clippingRect.left, | |
| height: clippingRect.bottom - clippingRect.top, | |
| x: clippingRect.left, | |
| y: clippingRect.top | |
| }; | |
| } | |
| function getDimensions(element) { | |
| const { | |
| width, | |
| height | |
| } = getCssDimensions(element); | |
| return { | |
| width, | |
| height | |
| }; | |
| } | |
| function getRectRelativeToOffsetParent(element, offsetParent, strategy) { | |
| const isOffsetParentAnElement = isHTMLElement(offsetParent); | |
| const documentElement = getDocumentElement(offsetParent); | |
| const isFixed = strategy === 'fixed'; | |
| const rect = getBoundingClientRect(element, true, isFixed, offsetParent); | |
| let scroll = { | |
| scrollLeft: 0, | |
| scrollTop: 0 | |
| }; | |
| const offsets = createCoords(0); | |
| // If the <body> scrollbar appears on the left (e.g. RTL systems). Use | |
| // Firefox with layout.scrollbar.side = 3 in about:config to test this. | |
| function setLeftRTLScrollbarOffset() { | |
| offsets.x = getWindowScrollBarX(documentElement); | |
| } | |
| 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) { | |
| setLeftRTLScrollbarOffset(); | |
| } | |
| } | |
| if (isFixed && !isOffsetParentAnElement && documentElement) { | |
| setLeftRTLScrollbarOffset(); | |
| } | |
| const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); | |
| const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x; | |
| const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y; | |
| return { | |
| x, | |
| y, | |
| width: rect.width, | |
| height: rect.height | |
| }; | |
| } | |
| function isStaticPositioned(element) { | |
| return getComputedStyle(element).position === 'static'; | |
| } | |
| function getTrueOffsetParent(element, polyfill) { | |
| if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') { | |
| return null; | |
| } | |
| if (polyfill) { | |
| return polyfill(element); | |
| } | |
| let rawOffsetParent = element.offsetParent; | |
| // Firefox returns the <html> element as the offsetParent if it's non-static, | |
| // while Chrome and Safari return the <body> element. The <body> element must | |
| // be used to perform the correct calculations even if the <html> element is | |
| // non-static. | |
| if (getDocumentElement(element) === rawOffsetParent) { | |
| rawOffsetParent = rawOffsetParent.ownerDocument.body; | |
| } | |
| return rawOffsetParent; | |
| } | |
| // Gets the closest ancestor positioned element. Handles some edge cases, | |
| // such as table ancestors and cross browser bugs. | |
| function getOffsetParent(element, polyfill) { | |
| const win = getWindow(element); | |
| if (isTopLayer(element)) { | |
| return win; | |
| } | |
| if (!isHTMLElement(element)) { | |
| let svgOffsetParent = getParentNode(element); | |
| while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) { | |
| if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) { | |
| return svgOffsetParent; | |
| } | |
| svgOffsetParent = getParentNode(svgOffsetParent); | |
| } | |
| return win; | |
| } | |
| let offsetParent = getTrueOffsetParent(element, polyfill); | |
| while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) { | |
| offsetParent = getTrueOffsetParent(offsetParent, polyfill); | |
| } | |
| if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) { | |
| return win; | |
| } | |
| return offsetParent || getContainingBlock(element) || win; | |
| } | |
| const getElementRects = async function (data) { | |
| const getOffsetParentFn = this.getOffsetParent || getOffsetParent; | |
| const getDimensionsFn = this.getDimensions; | |
| const floatingDimensions = await getDimensionsFn(data.floating); | |
| return { | |
| reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy), | |
| floating: { | |
| x: 0, | |
| y: 0, | |
| width: floatingDimensions.width, | |
| height: floatingDimensions.height | |
| } | |
| }; | |
| }; | |
| function isRTL(element) { | |
| return getComputedStyle(element).direction === 'rtl'; | |
| } | |
| const platform = { | |
| convertOffsetParentRelativeRectToViewportRelativeRect, | |
| getDocumentElement, | |
| getClippingRect, | |
| getOffsetParent, | |
| getElementRects, | |
| getClientRects, | |
| getDimensions, | |
| getScale, | |
| isElement, | |
| isRTL | |
| }; | |
| function rectsAreEqual(a, b) { | |
| return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; | |
| } | |
| // https://samthor.au/2021/observing-dom/ | |
| function observeMove(element, onMove) { | |
| let io = null; | |
| let timeoutId; | |
| const root = getDocumentElement(element); | |
| function cleanup() { | |
| var _io; | |
| clearTimeout(timeoutId); | |
| (_io = io) == null || _io.disconnect(); | |
| io = null; | |
| } | |
| function refresh(skip, threshold) { | |
| if (skip === void 0) { | |
| skip = false; | |
| } | |
| if (threshold === void 0) { | |
| threshold = 1; | |
| } | |
| cleanup(); | |
| const elementRectForRootMargin = element.getBoundingClientRect(); | |
| const { | |
| left, | |
| top, | |
| width, | |
| height | |
| } = elementRectForRootMargin; | |
| if (!skip) { | |
| onMove(); | |
| } | |
| if (!width || !height) { | |
| return; | |
| } | |
| const insetTop = floor(top); | |
| const insetRight = floor(root.clientWidth - (left + width)); | |
| const insetBottom = floor(root.clientHeight - (top + height)); | |
| const insetLeft = floor(left); | |
| const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px"; | |
| const options = { | |
| rootMargin, | |
| threshold: max(0, min(1, threshold)) || 1 | |
| }; | |
| let isFirstUpdate = true; | |
| function handleObserve(entries) { | |
| const ratio = entries[0].intersectionRatio; | |
| if (ratio !== threshold) { | |
| if (!isFirstUpdate) { | |
| return refresh(); | |
| } | |
| if (!ratio) { | |
| // If the reference is clipped, the ratio is 0. Throttle the refresh | |
| // to prevent an infinite loop of updates. | |
| timeoutId = setTimeout(() => { | |
| refresh(false, 1e-7); | |
| }, 1000); | |
| } else { | |
| refresh(false, ratio); | |
| } | |
| } | |
| if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) { | |
| // It's possible that even though the ratio is reported as 1, the | |
| // element is not actually fully within the IntersectionObserver's root | |
| // area anymore. This can happen under performance constraints. This may | |
| // be a bug in the browser's IntersectionObserver implementation. To | |
| // work around this, we compare the element's bounding rect now with | |
| // what it was at the time we created the IntersectionObserver. If they | |
| // are not equal then the element moved, so we refresh. | |
| refresh(); | |
| } | |
| isFirstUpdate = false; | |
| } | |
| // Older browsers don't support a `document` as the root and will throw an | |
| // error. | |
| try { | |
| io = new IntersectionObserver(handleObserve, { | |
| ...options, | |
| // Handle <iframe>s | |
| root: root.ownerDocument | |
| }); | |
| } catch (_e) { | |
| io = new IntersectionObserver(handleObserve, options); | |
| } | |
| io.observe(element); | |
| } | |
| refresh(true); | |
| return cleanup; | |
| } | |
| /** | |
| * Automatically updates the position of the floating element when necessary. | |
| * Should only be called when the floating element is mounted on the DOM or | |
| * visible on the screen. | |
| * @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) { | |
| options = {}; | |
| } | |
| const { | |
| ancestorScroll = true, | |
| ancestorResize = true, | |
| elementResize = typeof ResizeObserver === 'function', | |
| layoutShift = typeof IntersectionObserver === 'function', | |
| animationFrame = false | |
| } = options; | |
| const referenceEl = unwrapElement(reference); | |
| const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : []; | |
| ancestors.forEach(ancestor => { | |
| ancestorScroll && ancestor.addEventListener('scroll', update, { | |
| passive: true | |
| }); | |
| ancestorResize && ancestor.addEventListener('resize', update); | |
| }); | |
| const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null; | |
| let reobserveFrame = -1; | |
| let resizeObserver = null; | |
| if (elementResize) { | |
| resizeObserver = new ResizeObserver(_ref => { | |
| let [firstEntry] = _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(() => { | |
| var _resizeObserver; | |
| (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating); | |
| }); | |
| } | |
| update(); | |
| }); | |
| if (referenceEl && !animationFrame) { | |
| resizeObserver.observe(referenceEl); | |
| } | |
| resizeObserver.observe(floating); | |
| } | |
| let frameId; | |
| let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null; | |
| if (animationFrame) { | |
| frameLoop(); | |
| } | |
| function frameLoop() { | |
| const nextRefRect = getBoundingClientRect(reference); | |
| if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) { | |
| update(); | |
| } | |
| prevRefRect = nextRefRect; | |
| frameId = requestAnimationFrame(frameLoop); | |
| } | |
| update(); | |
| return () => { | |
| var _resizeObserver2; | |
| ancestors.forEach(ancestor => { | |
| ancestorScroll && ancestor.removeEventListener('scroll', update); | |
| ancestorResize && ancestor.removeEventListener('resize', update); | |
| }); | |
| cleanupIo == null || cleanupIo(); | |
| (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect(); | |
| resizeObserver = null; | |
| if (animationFrame) { | |
| cancelAnimationFrame(frameId); | |
| } | |
| }; | |
| } | |
| /** | |
| * Resolves with an object of overflow side offsets that determine how much the | |
| * element is overflowing a given clipping boundary on each side. | |
| * - positive = overflowing the boundary by that number of pixels | |
| * - negative = how many pixels left before it will overflow | |
| * - 0 = lies flush with the boundary | |
| * @see https://floating-ui.com/docs/detectOverflow | |
| */ | |
| const detectOverflow = detectOverflow$1; | |
| /** | |
| * Modifies the placement by translating the floating element along the | |
| * specified axes. | |
| * A number (shorthand for `mainAxis` or distance), or an axes configuration | |
| * object may be passed. | |
| * @see https://floating-ui.com/docs/offset | |
| */ | |
| const offset = offset$1; | |
| /** | |
| * Optimizes the visibility of the floating element by choosing the placement | |
| * that has the most space available automatically, without needing to specify a | |
| * preferred placement. Alternative to `flip`. | |
| * @see https://floating-ui.com/docs/autoPlacement | |
| */ | |
| const autoPlacement = autoPlacement$1; | |
| /** | |
| * Optimizes the visibility of the floating element by shifting it in order to | |
| * keep it in view when it will overflow the clipping boundary. | |
| * @see https://floating-ui.com/docs/shift | |
| */ | |
| const shift = shift$1; | |
| /** | |
| * Optimizes the visibility of the floating element by flipping the `placement` | |
| * in order to keep it in view when the preferred placement(s) will overflow the | |
| * clipping boundary. Alternative to `autoPlacement`. | |
| * @see https://floating-ui.com/docs/flip | |
| */ | |
| const flip = flip$1; | |
| /** | |
| * Provides data that allows you to change the size of the floating element — | |
| * for instance, prevent it from overflowing the clipping boundary or match the | |
| * width of the reference element. | |
| * @see https://floating-ui.com/docs/size | |
| */ | |
| const size = size$1; | |
| /** | |
| * Provides data to hide the floating element in applicable situations, such as | |
| * when it is not in the same clipping context as the reference element. | |
| * @see https://floating-ui.com/docs/hide | |
| */ | |
| const hide = hide$1; | |
| /** | |
| * Provides data to position an inner element of the floating element so that it | |
| * appears centered to the reference element. | |
| * @see https://floating-ui.com/docs/arrow | |
| */ | |
| const arrow = arrow$1; | |
| /** | |
| * Provides improved positioning for inline reference elements that can span | |
| * over multiple lines, such as hyperlinks or range selections. | |
| * @see https://floating-ui.com/docs/inline | |
| */ | |
| const inline = inline$1; | |
| /** | |
| * Built-in `limiter` that will stop `shift()` at a certain point. | |
| */ | |
| const limitShift = limitShift$1; | |
| /** | |
| * Computes the `x` and `y` coordinates that will place the floating element | |
| * next to a given reference element. | |
| */ | |
| const computePosition = (reference, floating, options) => { | |
| // This caches the expensive `getClippingElementAncestors` function so that | |
| // multiple lifecycle resets re-use the same result. It only lives for a | |
| // single call. If other functions become expensive, we can add them as well. | |
| const cache = new Map(); | |
| const mergedOptions = { | |
| platform, | |
| ...options | |
| }; | |
| const platformWithCache = { | |
| ...mergedOptions.platform, | |
| _c: cache | |
| }; | |
| return computePosition$1(reference, floating, { | |
| ...mergedOptions, | |
| platform: platformWithCache | |
| }); | |
| }; | |
| export { arrow, autoPlacement, autoUpdate, computePosition, detectOverflow, flip, getOverflowAncestors, hide, inline, limitShift, offset, platform, shift, size }; | |