import PopperJS from "popper.js" ; /** Converts a full placement to one of the four positions by stripping text after the `-`. */ export function getPosition ( placement ) { return placement . split ( "-" ) [ 0 ] as PopperJS . Position ; } /** Returns true if position is left or right. */ export function isVerticalPosition ( side ) { return [ "left" , "right" ] . indexOf ( side ) !== - 1 ; } /** Returns the opposite position. */ export function getOppositePosition ( side ) { switch ( side ) { case "top" : return "bottom" ; case "left" : return "right" ; case "bottom" : return "top" ; default : return "left" ; } } /** Returns the CSS alignment keyword corresponding to given placement. */ export function getAlignment ( placement ) { const align = placement . split ( "-" ) [ 1 ] as "start" | "end" | undefined ; switch ( align ) { case "start" : return "left" ; case "end" : return "right" ; default : return "center" ; } } /** Modifier helper function to compute popper transform-origin based on arrow position */ export function getTransformOrigin ( data ) { const position = getPosition ( data . placement ) ; if ( data . arrowElement == null ) { return isVerticalPosition ( position ) ? `${ getOppositePosition ( position ) } ${ getAlignment ( position ) }` : `${ getAlignment ( position ) } ${ getOppositePosition ( position ) }` ; } else { const arrowSizeShift = data . arrowElement . clientHeight / 2 ; const { arrow } = data . offsets ; return isVerticalPosition ( position ) ? `${ getOppositePosition ( position ) } ${ arrow . top + arrowSizeShift }px` : `${ arrow . left + arrowSizeShift }px ${ getOppositePosition ( position ) }` ; } } const ARROW_SPACING = 4 ; /** Popper modifier that offsets popper and arrow so arrow points out of the correct side */ export const arrowOffsetModifier = data => { if ( data . arrowElement == null ) { return data ; } const arrowSize = data . arrowElement . clientWidth ; const position = getPosition ( data . placement ) ; const isVertical = isVerticalPosition ( position ) ; const len = isVertical ? "width" : "height" ; const offsetSide = isVertical ? "left" : "top" ; const arrowOffsetSize = Math . round ( arrowSize / 2 / Math . sqrt ( 2 ) ) ; if ( position === "top" || position === "left" ) { data . offsets . popper [ offsetSide ] -= arrowOffsetSize + ARROW_SPACING ; data . offsets . arrow [ offsetSide ] = data . offsets . popper [ len ] - arrowSize + arrowOffsetSize ; } else { data . offsets . popper [ offsetSide ] += arrowOffsetSize + ARROW_SPACING ; data . offsets . arrow [ offsetSide ] = - arrowOffsetSize ; } return data ; } ;