floating-ui.utils.dom.umd.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.FloatingUIUtilsDOM = {}));
  5. })(this, (function (exports) { 'use strict';
  6. function hasWindow() {
  7. return typeof window !== 'undefined';
  8. }
  9. function getNodeName(node) {
  10. if (isNode(node)) {
  11. return (node.nodeName || '').toLowerCase();
  12. }
  13. // Mocked nodes in testing environments may not be instances of Node. By
  14. // returning `#document` an infinite loop won't occur.
  15. // https://github.com/floating-ui/floating-ui/issues/2317
  16. return '#document';
  17. }
  18. function getWindow(node) {
  19. var _node$ownerDocument;
  20. return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
  21. }
  22. function getDocumentElement(node) {
  23. var _ref;
  24. return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
  25. }
  26. function isNode(value) {
  27. if (!hasWindow()) {
  28. return false;
  29. }
  30. return value instanceof Node || value instanceof getWindow(value).Node;
  31. }
  32. function isElement(value) {
  33. if (!hasWindow()) {
  34. return false;
  35. }
  36. return value instanceof Element || value instanceof getWindow(value).Element;
  37. }
  38. function isHTMLElement(value) {
  39. if (!hasWindow()) {
  40. return false;
  41. }
  42. return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
  43. }
  44. function isShadowRoot(value) {
  45. if (!hasWindow() || typeof ShadowRoot === 'undefined') {
  46. return false;
  47. }
  48. return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
  49. }
  50. const invalidOverflowDisplayValues = /*#__PURE__*/new Set(['inline', 'contents']);
  51. function isOverflowElement(element) {
  52. const {
  53. overflow,
  54. overflowX,
  55. overflowY,
  56. display
  57. } = getComputedStyle(element);
  58. return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !invalidOverflowDisplayValues.has(display);
  59. }
  60. const tableElements = /*#__PURE__*/new Set(['table', 'td', 'th']);
  61. function isTableElement(element) {
  62. return tableElements.has(getNodeName(element));
  63. }
  64. const topLayerSelectors = [':popover-open', ':modal'];
  65. function isTopLayer(element) {
  66. return topLayerSelectors.some(selector => {
  67. try {
  68. return element.matches(selector);
  69. } catch (_e) {
  70. return false;
  71. }
  72. });
  73. }
  74. const transformProperties = ['transform', 'translate', 'scale', 'rotate', 'perspective'];
  75. const willChangeValues = ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'];
  76. const containValues = ['paint', 'layout', 'strict', 'content'];
  77. function isContainingBlock(elementOrCss) {
  78. const webkit = isWebKit();
  79. const css = isElement(elementOrCss) ? getComputedStyle(elementOrCss) : elementOrCss;
  80. // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
  81. // https://drafts.csswg.org/css-transforms-2/#individual-transforms
  82. return transformProperties.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) || willChangeValues.some(value => (css.willChange || '').includes(value)) || containValues.some(value => (css.contain || '').includes(value));
  83. }
  84. function getContainingBlock(element) {
  85. let currentNode = getParentNode(element);
  86. while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
  87. if (isContainingBlock(currentNode)) {
  88. return currentNode;
  89. } else if (isTopLayer(currentNode)) {
  90. return null;
  91. }
  92. currentNode = getParentNode(currentNode);
  93. }
  94. return null;
  95. }
  96. function isWebKit() {
  97. if (typeof CSS === 'undefined' || !CSS.supports) return false;
  98. return CSS.supports('-webkit-backdrop-filter', 'none');
  99. }
  100. const lastTraversableNodeNames = /*#__PURE__*/new Set(['html', 'body', '#document']);
  101. function isLastTraversableNode(node) {
  102. return lastTraversableNodeNames.has(getNodeName(node));
  103. }
  104. function getComputedStyle(element) {
  105. return getWindow(element).getComputedStyle(element);
  106. }
  107. function getNodeScroll(element) {
  108. if (isElement(element)) {
  109. return {
  110. scrollLeft: element.scrollLeft,
  111. scrollTop: element.scrollTop
  112. };
  113. }
  114. return {
  115. scrollLeft: element.scrollX,
  116. scrollTop: element.scrollY
  117. };
  118. }
  119. function getParentNode(node) {
  120. if (getNodeName(node) === 'html') {
  121. return node;
  122. }
  123. const result =
  124. // Step into the shadow DOM of the parent of a slotted node.
  125. node.assignedSlot ||
  126. // DOM Element detected.
  127. node.parentNode ||
  128. // ShadowRoot detected.
  129. isShadowRoot(node) && node.host ||
  130. // Fallback.
  131. getDocumentElement(node);
  132. return isShadowRoot(result) ? result.host : result;
  133. }
  134. function getNearestOverflowAncestor(node) {
  135. const parentNode = getParentNode(node);
  136. if (isLastTraversableNode(parentNode)) {
  137. return node.ownerDocument ? node.ownerDocument.body : node.body;
  138. }
  139. if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
  140. return parentNode;
  141. }
  142. return getNearestOverflowAncestor(parentNode);
  143. }
  144. function getOverflowAncestors(node, list, traverseIframes) {
  145. var _node$ownerDocument2;
  146. if (list === void 0) {
  147. list = [];
  148. }
  149. if (traverseIframes === void 0) {
  150. traverseIframes = true;
  151. }
  152. const scrollableAncestor = getNearestOverflowAncestor(node);
  153. const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
  154. const win = getWindow(scrollableAncestor);
  155. if (isBody) {
  156. const frameElement = getFrameElement(win);
  157. return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
  158. }
  159. return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
  160. }
  161. function getFrameElement(win) {
  162. return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
  163. }
  164. exports.getComputedStyle = getComputedStyle;
  165. exports.getContainingBlock = getContainingBlock;
  166. exports.getDocumentElement = getDocumentElement;
  167. exports.getFrameElement = getFrameElement;
  168. exports.getNearestOverflowAncestor = getNearestOverflowAncestor;
  169. exports.getNodeName = getNodeName;
  170. exports.getNodeScroll = getNodeScroll;
  171. exports.getOverflowAncestors = getOverflowAncestors;
  172. exports.getParentNode = getParentNode;
  173. exports.getWindow = getWindow;
  174. exports.isContainingBlock = isContainingBlock;
  175. exports.isElement = isElement;
  176. exports.isHTMLElement = isHTMLElement;
  177. exports.isLastTraversableNode = isLastTraversableNode;
  178. exports.isNode = isNode;
  179. exports.isOverflowElement = isOverflowElement;
  180. exports.isShadowRoot = isShadowRoot;
  181. exports.isTableElement = isTableElement;
  182. exports.isTopLayer = isTopLayer;
  183. exports.isWebKit = isWebKit;
  184. }));