| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 | // @flowimport getWindow from './getWindow';import getNodeName from './getNodeName';import getComputedStyle from './getComputedStyle';import { isHTMLElement, isShadowRoot } from './instanceOf';import isTableElement from './isTableElement';import getParentNode from './getParentNode';import getUAString from '../utils/userAgent';function getTrueOffsetParent(element: Element): ?Element {  if (    !isHTMLElement(element) ||    // https://github.com/popperjs/popper-core/issues/837    getComputedStyle(element).position === 'fixed'  ) {    return null;  }  return element.offsetParent;}// `.offsetParent` reports `null` for fixed elements, while absolute elements// return the containing blockfunction getContainingBlock(element: Element) {  const isFirefox = /firefox/i.test(getUAString());  const isIE = /Trident/i.test(getUAString());  if (isIE && isHTMLElement(element)) {    // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport    const elementCss = getComputedStyle(element);    if (elementCss.position === 'fixed') {      return null;    }  }  let currentNode = getParentNode(element);  if (isShadowRoot(currentNode)) {    currentNode = currentNode.host;  }  while (    isHTMLElement(currentNode) &&    ['html', 'body'].indexOf(getNodeName(currentNode)) < 0  ) {    const css = getComputedStyle(currentNode);    // 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    if (      css.transform !== 'none' ||      css.perspective !== 'none' ||      css.contain === 'paint' ||      ['transform', 'perspective'].indexOf(css.willChange) !== -1 ||      (isFirefox && css.willChange === 'filter') ||      (isFirefox && css.filter && css.filter !== 'none')    ) {      return currentNode;    } else {      currentNode = currentNode.parentNode;    }  }  return null;}// Gets the closest ancestor positioned element. Handles some edge cases,// such as table ancestors and cross browser bugs.export default function getOffsetParent(element: Element) {  const window = getWindow(element);  let offsetParent = getTrueOffsetParent(element);  while (    offsetParent &&    isTableElement(offsetParent) &&    getComputedStyle(offsetParent).position === 'static'  ) {    offsetParent = getTrueOffsetParent(offsetParent);  }  if (    offsetParent &&    (getNodeName(offsetParent) === 'html' ||      (getNodeName(offsetParent) === 'body' &&        getComputedStyle(offsetParent).position === 'static'))  ) {    return window;  }  return offsetParent || getContainingBlock(element) || window;}
 |