| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 | // @flowimport type { Placement, Boundary, RootBoundary } from '../enums';import type { ModifierArguments, Modifier, Padding } from '../types';import getOppositePlacement from '../utils/getOppositePlacement';import getBasePlacement from '../utils/getBasePlacement';import getOppositeVariationPlacement from '../utils/getOppositeVariationPlacement';import detectOverflow from '../utils/detectOverflow';import computeAutoPlacement from '../utils/computeAutoPlacement';import { bottom, top, start, right, left, auto } from '../enums';import getVariation from '../utils/getVariation';// eslint-disable-next-line import/no-unused-modulesexport type Options = {  mainAxis: boolean,  altAxis: boolean,  fallbackPlacements: Array<Placement>,  padding: Padding,  boundary: Boundary,  rootBoundary: RootBoundary,  altBoundary: boolean,  flipVariations: boolean,  allowedAutoPlacements: Array<Placement>,};function getExpandedFallbackPlacements(placement: Placement): Array<Placement> {  if (getBasePlacement(placement) === auto) {    return [];  }  const oppositePlacement = getOppositePlacement(placement);  return [    getOppositeVariationPlacement(placement),    oppositePlacement,    getOppositeVariationPlacement(oppositePlacement),  ];}function flip({ state, options, name }: ModifierArguments<Options>) {  if (state.modifiersData[name]._skip) {    return;  }  const {    mainAxis: checkMainAxis = true,    altAxis: checkAltAxis = true,    fallbackPlacements: specifiedFallbackPlacements,    padding,    boundary,    rootBoundary,    altBoundary,    flipVariations = true,    allowedAutoPlacements,  } = options;  const preferredPlacement = state.options.placement;  const basePlacement = getBasePlacement(preferredPlacement);  const isBasePlacement = basePlacement === preferredPlacement;  const fallbackPlacements =    specifiedFallbackPlacements ||    (isBasePlacement || !flipVariations      ? [getOppositePlacement(preferredPlacement)]      : getExpandedFallbackPlacements(preferredPlacement));  const placements = [preferredPlacement, ...fallbackPlacements].reduce(    (acc, placement) => {      return acc.concat(        getBasePlacement(placement) === auto          ? computeAutoPlacement(state, {              placement,              boundary,              rootBoundary,              padding,              flipVariations,              allowedAutoPlacements,            })          : placement      );    },    []  );  const referenceRect = state.rects.reference;  const popperRect = state.rects.popper;  const checksMap = new Map();  let makeFallbackChecks = true;  let firstFittingPlacement = placements[0];  for (let i = 0; i < placements.length; i++) {    const placement = placements[i];    const basePlacement = getBasePlacement(placement);    const isStartVariation = getVariation(placement) === start;    const isVertical = [top, bottom].indexOf(basePlacement) >= 0;    const len = isVertical ? 'width' : 'height';    const overflow = detectOverflow(state, {      placement,      boundary,      rootBoundary,      altBoundary,      padding,    });    let mainVariationSide: any = isVertical      ? isStartVariation        ? right        : left      : isStartVariation      ? bottom      : top;    if (referenceRect[len] > popperRect[len]) {      mainVariationSide = getOppositePlacement(mainVariationSide);    }    const altVariationSide: any = getOppositePlacement(mainVariationSide);    const checks = [];    if (checkMainAxis) {      checks.push(overflow[basePlacement] <= 0);    }    if (checkAltAxis) {      checks.push(        overflow[mainVariationSide] <= 0,        overflow[altVariationSide] <= 0      );    }    if (checks.every((check) => check)) {      firstFittingPlacement = placement;      makeFallbackChecks = false;      break;    }    checksMap.set(placement, checks);  }  if (makeFallbackChecks) {    // `2` may be desired in some cases – research later    const numberOfChecks = flipVariations ? 3 : 1;    for (let i = numberOfChecks; i > 0; i--) {      const fittingPlacement = placements.find((placement) => {        const checks = checksMap.get(placement);        if (checks) {          return checks.slice(0, i).every((check) => check);        }      });      if (fittingPlacement) {        firstFittingPlacement = fittingPlacement;        break;      }    }  }  if (state.placement !== firstFittingPlacement) {    state.modifiersData[name]._skip = true;    state.placement = firstFittingPlacement;    state.reset = true;  }}// eslint-disable-next-line import/no-unused-modulesexport type FlipModifier = Modifier<'flip', Options>;export default ({  name: 'flip',  enabled: true,  phase: 'main',  fn: flip,  requiresIfExists: ['offset'],  data: { _skip: false },}: FlipModifier);
 |