| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 | // @flowimport type { State, SideObject, Padding, PositioningStrategy } from '../types';import type { Placement, Boundary, RootBoundary, Context } from '../enums';import getClippingRect from '../dom-utils/getClippingRect';import getDocumentElement from '../dom-utils/getDocumentElement';import getBoundingClientRect from '../dom-utils/getBoundingClientRect';import computeOffsets from './computeOffsets';import rectToClientRect from './rectToClientRect';import {  clippingParents,  reference,  popper,  bottom,  top,  right,  basePlacements,  viewport,} from '../enums';import { isElement } from '../dom-utils/instanceOf';import mergePaddingObject from './mergePaddingObject';import expandToHashMap from './expandToHashMap';// eslint-disable-next-line import/no-unused-modulesexport type Options = {  placement: Placement,  strategy: PositioningStrategy,  boundary: Boundary,  rootBoundary: RootBoundary,  elementContext: Context,  altBoundary: boolean,  padding: Padding,};export default function detectOverflow(  state: State,  options: $Shape<Options> = {}): SideObject {  const {    placement = state.placement,    strategy = state.strategy,    boundary = clippingParents,    rootBoundary = viewport,    elementContext = popper,    altBoundary = false,    padding = 0,  } = options;  const paddingObject = mergePaddingObject(    typeof padding !== 'number'      ? padding      : expandToHashMap(padding, basePlacements)  );  const altContext = elementContext === popper ? reference : popper;  const popperRect = state.rects.popper;  const element = state.elements[altBoundary ? altContext : elementContext];  const clippingClientRect = getClippingRect(    isElement(element)      ? element      : element.contextElement || getDocumentElement(state.elements.popper),    boundary,    rootBoundary,    strategy  );  const referenceClientRect = getBoundingClientRect(state.elements.reference);  const popperOffsets = computeOffsets({    reference: referenceClientRect,    element: popperRect,    strategy: 'absolute',    placement,  });  const popperClientRect = rectToClientRect({    ...popperRect,    ...popperOffsets,  });  const elementClientRect =    elementContext === popper ? popperClientRect : referenceClientRect;  // positive = overflowing the clipping rect  // 0 or negative = within the clipping rect  const overflowOffsets = {    top: clippingClientRect.top - elementClientRect.top + paddingObject.top,    bottom:      elementClientRect.bottom -      clippingClientRect.bottom +      paddingObject.bottom,    left: clippingClientRect.left - elementClientRect.left + paddingObject.left,    right:      elementClientRect.right - clippingClientRect.right + paddingObject.right,  };  const offsetData = state.modifiersData.offset;  // Offsets can be applied only to the popper element  if (elementContext === popper && offsetData) {    const offset = offsetData[placement];    Object.keys(overflowOffsets).forEach((key) => {      const multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;      const axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';      overflowOffsets[key] += offset[axis] * multiply;    });  }  return overflowOffsets;}
 |