floating-ui.dom.esm.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. import { rectToClientRect, autoPlacement as autoPlacement$1, shift as shift$1, flip as flip$1, size as size$1, hide as hide$1, arrow as arrow$1, inline as inline$1, limitShift as limitShift$1, computePosition as computePosition$1 } from '@floating-ui/core';
  2. export { detectOverflow, offset } from '@floating-ui/core';
  3. import { round, createCoords, max, min, floor } from '@floating-ui/utils';
  4. import { getComputedStyle, isHTMLElement, isElement, getWindow, isWebKit, getDocumentElement, getNodeName, isOverflowElement, getNodeScroll, getOverflowAncestors, getParentNode, isLastTraversableNode, isContainingBlock, isTableElement, getContainingBlock } from '@floating-ui/utils/dom';
  5. export { getOverflowAncestors } from '@floating-ui/utils/dom';
  6. function getCssDimensions(element) {
  7. const css = getComputedStyle(element);
  8. // In testing environments, the `width` and `height` properties are empty
  9. // strings for SVG elements, returning NaN. Fallback to `0` in this case.
  10. let width = parseFloat(css.width) || 0;
  11. let height = parseFloat(css.height) || 0;
  12. const hasOffset = isHTMLElement(element);
  13. const offsetWidth = hasOffset ? element.offsetWidth : width;
  14. const offsetHeight = hasOffset ? element.offsetHeight : height;
  15. const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
  16. if (shouldFallback) {
  17. width = offsetWidth;
  18. height = offsetHeight;
  19. }
  20. return {
  21. width,
  22. height,
  23. $: shouldFallback
  24. };
  25. }
  26. function unwrapElement(element) {
  27. return !isElement(element) ? element.contextElement : element;
  28. }
  29. function getScale(element) {
  30. const domElement = unwrapElement(element);
  31. if (!isHTMLElement(domElement)) {
  32. return createCoords(1);
  33. }
  34. const rect = domElement.getBoundingClientRect();
  35. const {
  36. width,
  37. height,
  38. $
  39. } = getCssDimensions(domElement);
  40. let x = ($ ? round(rect.width) : rect.width) / width;
  41. let y = ($ ? round(rect.height) : rect.height) / height;
  42. // 0, NaN, or Infinity should always fallback to 1.
  43. if (!x || !Number.isFinite(x)) {
  44. x = 1;
  45. }
  46. if (!y || !Number.isFinite(y)) {
  47. y = 1;
  48. }
  49. return {
  50. x,
  51. y
  52. };
  53. }
  54. const noOffsets = /*#__PURE__*/createCoords(0);
  55. function getVisualOffsets(element) {
  56. const win = getWindow(element);
  57. if (!isWebKit() || !win.visualViewport) {
  58. return noOffsets;
  59. }
  60. return {
  61. x: win.visualViewport.offsetLeft,
  62. y: win.visualViewport.offsetTop
  63. };
  64. }
  65. function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
  66. if (isFixed === void 0) {
  67. isFixed = false;
  68. }
  69. if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) {
  70. return false;
  71. }
  72. return isFixed;
  73. }
  74. function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
  75. if (includeScale === void 0) {
  76. includeScale = false;
  77. }
  78. if (isFixedStrategy === void 0) {
  79. isFixedStrategy = false;
  80. }
  81. const clientRect = element.getBoundingClientRect();
  82. const domElement = unwrapElement(element);
  83. let scale = createCoords(1);
  84. if (includeScale) {
  85. if (offsetParent) {
  86. if (isElement(offsetParent)) {
  87. scale = getScale(offsetParent);
  88. }
  89. } else {
  90. scale = getScale(element);
  91. }
  92. }
  93. const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
  94. let x = (clientRect.left + visualOffsets.x) / scale.x;
  95. let y = (clientRect.top + visualOffsets.y) / scale.y;
  96. let width = clientRect.width / scale.x;
  97. let height = clientRect.height / scale.y;
  98. if (domElement) {
  99. const win = getWindow(domElement);
  100. const offsetWin = offsetParent && isElement(offsetParent) ? getWindow(offsetParent) : offsetParent;
  101. let currentWin = win;
  102. let currentIFrame = currentWin.frameElement;
  103. while (currentIFrame && offsetParent && offsetWin !== currentWin) {
  104. const iframeScale = getScale(currentIFrame);
  105. const iframeRect = currentIFrame.getBoundingClientRect();
  106. const css = getComputedStyle(currentIFrame);
  107. const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
  108. const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
  109. x *= iframeScale.x;
  110. y *= iframeScale.y;
  111. width *= iframeScale.x;
  112. height *= iframeScale.y;
  113. x += left;
  114. y += top;
  115. currentWin = getWindow(currentIFrame);
  116. currentIFrame = currentWin.frameElement;
  117. }
  118. }
  119. return rectToClientRect({
  120. width,
  121. height,
  122. x,
  123. y
  124. });
  125. }
  126. const topLayerSelectors = [':popover-open', ':modal'];
  127. function isTopLayer(floating) {
  128. return topLayerSelectors.some(selector => {
  129. try {
  130. return floating.matches(selector);
  131. } catch (e) {
  132. return false;
  133. }
  134. });
  135. }
  136. function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) {
  137. let {
  138. elements,
  139. rect,
  140. offsetParent,
  141. strategy
  142. } = _ref;
  143. const isFixed = strategy === 'fixed';
  144. const documentElement = getDocumentElement(offsetParent);
  145. const topLayer = elements ? isTopLayer(elements.floating) : false;
  146. if (offsetParent === documentElement || topLayer && isFixed) {
  147. return rect;
  148. }
  149. let scroll = {
  150. scrollLeft: 0,
  151. scrollTop: 0
  152. };
  153. let scale = createCoords(1);
  154. const offsets = createCoords(0);
  155. const isOffsetParentAnElement = isHTMLElement(offsetParent);
  156. if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
  157. if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
  158. scroll = getNodeScroll(offsetParent);
  159. }
  160. if (isHTMLElement(offsetParent)) {
  161. const offsetRect = getBoundingClientRect(offsetParent);
  162. scale = getScale(offsetParent);
  163. offsets.x = offsetRect.x + offsetParent.clientLeft;
  164. offsets.y = offsetRect.y + offsetParent.clientTop;
  165. }
  166. }
  167. return {
  168. width: rect.width * scale.x,
  169. height: rect.height * scale.y,
  170. x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x,
  171. y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y
  172. };
  173. }
  174. function getClientRects(element) {
  175. return Array.from(element.getClientRects());
  176. }
  177. function getWindowScrollBarX(element) {
  178. // If <html> has a CSS width greater than the viewport, then this will be
  179. // incorrect for RTL.
  180. return getBoundingClientRect(getDocumentElement(element)).left + getNodeScroll(element).scrollLeft;
  181. }
  182. // Gets the entire size of the scrollable document area, even extending outside
  183. // of the `<html>` and `<body>` rect bounds if horizontally scrollable.
  184. function getDocumentRect(element) {
  185. const html = getDocumentElement(element);
  186. const scroll = getNodeScroll(element);
  187. const body = element.ownerDocument.body;
  188. const width = max(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth);
  189. const height = max(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight);
  190. let x = -scroll.scrollLeft + getWindowScrollBarX(element);
  191. const y = -scroll.scrollTop;
  192. if (getComputedStyle(body).direction === 'rtl') {
  193. x += max(html.clientWidth, body.clientWidth) - width;
  194. }
  195. return {
  196. width,
  197. height,
  198. x,
  199. y
  200. };
  201. }
  202. function getViewportRect(element, strategy) {
  203. const win = getWindow(element);
  204. const html = getDocumentElement(element);
  205. const visualViewport = win.visualViewport;
  206. let width = html.clientWidth;
  207. let height = html.clientHeight;
  208. let x = 0;
  209. let y = 0;
  210. if (visualViewport) {
  211. width = visualViewport.width;
  212. height = visualViewport.height;
  213. const visualViewportBased = isWebKit();
  214. if (!visualViewportBased || visualViewportBased && strategy === 'fixed') {
  215. x = visualViewport.offsetLeft;
  216. y = visualViewport.offsetTop;
  217. }
  218. }
  219. return {
  220. width,
  221. height,
  222. x,
  223. y
  224. };
  225. }
  226. // Returns the inner client rect, subtracting scrollbars if present.
  227. function getInnerBoundingClientRect(element, strategy) {
  228. const clientRect = getBoundingClientRect(element, true, strategy === 'fixed');
  229. const top = clientRect.top + element.clientTop;
  230. const left = clientRect.left + element.clientLeft;
  231. const scale = isHTMLElement(element) ? getScale(element) : createCoords(1);
  232. const width = element.clientWidth * scale.x;
  233. const height = element.clientHeight * scale.y;
  234. const x = left * scale.x;
  235. const y = top * scale.y;
  236. return {
  237. width,
  238. height,
  239. x,
  240. y
  241. };
  242. }
  243. function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
  244. let rect;
  245. if (clippingAncestor === 'viewport') {
  246. rect = getViewportRect(element, strategy);
  247. } else if (clippingAncestor === 'document') {
  248. rect = getDocumentRect(getDocumentElement(element));
  249. } else if (isElement(clippingAncestor)) {
  250. rect = getInnerBoundingClientRect(clippingAncestor, strategy);
  251. } else {
  252. const visualOffsets = getVisualOffsets(element);
  253. rect = {
  254. ...clippingAncestor,
  255. x: clippingAncestor.x - visualOffsets.x,
  256. y: clippingAncestor.y - visualOffsets.y
  257. };
  258. }
  259. return rectToClientRect(rect);
  260. }
  261. function hasFixedPositionAncestor(element, stopNode) {
  262. const parentNode = getParentNode(element);
  263. if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
  264. return false;
  265. }
  266. return getComputedStyle(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode);
  267. }
  268. // A "clipping ancestor" is an `overflow` element with the characteristic of
  269. // clipping (or hiding) child elements. This returns all clipping ancestors
  270. // of the given element up the tree.
  271. function getClippingElementAncestors(element, cache) {
  272. const cachedResult = cache.get(element);
  273. if (cachedResult) {
  274. return cachedResult;
  275. }
  276. let result = getOverflowAncestors(element, [], false).filter(el => isElement(el) && getNodeName(el) !== 'body');
  277. let currentContainingBlockComputedStyle = null;
  278. const elementIsFixed = getComputedStyle(element).position === 'fixed';
  279. let currentNode = elementIsFixed ? getParentNode(element) : element;
  280. // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
  281. while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
  282. const computedStyle = getComputedStyle(currentNode);
  283. const currentNodeIsContaining = isContainingBlock(currentNode);
  284. if (!currentNodeIsContaining && computedStyle.position === 'fixed') {
  285. currentContainingBlockComputedStyle = null;
  286. }
  287. const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
  288. if (shouldDropCurrentNode) {
  289. // Drop non-containing blocks.
  290. result = result.filter(ancestor => ancestor !== currentNode);
  291. } else {
  292. // Record last containing block for next iteration.
  293. currentContainingBlockComputedStyle = computedStyle;
  294. }
  295. currentNode = getParentNode(currentNode);
  296. }
  297. cache.set(element, result);
  298. return result;
  299. }
  300. // Gets the maximum area that the element is visible in due to any number of
  301. // clipping ancestors.
  302. function getClippingRect(_ref) {
  303. let {
  304. element,
  305. boundary,
  306. rootBoundary,
  307. strategy
  308. } = _ref;
  309. const elementClippingAncestors = boundary === 'clippingAncestors' ? getClippingElementAncestors(element, this._c) : [].concat(boundary);
  310. const clippingAncestors = [...elementClippingAncestors, rootBoundary];
  311. const firstClippingAncestor = clippingAncestors[0];
  312. const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => {
  313. const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy);
  314. accRect.top = max(rect.top, accRect.top);
  315. accRect.right = min(rect.right, accRect.right);
  316. accRect.bottom = min(rect.bottom, accRect.bottom);
  317. accRect.left = max(rect.left, accRect.left);
  318. return accRect;
  319. }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy));
  320. return {
  321. width: clippingRect.right - clippingRect.left,
  322. height: clippingRect.bottom - clippingRect.top,
  323. x: clippingRect.left,
  324. y: clippingRect.top
  325. };
  326. }
  327. function getDimensions(element) {
  328. const {
  329. width,
  330. height
  331. } = getCssDimensions(element);
  332. return {
  333. width,
  334. height
  335. };
  336. }
  337. function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
  338. const isOffsetParentAnElement = isHTMLElement(offsetParent);
  339. const documentElement = getDocumentElement(offsetParent);
  340. const isFixed = strategy === 'fixed';
  341. const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
  342. let scroll = {
  343. scrollLeft: 0,
  344. scrollTop: 0
  345. };
  346. const offsets = createCoords(0);
  347. if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
  348. if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) {
  349. scroll = getNodeScroll(offsetParent);
  350. }
  351. if (isOffsetParentAnElement) {
  352. const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
  353. offsets.x = offsetRect.x + offsetParent.clientLeft;
  354. offsets.y = offsetRect.y + offsetParent.clientTop;
  355. } else if (documentElement) {
  356. offsets.x = getWindowScrollBarX(documentElement);
  357. }
  358. }
  359. const x = rect.left + scroll.scrollLeft - offsets.x;
  360. const y = rect.top + scroll.scrollTop - offsets.y;
  361. return {
  362. x,
  363. y,
  364. width: rect.width,
  365. height: rect.height
  366. };
  367. }
  368. function getTrueOffsetParent(element, polyfill) {
  369. if (!isHTMLElement(element) || getComputedStyle(element).position === 'fixed') {
  370. return null;
  371. }
  372. if (polyfill) {
  373. return polyfill(element);
  374. }
  375. return element.offsetParent;
  376. }
  377. // Gets the closest ancestor positioned element. Handles some edge cases,
  378. // such as table ancestors and cross browser bugs.
  379. function getOffsetParent(element, polyfill) {
  380. const window = getWindow(element);
  381. if (!isHTMLElement(element) || isTopLayer(element)) {
  382. return window;
  383. }
  384. let offsetParent = getTrueOffsetParent(element, polyfill);
  385. while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
  386. offsetParent = getTrueOffsetParent(offsetParent, polyfill);
  387. }
  388. if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static' && !isContainingBlock(offsetParent))) {
  389. return window;
  390. }
  391. return offsetParent || getContainingBlock(element) || window;
  392. }
  393. const getElementRects = async function (data) {
  394. const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
  395. const getDimensionsFn = this.getDimensions;
  396. return {
  397. reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
  398. floating: {
  399. x: 0,
  400. y: 0,
  401. ...(await getDimensionsFn(data.floating))
  402. }
  403. };
  404. };
  405. function isRTL(element) {
  406. return getComputedStyle(element).direction === 'rtl';
  407. }
  408. const platform = {
  409. convertOffsetParentRelativeRectToViewportRelativeRect,
  410. getDocumentElement,
  411. getClippingRect,
  412. getOffsetParent,
  413. getElementRects,
  414. getClientRects,
  415. getDimensions,
  416. getScale,
  417. isElement,
  418. isRTL
  419. };
  420. // https://samthor.au/2021/observing-dom/
  421. function observeMove(element, onMove) {
  422. let io = null;
  423. let timeoutId;
  424. const root = getDocumentElement(element);
  425. function cleanup() {
  426. var _io;
  427. clearTimeout(timeoutId);
  428. (_io = io) == null || _io.disconnect();
  429. io = null;
  430. }
  431. function refresh(skip, threshold) {
  432. if (skip === void 0) {
  433. skip = false;
  434. }
  435. if (threshold === void 0) {
  436. threshold = 1;
  437. }
  438. cleanup();
  439. const {
  440. left,
  441. top,
  442. width,
  443. height
  444. } = element.getBoundingClientRect();
  445. if (!skip) {
  446. onMove();
  447. }
  448. if (!width || !height) {
  449. return;
  450. }
  451. const insetTop = floor(top);
  452. const insetRight = floor(root.clientWidth - (left + width));
  453. const insetBottom = floor(root.clientHeight - (top + height));
  454. const insetLeft = floor(left);
  455. const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
  456. const options = {
  457. rootMargin,
  458. threshold: max(0, min(1, threshold)) || 1
  459. };
  460. let isFirstUpdate = true;
  461. function handleObserve(entries) {
  462. const ratio = entries[0].intersectionRatio;
  463. if (ratio !== threshold) {
  464. if (!isFirstUpdate) {
  465. return refresh();
  466. }
  467. if (!ratio) {
  468. timeoutId = setTimeout(() => {
  469. refresh(false, 1e-7);
  470. }, 100);
  471. } else {
  472. refresh(false, ratio);
  473. }
  474. }
  475. isFirstUpdate = false;
  476. }
  477. // Older browsers don't support a `document` as the root and will throw an
  478. // error.
  479. try {
  480. io = new IntersectionObserver(handleObserve, {
  481. ...options,
  482. // Handle <iframe>s
  483. root: root.ownerDocument
  484. });
  485. } catch (e) {
  486. io = new IntersectionObserver(handleObserve, options);
  487. }
  488. io.observe(element);
  489. }
  490. refresh(true);
  491. return cleanup;
  492. }
  493. /**
  494. * Automatically updates the position of the floating element when necessary.
  495. * Should only be called when the floating element is mounted on the DOM or
  496. * visible on the screen.
  497. * @returns cleanup function that should be invoked when the floating element is
  498. * removed from the DOM or hidden from the screen.
  499. * @see https://floating-ui.com/docs/autoUpdate
  500. */
  501. function autoUpdate(reference, floating, update, options) {
  502. if (options === void 0) {
  503. options = {};
  504. }
  505. const {
  506. ancestorScroll = true,
  507. ancestorResize = true,
  508. elementResize = typeof ResizeObserver === 'function',
  509. layoutShift = typeof IntersectionObserver === 'function',
  510. animationFrame = false
  511. } = options;
  512. const referenceEl = unwrapElement(reference);
  513. const ancestors = ancestorScroll || ancestorResize ? [...(referenceEl ? getOverflowAncestors(referenceEl) : []), ...getOverflowAncestors(floating)] : [];
  514. ancestors.forEach(ancestor => {
  515. ancestorScroll && ancestor.addEventListener('scroll', update, {
  516. passive: true
  517. });
  518. ancestorResize && ancestor.addEventListener('resize', update);
  519. });
  520. const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
  521. let reobserveFrame = -1;
  522. let resizeObserver = null;
  523. if (elementResize) {
  524. resizeObserver = new ResizeObserver(_ref => {
  525. let [firstEntry] = _ref;
  526. if (firstEntry && firstEntry.target === referenceEl && resizeObserver) {
  527. // Prevent update loops when using the `size` middleware.
  528. // https://github.com/floating-ui/floating-ui/issues/1740
  529. resizeObserver.unobserve(floating);
  530. cancelAnimationFrame(reobserveFrame);
  531. reobserveFrame = requestAnimationFrame(() => {
  532. var _resizeObserver;
  533. (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
  534. });
  535. }
  536. update();
  537. });
  538. if (referenceEl && !animationFrame) {
  539. resizeObserver.observe(referenceEl);
  540. }
  541. resizeObserver.observe(floating);
  542. }
  543. let frameId;
  544. let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
  545. if (animationFrame) {
  546. frameLoop();
  547. }
  548. function frameLoop() {
  549. const nextRefRect = getBoundingClientRect(reference);
  550. if (prevRefRect && (nextRefRect.x !== prevRefRect.x || nextRefRect.y !== prevRefRect.y || nextRefRect.width !== prevRefRect.width || nextRefRect.height !== prevRefRect.height)) {
  551. update();
  552. }
  553. prevRefRect = nextRefRect;
  554. frameId = requestAnimationFrame(frameLoop);
  555. }
  556. update();
  557. return () => {
  558. var _resizeObserver2;
  559. ancestors.forEach(ancestor => {
  560. ancestorScroll && ancestor.removeEventListener('scroll', update);
  561. ancestorResize && ancestor.removeEventListener('resize', update);
  562. });
  563. cleanupIo == null || cleanupIo();
  564. (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
  565. resizeObserver = null;
  566. if (animationFrame) {
  567. cancelAnimationFrame(frameId);
  568. }
  569. };
  570. }
  571. /**
  572. * Optimizes the visibility of the floating element by choosing the placement
  573. * that has the most space available automatically, without needing to specify a
  574. * preferred placement. Alternative to `flip`.
  575. * @see https://floating-ui.com/docs/autoPlacement
  576. */
  577. const autoPlacement = autoPlacement$1;
  578. /**
  579. * Optimizes the visibility of the floating element by shifting it in order to
  580. * keep it in view when it will overflow the clipping boundary.
  581. * @see https://floating-ui.com/docs/shift
  582. */
  583. const shift = shift$1;
  584. /**
  585. * Optimizes the visibility of the floating element by flipping the `placement`
  586. * in order to keep it in view when the preferred placement(s) will overflow the
  587. * clipping boundary. Alternative to `autoPlacement`.
  588. * @see https://floating-ui.com/docs/flip
  589. */
  590. const flip = flip$1;
  591. /**
  592. * Provides data that allows you to change the size of the floating element —
  593. * for instance, prevent it from overflowing the clipping boundary or match the
  594. * width of the reference element.
  595. * @see https://floating-ui.com/docs/size
  596. */
  597. const size = size$1;
  598. /**
  599. * Provides data to hide the floating element in applicable situations, such as
  600. * when it is not in the same clipping context as the reference element.
  601. * @see https://floating-ui.com/docs/hide
  602. */
  603. const hide = hide$1;
  604. /**
  605. * Provides data to position an inner element of the floating element so that it
  606. * appears centered to the reference element.
  607. * @see https://floating-ui.com/docs/arrow
  608. */
  609. const arrow = arrow$1;
  610. /**
  611. * Provides improved positioning for inline reference elements that can span
  612. * over multiple lines, such as hyperlinks or range selections.
  613. * @see https://floating-ui.com/docs/inline
  614. */
  615. const inline = inline$1;
  616. /**
  617. * Built-in `limiter` that will stop `shift()` at a certain point.
  618. */
  619. const limitShift = limitShift$1;
  620. /**
  621. * Computes the `x` and `y` coordinates that will place the floating element
  622. * next to a given reference element.
  623. */
  624. const computePosition = (reference, floating, options) => {
  625. // This caches the expensive `getClippingElementAncestors` function so that
  626. // multiple lifecycle resets re-use the same result. It only lives for a
  627. // single call. If other functions become expensive, we can add them as well.
  628. const cache = new Map();
  629. const mergedOptions = {
  630. platform,
  631. ...options
  632. };
  633. const platformWithCache = {
  634. ...mergedOptions.platform,
  635. _c: cache
  636. };
  637. return computePosition$1(reference, floating, {
  638. ...mergedOptions,
  639. platform: platformWithCache
  640. });
  641. };
  642. export { arrow, autoPlacement, autoUpdate, computePosition, flip, hide, inline, limitShift, platform, shift, size };