text: import getClientRect from '../utils/getClientRect';
  import getOuterSizes from '../utils/getOuterSizes';
  import isModifierRequired from '../utils/isModifierRequired';
  import getStyleComputedProperty from '../utils/getStyleComputedProperty';
  
  /**
   * @function
   * @memberof Modifiers
   * @argument {Object} data - The data object generated by update method
   * @argument {Object} options - Modifiers configuration and options
   * @returns {Object} The data object, properly modified
   */
  export default function arrow(data, options) {
    // arrow depends on keepTogether in order to work
    if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
      return data;
    }
  
    let arrowElement = options.element;
  
    // if arrowElement is a string, suppose it's a CSS selector
    if (typeof arrowElement === 'string') {
      arrowElement = data.instance.popper.querySelector(arrowElement);
  
      // if arrowElement is not found, don't run the modifier
      if (!arrowElement) {
        return data;
      }
    } else {
      // if the arrowElement isn't a query selector we must check that the
      // provided DOM node is child of its popper node
      if (!data.instance.popper.contains(arrowElement)) {
        console.warn('WARNING: `arrow.element` must be child of its popper element!');
        return data;
      }
    }
  
    const placement = data.placement.split('-')[0];
    const { popper, reference } = data.offsets;
    const isVertical = ['left', 'right'].indexOf(placement) !== -1;
  
    const len = isVertical ? 'height' : 'width';
    const sideCapitalized = isVertical ? 'Top' : 'Left';
    const side = sideCapitalized.toLowerCase();
    const altSide = isVertical ? 'left' : 'top';
    const opSide = isVertical ? 'bottom' : 'right';
    const arrowElementSize = getOuterSizes(arrowElement)[len];
  
    //
    // extends keepTogether behavior making sure the popper and its
    // reference have enough pixels in conjunction
    //
  
    // top/left side
    if (reference[opSide] - arrowElementSize < popper[side]) {
      data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
    }
    // bottom/right side
    if (reference[side] + arrowElementSize > popper[opSide]) {
      data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
    }
    data.offsets.popper = getClientRect(data.offsets.popper);
  
    // compute center of the popper
    const center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
  
    // Compute the sideValue using the updated popper offsets
    // take popper margin in account because we don't have this info available
    const css = getStyleComputedProperty(data.instance.popper);
    const popperMarginSide = parseFloat(css[`margin${sideCapitalized}`]);
    const popperBorderSide = parseFloat(css[`border${sideCapitalized}Width`]);
    let sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
  
    // prevent arrowElement from being placed not contiguously to its popper
    sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
  
    data.arrowElement = arrowElement;
    data.offsets.arrow = {
      [side]: Math.round(sideValue),
      [altSide]: '' // make sure to unset any eventual altSide value from the DOM node
    };
  
    return data;
  }
  