|
|
import getOppositePlacement from '../utils/getOppositePlacement'; |
|
|
import getOppositeVariation from '../utils/getOppositeVariation'; |
|
|
import getPopperOffsets from '../utils/getPopperOffsets'; |
|
|
import runModifiers from '../utils/runModifiers'; |
|
|
import getBoundaries from '../utils/getBoundaries'; |
|
|
import isModifierEnabled from '../utils/isModifierEnabled'; |
|
|
import clockwise from '../utils/clockwise'; |
|
|
|
|
|
const BEHAVIORS = { |
|
|
FLIP: 'flip', |
|
|
CLOCKWISE: 'clockwise', |
|
|
COUNTERCLOCKWISE: 'counterclockwise', |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default function flip(data, options) { |
|
|
|
|
|
if (isModifierEnabled(data.instance.modifiers, 'inner')) { |
|
|
return data; |
|
|
} |
|
|
|
|
|
if (data.flipped && data.placement === data.originalPlacement) { |
|
|
|
|
|
return data; |
|
|
} |
|
|
|
|
|
const boundaries = getBoundaries( |
|
|
data.instance.popper, |
|
|
data.instance.reference, |
|
|
options.padding, |
|
|
options.boundariesElement, |
|
|
data.positionFixed |
|
|
); |
|
|
|
|
|
let placement = data.placement.split('-')[0]; |
|
|
let placementOpposite = getOppositePlacement(placement); |
|
|
let variation = data.placement.split('-')[1] || ''; |
|
|
|
|
|
let flipOrder = []; |
|
|
|
|
|
switch (options.behavior) { |
|
|
case BEHAVIORS.FLIP: |
|
|
flipOrder = [placement, placementOpposite]; |
|
|
break; |
|
|
case BEHAVIORS.CLOCKWISE: |
|
|
flipOrder = clockwise(placement); |
|
|
break; |
|
|
case BEHAVIORS.COUNTERCLOCKWISE: |
|
|
flipOrder = clockwise(placement, true); |
|
|
break; |
|
|
default: |
|
|
flipOrder = options.behavior; |
|
|
} |
|
|
|
|
|
flipOrder.forEach((step, index) => { |
|
|
if (placement !== step || flipOrder.length === index + 1) { |
|
|
return data; |
|
|
} |
|
|
|
|
|
placement = data.placement.split('-')[0]; |
|
|
placementOpposite = getOppositePlacement(placement); |
|
|
|
|
|
const popperOffsets = data.offsets.popper; |
|
|
const refOffsets = data.offsets.reference; |
|
|
|
|
|
|
|
|
const floor = Math.floor; |
|
|
const overlapsRef = |
|
|
(placement === 'left' && |
|
|
floor(popperOffsets.right) > floor(refOffsets.left)) || |
|
|
(placement === 'right' && |
|
|
floor(popperOffsets.left) < floor(refOffsets.right)) || |
|
|
(placement === 'top' && |
|
|
floor(popperOffsets.bottom) > floor(refOffsets.top)) || |
|
|
(placement === 'bottom' && |
|
|
floor(popperOffsets.top) < floor(refOffsets.bottom)); |
|
|
|
|
|
const overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); |
|
|
const overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); |
|
|
const overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); |
|
|
const overflowsBottom = |
|
|
floor(popperOffsets.bottom) > floor(boundaries.bottom); |
|
|
|
|
|
const overflowsBoundaries = |
|
|
(placement === 'left' && overflowsLeft) || |
|
|
(placement === 'right' && overflowsRight) || |
|
|
(placement === 'top' && overflowsTop) || |
|
|
(placement === 'bottom' && overflowsBottom); |
|
|
|
|
|
|
|
|
const isVertical = ['top', 'bottom'].indexOf(placement) !== -1; |
|
|
|
|
|
|
|
|
const flippedVariationByRef = |
|
|
!!options.flipVariations && |
|
|
((isVertical && variation === 'start' && overflowsLeft) || |
|
|
(isVertical && variation === 'end' && overflowsRight) || |
|
|
(!isVertical && variation === 'start' && overflowsTop) || |
|
|
(!isVertical && variation === 'end' && overflowsBottom)); |
|
|
|
|
|
|
|
|
const flippedVariationByContent = |
|
|
!!options.flipVariationsByContent && |
|
|
((isVertical && variation === 'start' && overflowsRight) || |
|
|
(isVertical && variation === 'end' && overflowsLeft) || |
|
|
(!isVertical && variation === 'start' && overflowsBottom) || |
|
|
(!isVertical && variation === 'end' && overflowsTop)); |
|
|
|
|
|
const flippedVariation = flippedVariationByRef || flippedVariationByContent; |
|
|
|
|
|
if (overlapsRef || overflowsBoundaries || flippedVariation) { |
|
|
|
|
|
data.flipped = true; |
|
|
|
|
|
if (overlapsRef || overflowsBoundaries) { |
|
|
placement = flipOrder[index + 1]; |
|
|
} |
|
|
|
|
|
if (flippedVariation) { |
|
|
variation = getOppositeVariation(variation); |
|
|
} |
|
|
|
|
|
data.placement = placement + (variation ? '-' + variation : ''); |
|
|
|
|
|
|
|
|
|
|
|
data.offsets.popper = { |
|
|
...data.offsets.popper, |
|
|
...getPopperOffsets( |
|
|
data.instance.popper, |
|
|
data.offsets.reference, |
|
|
data.placement |
|
|
), |
|
|
}; |
|
|
|
|
|
data = runModifiers(data.instance.modifiers, data, 'flip'); |
|
|
} |
|
|
}); |
|
|
return data; |
|
|
} |
|
|
|