floating-ui.utils.dom.esm.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. function getNodeName(node) {
  2. if (isNode(node)) {
  3. return (node.nodeName || '').toLowerCase();
  4. }
  5. // Mocked nodes in testing environments may not be instances of Node. By
  6. // returning `#document` an infinite loop won't occur.
  7. // https://github.com/floating-ui/floating-ui/issues/2317
  8. return '#document';
  9. }
  10. function getWindow(node) {
  11. var _node$ownerDocument;
  12. return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
  13. }
  14. function getDocumentElement(node) {
  15. var _ref;
  16. return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement;
  17. }
  18. function isNode(value) {
  19. return value instanceof Node || value instanceof getWindow(value).Node;
  20. }
  21. function isElement(value) {
  22. return value instanceof Element || value instanceof getWindow(value).Element;
  23. }
  24. function isHTMLElement(value) {
  25. return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement;
  26. }
  27. function isShadowRoot(value) {
  28. // Browsers without `ShadowRoot` support.
  29. if (typeof ShadowRoot === 'undefined') {
  30. return false;
  31. }
  32. return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot;
  33. }
  34. function isOverflowElement(element) {
  35. const {
  36. overflow,
  37. overflowX,
  38. overflowY,
  39. display
  40. } = getComputedStyle(element);
  41. return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display);
  42. }
  43. function isTableElement(element) {
  44. return ['table', 'td', 'th'].includes(getNodeName(element));
  45. }
  46. function isContainingBlock(element) {
  47. const webkit = isWebKit();
  48. const css = getComputedStyle(element);
  49. // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block
  50. return css.transform !== 'none' || css.perspective !== 'none' || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value));
  51. }
  52. function getContainingBlock(element) {
  53. let currentNode = getParentNode(element);
  54. while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) {
  55. if (isContainingBlock(currentNode)) {
  56. return currentNode;
  57. } else {
  58. currentNode = getParentNode(currentNode);
  59. }
  60. }
  61. return null;
  62. }
  63. function isWebKit() {
  64. if (typeof CSS === 'undefined' || !CSS.supports) return false;
  65. return CSS.supports('-webkit-backdrop-filter', 'none');
  66. }
  67. function isLastTraversableNode(node) {
  68. return ['html', 'body', '#document'].includes(getNodeName(node));
  69. }
  70. function getComputedStyle(element) {
  71. return getWindow(element).getComputedStyle(element);
  72. }
  73. function getNodeScroll(element) {
  74. if (isElement(element)) {
  75. return {
  76. scrollLeft: element.scrollLeft,
  77. scrollTop: element.scrollTop
  78. };
  79. }
  80. return {
  81. scrollLeft: element.pageXOffset,
  82. scrollTop: element.pageYOffset
  83. };
  84. }
  85. function getParentNode(node) {
  86. if (getNodeName(node) === 'html') {
  87. return node;
  88. }
  89. const result =
  90. // Step into the shadow DOM of the parent of a slotted node.
  91. node.assignedSlot ||
  92. // DOM Element detected.
  93. node.parentNode ||
  94. // ShadowRoot detected.
  95. isShadowRoot(node) && node.host ||
  96. // Fallback.
  97. getDocumentElement(node);
  98. return isShadowRoot(result) ? result.host : result;
  99. }
  100. function getNearestOverflowAncestor(node) {
  101. const parentNode = getParentNode(node);
  102. if (isLastTraversableNode(parentNode)) {
  103. return node.ownerDocument ? node.ownerDocument.body : node.body;
  104. }
  105. if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) {
  106. return parentNode;
  107. }
  108. return getNearestOverflowAncestor(parentNode);
  109. }
  110. function getOverflowAncestors(node, list, traverseIframes) {
  111. var _node$ownerDocument2;
  112. if (list === void 0) {
  113. list = [];
  114. }
  115. if (traverseIframes === void 0) {
  116. traverseIframes = true;
  117. }
  118. const scrollableAncestor = getNearestOverflowAncestor(node);
  119. const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
  120. const win = getWindow(scrollableAncestor);
  121. if (isBody) {
  122. return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], win.frameElement && traverseIframes ? getOverflowAncestors(win.frameElement) : []);
  123. }
  124. return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
  125. }
  126. export { getComputedStyle, getContainingBlock, getDocumentElement, getNearestOverflowAncestor, getNodeName, getNodeScroll, getOverflowAncestors, getParentNode, getWindow, isContainingBlock, isElement, isHTMLElement, isLastTraversableNode, isNode, isOverflowElement, isShadowRoot, isTableElement, isWebKit };