You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							643 lines
						
					
					
						
							21 KiB
						
					
					
				
			
		
		
	
	
							643 lines
						
					
					
						
							21 KiB
						
					
					
				| import { rectToClientRect, computePosition as computePosition$1 } from '@floating-ui/core';
 | |
| export { arrow, autoPlacement, detectOverflow, flip, hide, inline, limitShift, offset, shift, size } from '@floating-ui/core';
 | |
| 
 | |
| function getWindow(node) {
 | |
|   var _node$ownerDocument;
 | |
|   return ((_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
 | |
| }
 | |
| 
 | |
| function getComputedStyle$1(element) {
 | |
|   return getWindow(element).getComputedStyle(element);
 | |
| }
 | |
| 
 | |
| function getNodeName(node) {
 | |
|   return isNode(node) ? (node.nodeName || '').toLowerCase() : '';
 | |
| }
 | |
| 
 | |
| let uaString;
 | |
| function getUAString() {
 | |
|   if (uaString) {
 | |
|     return uaString;
 | |
|   }
 | |
|   const uaData = navigator.userAgentData;
 | |
|   if (uaData && Array.isArray(uaData.brands)) {
 | |
|     uaString = uaData.brands.map(item => item.brand + "/" + item.version).join(' ');
 | |
|     return uaString;
 | |
|   }
 | |
|   return navigator.userAgent;
 | |
| }
 | |
| 
 | |
| function isHTMLElement(value) {
 | |
|   return value instanceof getWindow(value).HTMLElement;
 | |
| }
 | |
| function isElement(value) {
 | |
|   return value instanceof getWindow(value).Element;
 | |
| }
 | |
| function isNode(value) {
 | |
|   return value instanceof getWindow(value).Node;
 | |
| }
 | |
| function isShadowRoot(node) {
 | |
|   // Browsers without `ShadowRoot` support
 | |
|   if (typeof ShadowRoot === 'undefined') {
 | |
|     return false;
 | |
|   }
 | |
|   const OwnElement = getWindow(node).ShadowRoot;
 | |
|   return node instanceof OwnElement || node instanceof ShadowRoot;
 | |
| }
 | |
| function isOverflowElement(element) {
 | |
|   const {
 | |
|     overflow,
 | |
|     overflowX,
 | |
|     overflowY,
 | |
|     display
 | |
|   } = getComputedStyle$1(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 isContainingBlock(element) {
 | |
|   // TODO: Try and use feature detection here instead
 | |
|   const isFirefox = /firefox/i.test(getUAString());
 | |
|   const css = getComputedStyle$1(element);
 | |
|   const backdropFilter = css.backdropFilter || css.WebkitBackdropFilter;
 | |
| 
 | |
|   // This is non-exhaustive but covers the most common CSS properties that
 | |
|   // create a containing block.
 | |
|   // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
 | |
|   return css.transform !== 'none' || css.perspective !== 'none' || (backdropFilter ? backdropFilter !== 'none' : false) || isFirefox && css.willChange === 'filter' || isFirefox && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective'].some(value => css.willChange.includes(value)) || ['paint', 'layout', 'strict', 'content'].some(
 | |
|   // TS 4.1 compat
 | |
|   value => {
 | |
|     const contain = css.contain;
 | |
|     return contain != null ? contain.includes(value) : false;
 | |
|   });
 | |
| }
 | |
| function isLayoutViewport() {
 | |
|   // Not Safari
 | |
|   return !/^((?!chrome|android).)*safari/i.test(getUAString());
 | |
|   // Feature detection for this fails in various ways
 | |
|   // • Always-visible scrollbar or not
 | |
|   // • Width of <html>, etc.
 | |
|   // const vV = win.visualViewport;
 | |
|   // return vV ? Math.abs(win.innerWidth / vV.scale - vV.width) < 0.5 : true;
 | |
| }
 | |
| 
 | |
| function isLastTraversableNode(node) {
 | |
|   return ['html', 'body', '#document'].includes(getNodeName(node));
 | |
| }
 | |
| 
 | |
| const min = Math.min;
 | |
| const max = Math.max;
 | |
| const round = Math.round;
 | |
| 
 | |
| function getCssDimensions(element) {
 | |
|   const css = getComputedStyle$1(element);
 | |
|   let width = parseFloat(css.width);
 | |
|   let height = parseFloat(css.height);
 | |
|   const offsetWidth = element.offsetWidth;
 | |
|   const offsetHeight = element.offsetHeight;
 | |
|   const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
 | |
|   if (shouldFallback) {
 | |
|     width = offsetWidth;
 | |
|     height = offsetHeight;
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height,
 | |
|     fallback: shouldFallback
 | |
|   };
 | |
| }
 | |
| 
 | |
| function unwrapElement(element) {
 | |
|   return !isElement(element) ? element.contextElement : element;
 | |
| }
 | |
| 
 | |
| const FALLBACK_SCALE = {
 | |
|   x: 1,
 | |
|   y: 1
 | |
| };
 | |
| function getScale(element) {
 | |
|   const domElement = unwrapElement(element);
 | |
|   if (!isHTMLElement(domElement)) {
 | |
|     return FALLBACK_SCALE;
 | |
|   }
 | |
|   const rect = domElement.getBoundingClientRect();
 | |
|   const {
 | |
|     width,
 | |
|     height,
 | |
|     fallback
 | |
|   } = getCssDimensions(domElement);
 | |
|   let x = (fallback ? round(rect.width) : rect.width) / width;
 | |
|   let y = (fallback ? 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
 | |
|   };
 | |
| }
 | |
| 
 | |
| function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
 | |
|   var _win$visualViewport, _win$visualViewport2;
 | |
|   if (includeScale === void 0) {
 | |
|     includeScale = false;
 | |
|   }
 | |
|   if (isFixedStrategy === void 0) {
 | |
|     isFixedStrategy = false;
 | |
|   }
 | |
|   const clientRect = element.getBoundingClientRect();
 | |
|   const domElement = unwrapElement(element);
 | |
|   let scale = FALLBACK_SCALE;
 | |
|   if (includeScale) {
 | |
|     if (offsetParent) {
 | |
|       if (isElement(offsetParent)) {
 | |
|         scale = getScale(offsetParent);
 | |
|       }
 | |
|     } else {
 | |
|       scale = getScale(element);
 | |
|     }
 | |
|   }
 | |
|   const win = domElement ? getWindow(domElement) : window;
 | |
|   const addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
 | |
|   let x = (clientRect.left + (addVisualOffsets ? ((_win$visualViewport = win.visualViewport) == null ? void 0 : _win$visualViewport.offsetLeft) || 0 : 0)) / scale.x;
 | |
|   let y = (clientRect.top + (addVisualOffsets ? ((_win$visualViewport2 = win.visualViewport) == null ? void 0 : _win$visualViewport2.offsetTop) || 0 : 0)) / 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 currentIFrame = win.frameElement;
 | |
|     while (currentIFrame && offsetParent && offsetWin !== win) {
 | |
|       const iframeScale = getScale(currentIFrame);
 | |
|       const iframeRect = currentIFrame.getBoundingClientRect();
 | |
|       const css = getComputedStyle(currentIFrame);
 | |
|       iframeRect.x += (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
 | |
|       iframeRect.y += (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
 | |
|       x *= iframeScale.x;
 | |
|       y *= iframeScale.y;
 | |
|       width *= iframeScale.x;
 | |
|       height *= iframeScale.y;
 | |
|       x += iframeRect.x;
 | |
|       y += iframeRect.y;
 | |
|       currentIFrame = getWindow(currentIFrame).frameElement;
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height,
 | |
|     top: y,
 | |
|     right: x + width,
 | |
|     bottom: y + height,
 | |
|     left: x,
 | |
|     x,
 | |
|     y
 | |
|   };
 | |
| }
 | |
| 
 | |
| function getDocumentElement(node) {
 | |
|   return ((isNode(node) ? node.ownerDocument : node.document) || window.document).documentElement;
 | |
| }
 | |
| 
 | |
| function getNodeScroll(element) {
 | |
|   if (isElement(element)) {
 | |
|     return {
 | |
|       scrollLeft: element.scrollLeft,
 | |
|       scrollTop: element.scrollTop
 | |
|     };
 | |
|   }
 | |
|   return {
 | |
|     scrollLeft: element.pageXOffset,
 | |
|     scrollTop: element.pageYOffset
 | |
|   };
 | |
| }
 | |
| 
 | |
| function getWindowScrollBarX(element) {
 | |
|   // If <html> has a CSS width greater than the viewport, then this will be
 | |
|   // incorrect for RTL.
 | |
|   return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
 | |
| }
 | |
| 
 | |
| function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
 | |
|   const isOffsetParentAnElement = isHTMLElement(offsetParent);
 | |
|   const documentElement = getDocumentElement(offsetParent);
 | |
|   const rect = getBoundingClientRect(element, true, strategy === 'fixed', offsetParent);
 | |
|   let scroll = {
 | |
|     scrollLeft: 0,
 | |
|     scrollTop: 0
 | |
|   };
 | |
|   const offsets = {
 | |
|     x: 0,
 | |
|     y: 0
 | |
|   };
 | |
|   if (isOffsetParentAnElement || !isOffsetParentAnElement && strategy !== 'fixed') {
 | |
|     if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
 | |
|       scroll = getNodeScroll(offsetParent);
 | |
|     }
 | |
|     if (isHTMLElement(offsetParent)) {
 | |
|       const offsetRect = getBoundingClientRect(offsetParent, true);
 | |
|       offsets.x = offsetRect.x + offsetParent.clientLeft;
 | |
|       offsets.y = offsetRect.y + offsetParent.clientTop;
 | |
|     } else if (documentElement) {
 | |
|       offsets.x = getWindowScrollBarX(documentElement);
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     x: rect.left + scroll.scrollLeft - offsets.x,
 | |
|     y: rect.top + scroll.scrollTop - offsets.y,
 | |
|     width: rect.width,
 | |
|     height: rect.height
 | |
|   };
 | |
| }
 | |
| 
 | |
| 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 : null) ||
 | |
|   // Fallback
 | |
|   getDocumentElement(node);
 | |
|   return isShadowRoot(result) ? result.host : result;
 | |
| }
 | |
| 
 | |
| function getTrueOffsetParent(element) {
 | |
|   if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') {
 | |
|     return null;
 | |
|   }
 | |
|   return element.offsetParent;
 | |
| }
 | |
| function getContainingBlock(element) {
 | |
|   let currentNode = getParentNode(element);
 | |
|   while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
 | |
|     if (isContainingBlock(currentNode)) {
 | |
|       return currentNode;
 | |
|     } else {
 | |
|       currentNode = getParentNode(currentNode);
 | |
|     }
 | |
|   }
 | |
|   return null;
 | |
| }
 | |
| 
 | |
| // Gets the closest ancestor positioned element. Handles some edge cases,
 | |
| // such as table ancestors and cross browser bugs.
 | |
| function getOffsetParent(element) {
 | |
|   const window = getWindow(element);
 | |
|   let offsetParent = getTrueOffsetParent(element);
 | |
|   while (offsetParent && isTableElement(offsetParent) && getComputedStyle$1(offsetParent).position === 'static') {
 | |
|     offsetParent = getTrueOffsetParent(offsetParent);
 | |
|   }
 | |
|   if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle$1(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
 | |
|     return window;
 | |
|   }
 | |
|   return offsetParent || getContainingBlock(element) || window;
 | |
| }
 | |
| 
 | |
| function getDimensions(element) {
 | |
|   return getCssDimensions(element);
 | |
| }
 | |
| 
 | |
| function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
 | |
|   let {
 | |
|     rect,
 | |
|     offsetParent,
 | |
|     strategy
 | |
|   } = _ref;
 | |
|   const isOffsetParentAnElement = isHTMLElement(offsetParent);
 | |
|   const documentElement = getDocumentElement(offsetParent);
 | |
|   if (offsetParent === documentElement) {
 | |
|     return rect;
 | |
|   }
 | |
|   let scroll = {
 | |
|     scrollLeft: 0,
 | |
|     scrollTop: 0
 | |
|   };
 | |
|   let scale = {
 | |
|     x: 1,
 | |
|     y: 1
 | |
|   };
 | |
|   const offsets = {
 | |
|     x: 0,
 | |
|     y: 0
 | |
|   };
 | |
|   if (isOffsetParentAnElement || !isOffsetParentAnElement && strategy !== 'fixed') {
 | |
|     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;
 | |
|     }
 | |
|     // This doesn't appear to need to be negated.
 | |
|     // else if (documentElement) {
 | |
|     //   offsets.x = getWindowScrollBarX(documentElement);
 | |
|     // }
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     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 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 layoutViewport = isLayoutViewport();
 | |
|     if (layoutViewport || !layoutViewport && strategy === 'fixed') {
 | |
|       x = visualViewport.offsetLeft;
 | |
|       y = visualViewport.offsetTop;
 | |
|     }
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height,
 | |
|     x,
 | |
|     y
 | |
|   };
 | |
| }
 | |
| 
 | |
| // 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) {
 | |
|   var _element$ownerDocumen;
 | |
|   const html = getDocumentElement(element);
 | |
|   const scroll = getNodeScroll(element);
 | |
|   const body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
 | |
|   const width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
 | |
|   const height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
 | |
|   let x = -scroll.scrollLeft + getWindowScrollBarX(element);
 | |
|   const y = -scroll.scrollTop;
 | |
|   if (getComputedStyle$1(body || html).direction === 'rtl') {
 | |
|     x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
 | |
|   }
 | |
|   return {
 | |
|     width,
 | |
|     height,
 | |
|     x,
 | |
|     y
 | |
|   };
 | |
| }
 | |
| 
 | |
| function getNearestOverflowAncestor(node) {
 | |
|   const parentNode = getParentNode(node);
 | |
|   if (isLastTraversableNode(parentNode)) {
 | |
|     // @ts-ignore assume body is always available
 | |
|     return node.ownerDocument.body;
 | |
|   }
 | |
|   if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
 | |
|     return parentNode;
 | |
|   }
 | |
|   return getNearestOverflowAncestor(parentNode);
 | |
| }
 | |
| 
 | |
| function getOverflowAncestors(node, list) {
 | |
|   var _node$ownerDocument;
 | |
|   if (list === void 0) {
 | |
|     list = [];
 | |
|   }
 | |
|   const scrollableAncestor = getNearestOverflowAncestor(node);
 | |
|   const isBody = scrollableAncestor === ((_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.body);
 | |
|   const win = getWindow(scrollableAncestor);
 | |
|   if (isBody) {
 | |
|     return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : []);
 | |
|   }
 | |
|   return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor));
 | |
| }
 | |
| 
 | |
| // 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) : {
 | |
|     x: 1,
 | |
|     y: 1
 | |
|   };
 | |
|   const width = element.clientWidth * scale.x;
 | |
|   const height = element.clientHeight * scale.y;
 | |
|   const x = left * scale.x;
 | |
|   const y = top * scale.y;
 | |
|   return {
 | |
|     top: y,
 | |
|     left: x,
 | |
|     right: x + width,
 | |
|     bottom: y + height,
 | |
|     x,
 | |
|     y,
 | |
|     width,
 | |
|     height
 | |
|   };
 | |
| }
 | |
| function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
 | |
|   if (clippingAncestor === 'viewport') {
 | |
|     return rectToClientRect(getViewportRect(element, strategy));
 | |
|   }
 | |
|   if (isElement(clippingAncestor)) {
 | |
|     return getInnerBoundingClientRect(clippingAncestor, strategy);
 | |
|   }
 | |
|   return rectToClientRect(getDocumentRect(getDocumentElement(element)));
 | |
| }
 | |
| 
 | |
| // 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).filter(el => isElement(el) && getNodeName(el) !== 'body');
 | |
|   let currentContainingBlockComputedStyle = null;
 | |
|   const elementIsFixed = getComputedStyle$1(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$1(currentNode);
 | |
|     const containingBlock = isContainingBlock(currentNode);
 | |
|     const shouldDropCurrentNode = elementIsFixed ? !containingBlock && !currentContainingBlockComputedStyle : !containingBlock && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position);
 | |
|     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' ? 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
 | |
|   };
 | |
| }
 | |
| 
 | |
| const platform = {
 | |
|   getClippingRect,
 | |
|   convertOffsetParentRelativeRectToViewportRelativeRect,
 | |
|   isElement,
 | |
|   getDimensions,
 | |
|   getOffsetParent,
 | |
|   getDocumentElement,
 | |
|   getScale,
 | |
|   async getElementRects(_ref) {
 | |
|     let {
 | |
|       reference,
 | |
|       floating,
 | |
|       strategy
 | |
|     } = _ref;
 | |
|     const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
 | |
|     const getDimensionsFn = this.getDimensions;
 | |
|     return {
 | |
|       reference: getRectRelativeToOffsetParent(reference, await getOffsetParentFn(floating), strategy),
 | |
|       floating: {
 | |
|         x: 0,
 | |
|         y: 0,
 | |
|         ...(await getDimensionsFn(floating))
 | |
|       }
 | |
|     };
 | |
|   },
 | |
|   getClientRects: element => Array.from(element.getClientRects()),
 | |
|   isRTL: element => getComputedStyle$1(element).direction === 'rtl'
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * Automatically updates the position of the floating element when necessary.
 | |
|  * @see https://floating-ui.com/docs/autoUpdate
 | |
|  */
 | |
| function autoUpdate(reference, floating, update, options) {
 | |
|   if (options === void 0) {
 | |
|     options = {};
 | |
|   }
 | |
|   const {
 | |
|     ancestorScroll: _ancestorScroll = true,
 | |
|     ancestorResize = true,
 | |
|     elementResize = true,
 | |
|     animationFrame = false
 | |
|   } = options;
 | |
|   const ancestorScroll = _ancestorScroll && !animationFrame;
 | |
|   const ancestors = ancestorScroll || ancestorResize ? [...(isElement(reference) ? getOverflowAncestors(reference) : reference.contextElement ? getOverflowAncestors(reference.contextElement) : []), ...getOverflowAncestors(floating)] : [];
 | |
|   ancestors.forEach(ancestor => {
 | |
|     ancestorScroll && ancestor.addEventListener('scroll', update, {
 | |
|       passive: true
 | |
|     });
 | |
|     ancestorResize && ancestor.addEventListener('resize', update);
 | |
|   });
 | |
|   let observer = null;
 | |
|   if (elementResize) {
 | |
|     let initialUpdate = true;
 | |
|     observer = new ResizeObserver(() => {
 | |
|       if (!initialUpdate) {
 | |
|         update();
 | |
|       }
 | |
|       initialUpdate = false;
 | |
|     });
 | |
|     isElement(reference) && !animationFrame && observer.observe(reference);
 | |
|     if (!isElement(reference) && reference.contextElement && !animationFrame) {
 | |
|       observer.observe(reference.contextElement);
 | |
|     }
 | |
|     observer.observe(floating);
 | |
|   }
 | |
|   let frameId;
 | |
|   let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
 | |
|   if (animationFrame) {
 | |
|     frameLoop();
 | |
|   }
 | |
|   function frameLoop() {
 | |
|     const nextRefRect = getBoundingClientRect(reference);
 | |
|     if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
 | |
|       update();
 | |
|     }
 | |
|     prevRefRect = nextRefRect;
 | |
|     frameId = requestAnimationFrame(frameLoop);
 | |
|   }
 | |
|   update();
 | |
|   return () => {
 | |
|     var _observer;
 | |
|     ancestors.forEach(ancestor => {
 | |
|       ancestorScroll && ancestor.removeEventListener('scroll', update);
 | |
|       ancestorResize && ancestor.removeEventListener('resize', update);
 | |
|     });
 | |
|     (_observer = observer) == null ? void 0 : _observer.disconnect();
 | |
|     observer = null;
 | |
|     if (animationFrame) {
 | |
|       cancelAnimationFrame(frameId);
 | |
|     }
 | |
|   };
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Computes the `x` and `y` coordinates that will place the floating element
 | |
|  * next to a reference element when it is given a certain CSS positioning
 | |
|  * strategy.
 | |
|  */
 | |
| 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 { autoUpdate, computePosition, getOverflowAncestors, platform };
 |