/*!
* Tippy.js v2.5.3
* (c) 2017-2018 atomiks
* MIT
*/
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('popper.js')) :
	typeof define === 'function' && define.amd ? define(['popper.js'], factory) :
	(global.tippy = factory(global.Popper));
}(this, (function (Popper) { 'use strict';

Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;

var version = "2.5.3";

var isBrowser = typeof window !== 'undefined';

var isIE = isBrowser && /MSIE |Trident\//.test(navigator.userAgent);

var browser = {};

if (isBrowser) {
  browser.supported = 'requestAnimationFrame' in window;
  browser.supportsTouch = 'ontouchstart' in window;
  browser.usingTouch = false;
  browser.dynamicInputDetection = true;
  browser.iOS = /iPhone|iPad|iPod/.test(navigator.platform) && !window.MSStream;
  browser.onUserInputChange = function () {};
}

/**
 * Selector constants used for grabbing elements
 */
var selectors = {
  POPPER: '.tippy-popper',
  TOOLTIP: '.tippy-tooltip',
  CONTENT: '.tippy-content',
  BACKDROP: '.tippy-backdrop',
  ARROW: '.tippy-arrow',
  ROUND_ARROW: '.tippy-roundarrow',
  REFERENCE: '[data-tippy]'
};

var defaults = {
  placement: 'top',
  livePlacement: true,
  trigger: 'mouseenter focus',
  animation: 'shift-away',
  html: false,
  animateFill: true,
  arrow: false,
  delay: 0,
  duration: [350, 300],
  interactive: false,
  interactiveBorder: 2,
  theme: 'dark',
  size: 'regular',
  distance: 10,
  offset: 0,
  hideOnClick: true,
  multiple: false,
  followCursor: false,
  inertia: false,
  updateDuration: 350,
  sticky: false,
  appendTo: function appendTo() {
    return document.body;
  },
  zIndex: 9999,
  touchHold: false,
  performance: false,
  dynamicTitle: false,
  flip: true,
  flipBehavior: 'flip',
  arrowType: 'sharp',
  arrowTransform: '',
  maxWidth: '',
  target: null,
  allowTitleHTML: true,
  popperOptions: {},
  createPopperInstanceOnInit: false,
  onShow: function onShow() {},
  onShown: function onShown() {},
  onHide: function onHide() {},
  onHidden: function onHidden() {}
};

/**
 * The keys of the defaults object for reducing down into a new object
 * Used in `getIndividualOptions()`
 */
var defaultsKeys = browser.supported && Object.keys(defaults);

/**
 * Determines if a value is an object literal
 * @param {*} value
 * @return {Boolean}
 */
function isObjectLiteral(value) {
  return {}.toString.call(value) === '[object Object]';
}

/**
 * Ponyfill for Array.from
 * @param {*} value
 * @return {Array}
 */
function toArray(value) {
  return [].slice.call(value);
}

/**
 * Returns an array of elements based on the selector input
 * @param {String|Element|Element[]|NodeList|Object} selector
 * @return {Element[]}
 */
function getArrayOfElements(selector) {
  if (selector instanceof Element || isObjectLiteral(selector)) {
    return [selector];
  }

  if (selector instanceof NodeList) {
    return toArray(selector);
  }

  if (Array.isArray(selector)) {
    return selector;
  }

  try {
    return toArray(document.querySelectorAll(selector));
  } catch (_) {
    return [];
  }
}

/**
 * Polyfills needed props/methods for a virtual reference object
 * NOTE: in v3.0 this will be pure
 * @param {Object} reference
 */
function polyfillVirtualReferenceProps(reference) {
  reference.refObj = true;
  reference.attributes = reference.attributes || {};
  reference.setAttribute = function (key, val) {
    reference.attributes[key] = val;
  };
  reference.getAttribute = function (key) {
    return reference.attributes[key];
  };
  reference.removeAttribute = function (key) {
    delete reference.attributes[key];
  };
  reference.hasAttribute = function (key) {
    return key in reference.attributes;
  };
  reference.addEventListener = function () {};
  reference.removeEventListener = function () {};
  reference.classList = {
    classNames: {},
    add: function add(key) {
      return reference.classList.classNames[key] = true;
    },
    remove: function remove(key) {
      delete reference.classList.classNames[key];
      return true;
    },
    contains: function contains(key) {
      return key in reference.classList.classNames;
    }
  };
}

/**
 * Returns the supported prefixed property - only `webkit` is needed, `moz`, `ms` and `o` are obsolete
 * @param {String} property
 * @return {String} - browser supported prefixed property
 */
function prefix(property) {
  var prefixes = ['', 'webkit'];
  var upperProp = property.charAt(0).toUpperCase() + property.slice(1);

  for (var i = 0; i < prefixes.length; i++) {
    var _prefix = prefixes[i];
    var prefixedProp = _prefix ? _prefix + upperProp : property;
    if (typeof document.body.style[prefixedProp] !== 'undefined') {
      return prefixedProp;
    }
  }

  return null;
}

/**
 * Creates a div element
 * @return {Element}
 */
function div() {
  return document.createElement('div');
}

/**
 * Creates a popper element then returns it
 * @param {Number} id - the popper id
 * @param {String} title - the tooltip's `title` attribute
 * @param {Object} options - individual options
 * @return {Element} - the popper element
 */
function createPopperElement(id, title, options) {
  var popper = div();
  popper.setAttribute('class', 'tippy-popper');
  popper.setAttribute('role', 'tooltip');
  popper.setAttribute('id', 'tippy-' + id);
  popper.style.zIndex = options.zIndex;
  popper.style.maxWidth = options.maxWidth;

  var tooltip = div();
  tooltip.setAttribute('class', 'tippy-tooltip');
  tooltip.setAttribute('data-size', options.size);
  tooltip.setAttribute('data-animation', options.animation);
  tooltip.setAttribute('data-state', 'hidden');
  options.theme.split(' ').forEach(function (t) {
    tooltip.classList.add(t + '-theme');
  });

  var content = div();
  content.setAttribute('class', 'tippy-content');

  if (options.arrow) {
    var arrow = div();
    arrow.style[prefix('transform')] = options.arrowTransform;

    if (options.arrowType === 'round') {
      arrow.classList.add('tippy-roundarrow');
      arrow.innerHTML = '<svg viewBox="0 0 24 8" xmlns="http://www.w3.org/2000/svg"><path d="M3 8s2.021-.015 5.253-4.218C9.584 2.051 10.797 1.007 12 1c1.203-.007 2.416 1.035 3.761 2.782C19.012 8.005 21 8 21 8H3z"/></svg>';
    } else {
      arrow.classList.add('tippy-arrow');
    }

    tooltip.appendChild(arrow);
  }

  if (options.animateFill) {
    // Create animateFill circle element for animation
    tooltip.setAttribute('data-animatefill', '');
    var backdrop = div();
    backdrop.classList.add('tippy-backdrop');
    backdrop.setAttribute('data-state', 'hidden');
    tooltip.appendChild(backdrop);
  }

  if (options.inertia) {
    // Change transition timing function cubic bezier
    tooltip.setAttribute('data-inertia', '');
  }

  if (options.interactive) {
    tooltip.setAttribute('data-interactive', '');
  }

  var html = options.html;
  if (html) {
    var templateId = void 0;

    if (html instanceof Element) {
      content.appendChild(html);
      templateId = '#' + (html.id || 'tippy-html-template');
    } else {
      // trick linters: https://github.com/atomiks/tippyjs/issues/197
      content[true && 'innerHTML'] = document.querySelector(html)[true && 'innerHTML'];
      templateId = html;
    }

    popper.setAttribute('data-html', '');
    tooltip.setAttribute('data-template-id', templateId);

    if (options.interactive) {
      popper.setAttribute('tabindex', '-1');
    }
  } else {
    content[options.allowTitleHTML ? 'innerHTML' : 'textContent'] = title;
  }

  tooltip.appendChild(content);
  popper.appendChild(tooltip);

  return popper;
}

/**
 * Creates a trigger by adding the necessary event listeners to the reference element
 * @param {String} eventType - the custom event specified in the `trigger` setting
 * @param {Element} reference
 * @param {Object} handlers - the handlers for each event
 * @param {Object} options
 * @return {Array} - array of listener objects
 */
function createTrigger(eventType, reference, handlers, options) {
  var onTrigger = handlers.onTrigger,
      onMouseLeave = handlers.onMouseLeave,
      onBlur = handlers.onBlur,
      onDelegateShow = handlers.onDelegateShow,
      onDelegateHide = handlers.onDelegateHide;

  var listeners = [];

  if (eventType === 'manual') return listeners;

  var on = function on(eventType, handler) {
    reference.addEventListener(eventType, handler);
    listeners.push({ event: eventType, handler: handler });
  };

  if (!options.target) {
    on(eventType, onTrigger);

    if (browser.supportsTouch && options.touchHold) {
      on('touchstart', onTrigger);
      on('touchend', onMouseLeave);
    }
    if (eventType === 'mouseenter') {
      on('mouseleave', onMouseLeave);
    }
    if (eventType === 'focus') {
      on(isIE ? 'focusout' : 'blur', onBlur);
    }
  } else {
    if (browser.supportsTouch && options.touchHold) {
      on('touchstart', onDelegateShow);
      on('touchend', onDelegateHide);
    }
    if (eventType === 'mouseenter') {
      on('mouseover', onDelegateShow);
      on('mouseout', onDelegateHide);
    }
    if (eventType === 'focus') {
      on('focusin', onDelegateShow);
      on('focusout', onDelegateHide);
    }
    if (eventType === 'click') {
      on('click', onDelegateShow);
    }
  }

  return listeners;
}

var classCallCheck = function (instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
};

var createClass = function () {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ("value" in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }

  return function (Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
}();







var _extends = Object.assign || function (target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];

    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }

  return target;
};

/**
 * Returns an object of settings to override global settings
 * @param {Element} reference
 * @param {Object} instanceOptions
 * @return {Object} - individual options
 */
function getIndividualOptions(reference, instanceOptions) {
  var options = defaultsKeys.reduce(function (acc, key) {
    var val = reference.getAttribute('data-tippy-' + key.toLowerCase()) || instanceOptions[key];

    // Convert strings to booleans
    if (val === 'false') val = false;
    if (val === 'true') val = true;

    // Convert number strings to true numbers
    if (isFinite(val) && !isNaN(parseFloat(val))) {
      val = parseFloat(val);
    }

    // Convert array strings to actual arrays
    if (key !== 'target' && typeof val === 'string' && val.trim().charAt(0) === '[') {
      val = JSON.parse(val);
    }

    acc[key] = val;

    return acc;
  }, {});

  return _extends({}, instanceOptions, options);
}

/**
 * Evaluates/modifies the options object for appropriate behavior
 * @param {Element|Object} reference
 * @param {Object} options
 * @return {Object} modified/evaluated options
 */
function evaluateOptions(reference, options) {
  // animateFill is disabled if an arrow is true
  if (options.arrow) {
    options.animateFill = false;
  }

  if (options.appendTo && typeof options.appendTo === 'function') {
    options.appendTo = options.appendTo();
  }

  if (typeof options.html === 'function') {
    options.html = options.html(reference);
  }

  return options;
}

/**
 * Returns inner elements of the popper element
 * @param {Element} popper
 * @return {Object}
 */
function getInnerElements(popper) {
  var select = function select(s) {
    return popper.querySelector(s);
  };
  return {
    tooltip: select(selectors.TOOLTIP),
    backdrop: select(selectors.BACKDROP),
    content: select(selectors.CONTENT),
    arrow: select(selectors.ARROW) || select(selectors.ROUND_ARROW)
  };
}

/**
 * Removes the title from an element, setting `data-original-title`
 * appropriately
 * @param {Element} el
 */
function removeTitle(el) {
  var title = el.getAttribute('title');
  // Only set `data-original-title` attr if there is a title
  if (title) {
    el.setAttribute('data-original-title', title);
  }
  el.removeAttribute('title');
}

/**
 * Triggers document reflow.
 * Use void because some minifiers or engines think simply accessing the property
 * is unnecessary.
 * @param {Element} popper
 */
function reflow(popper) {
  void popper.offsetHeight;
}

/**
 * Wrapper util for popper position updating.
 * Updates the popper's position and invokes the callback on update.
 * Hackish workaround until Popper 2.0's update() becomes sync.
 * @param {Popper} popperInstance
 * @param {Function} callback: to run once popper's position was updated
 * @param {Boolean} updateAlreadyCalled: was scheduleUpdate() already called?
 */
function updatePopperPosition(popperInstance, callback, updateAlreadyCalled) {
  var popper = popperInstance.popper,
      options = popperInstance.options;

  var onCreate = options.onCreate;
  var onUpdate = options.onUpdate;

  options.onCreate = options.onUpdate = function () {
    reflow(popper), callback && callback(), onUpdate();
    options.onCreate = onCreate;
    options.onUpdate = onUpdate;
  };

  if (!updateAlreadyCalled) {
    popperInstance.scheduleUpdate();
  }
}

/**
 * Returns the core placement ('top', 'bottom', 'left', 'right') of a popper
 * @param {Element} popper
 * @return {String}
 */
function getPopperPlacement(popper) {
  return popper.getAttribute('x-placement').replace(/-.+/, '');
}

/**
 * Determines if the mouse's cursor is outside the interactive border
 * @param {MouseEvent} event
 * @param {Element} popper
 * @param {Object} options
 * @return {Boolean}
 */
function cursorIsOutsideInteractiveBorder(event, popper, options) {
  if (!popper.getAttribute('x-placement')) return true;

  var x = event.clientX,
      y = event.clientY;
  var interactiveBorder = options.interactiveBorder,
      distance = options.distance;


  var rect = popper.getBoundingClientRect();
  var placement = getPopperPlacement(popper);
  var borderWithDistance = interactiveBorder + distance;

  var exceeds = {
    top: rect.top - y > interactiveBorder,
    bottom: y - rect.bottom > interactiveBorder,
    left: rect.left - x > interactiveBorder,
    right: x - rect.right > interactiveBorder
  };

  switch (placement) {
    case 'top':
      exceeds.top = rect.top - y > borderWithDistance;
      break;
    case 'bottom':
      exceeds.bottom = y - rect.bottom > borderWithDistance;
      break;
    case 'left':
      exceeds.left = rect.left - x > borderWithDistance;
      break;
    case 'right':
      exceeds.right = x - rect.right > borderWithDistance;
      break;
  }

  return exceeds.top || exceeds.bottom || exceeds.left || exceeds.right;
}

/**
 * Transforms the `arrowTransform` numbers based on the placement axis
 * @param {String} type 'scale' or 'translate'
 * @param {Number[]} numbers
 * @param {Boolean} isVertical
 * @param {Boolean} isReverse
 * @return {String}
 */
function transformNumbersBasedOnPlacementAxis(type, numbers, isVertical, isReverse) {
  if (!numbers.length) return '';

  var transforms = {
    scale: function () {
      if (numbers.length === 1) {
        return '' + numbers[0];
      } else {
        return isVertical ? numbers[0] + ', ' + numbers[1] : numbers[1] + ', ' + numbers[0];
      }
    }(),
    translate: function () {
      if (numbers.length === 1) {
        return isReverse ? -numbers[0] + 'px' : numbers[0] + 'px';
      } else {
        if (isVertical) {
          return isReverse ? numbers[0] + 'px, ' + -numbers[1] + 'px' : numbers[0] + 'px, ' + numbers[1] + 'px';
        } else {
          return isReverse ? -numbers[1] + 'px, ' + numbers[0] + 'px' : numbers[1] + 'px, ' + numbers[0] + 'px';
        }
      }
    }()
  };

  return transforms[type];
}

/**
 * Transforms the `arrowTransform` x or y axis based on the placement axis
 * @param {String} axis 'X', 'Y', ''
 * @param {Boolean} isVertical
 * @return {String}
 */
function transformAxis(axis, isVertical) {
  if (!axis) return '';
  var map = {
    X: 'Y',
    Y: 'X'
  };
  return isVertical ? axis : map[axis];
}

/**
 * Computes and applies the necessary arrow transform
 * @param {Element} popper
 * @param {Element} arrow
 * @param {String} arrowTransform
 */
function computeArrowTransform(popper, arrow, arrowTransform) {
  var placement = getPopperPlacement(popper);
  var isVertical = placement === 'top' || placement === 'bottom';
  var isReverse = placement === 'right' || placement === 'bottom';

  var getAxis = function getAxis(re) {
    var match = arrowTransform.match(re);
    return match ? match[1] : '';
  };

  var getNumbers = function getNumbers(re) {
    var match = arrowTransform.match(re);
    return match ? match[1].split(',').map(parseFloat) : [];
  };

  var re = {
    translate: /translateX?Y?\(([^)]+)\)/,
    scale: /scaleX?Y?\(([^)]+)\)/
  };

  var matches = {
    translate: {
      axis: getAxis(/translate([XY])/),
      numbers: getNumbers(re.translate)
    },
    scale: {
      axis: getAxis(/scale([XY])/),
      numbers: getNumbers(re.scale)
    }
  };

  var computedTransform = arrowTransform.replace(re.translate, 'translate' + transformAxis(matches.translate.axis, isVertical) + '(' + transformNumbersBasedOnPlacementAxis('translate', matches.translate.numbers, isVertical, isReverse) + ')').replace(re.scale, 'scale' + transformAxis(matches.scale.axis, isVertical) + '(' + transformNumbersBasedOnPlacementAxis('scale', matches.scale.numbers, isVertical, isReverse) + ')');

  arrow.style[prefix('transform')] = computedTransform;
}

/**
 * Returns the distance taking into account the default distance due to
 * the transform: translate setting in CSS
 * @param {Number} distance
 * @return {String}
 */
function getOffsetDistanceInPx(distance) {
  return -(distance - defaults.distance) + 'px';
}

/**
 * Waits until next repaint to execute a fn
 * @param {Function} fn
 */
function defer(fn) {
  requestAnimationFrame(function () {
    setTimeout(fn, 1);
  });
}

var matches = {};

if (isBrowser) {
  var e = Element.prototype;
  matches = e.matches || e.matchesSelector || e.webkitMatchesSelector || e.mozMatchesSelector || e.msMatchesSelector || function (s) {
    var matches = (this.document || this.ownerDocument).querySelectorAll(s);
    var i = matches.length;
    while (--i >= 0 && matches.item(i) !== this) {} // eslint-disable-line no-empty
    return i > -1;
  };
}

var matches$1 = matches;

/**
 * Ponyfill to get the closest parent element
 * @param {Element} element - child of parent to be returned
 * @param {String} parentSelector - selector to match the parent if found
 * @return {Element}
 */
function closest(element, parentSelector) {
  var fn = Element.prototype.closest || function (selector) {
    var el = this;
    while (el) {
      if (matches$1.call(el, selector)) {
        return el;
      }
      el = el.parentElement;
    }
  };

  return fn.call(element, parentSelector);
}

/**
 * Returns the value taking into account the value being either a number or array
 * @param {Number|Array} value
 * @param {Number} index
 * @return {Number}
 */
function getValue(value, index) {
  return Array.isArray(value) ? value[index] : value;
}

/**
 * Sets the visibility state of an element for transition to begin
 * @param {Element[]} els - array of elements
 * @param {String} type - 'visible' or 'hidden'
 */
function setVisibilityState(els, type) {
  els.forEach(function (el) {
    if (!el) return;
    el.setAttribute('data-state', type);
  });
}

/**
 * Sets the transition property to each element
 * @param {Element[]} els - Array of elements
 * @param {String} value
 */
function applyTransitionDuration(els, value) {
  els.filter(Boolean).forEach(function (el) {
    el.style[prefix('transitionDuration')] = value + 'ms';
  });
}

/**
 * Focuses an element while preventing a scroll jump if it's not entirely within the viewport
 * @param {Element} el
 */
function focus(el) {
  var x = window.scrollX || window.pageXOffset;
  var y = window.scrollY || window.pageYOffset;
  el.focus();
  scroll(x, y);
}

var key = {};
var store = function store(data) {
  return function (k) {
    return k === key && data;
  };
};

var Tippy = function () {
  function Tippy(config) {
    classCallCheck(this, Tippy);

    for (var _key in config) {
      this[_key] = config[_key];
    }

    this.state = {
      destroyed: false,
      visible: false,
      enabled: true
    };

    this._ = store({
      mutationObservers: []
    });
  }

  /**
   * Enables the tooltip to allow it to show or hide
   * @memberof Tippy
   * @public
   */


  createClass(Tippy, [{
    key: 'enable',
    value: function enable() {
      this.state.enabled = true;
    }

    /**
     * Disables the tooltip from showing or hiding, but does not destroy it
     * @memberof Tippy
     * @public
     */

  }, {
    key: 'disable',
    value: function disable() {
      this.state.enabled = false;
    }

    /**
     * Shows the tooltip
     * @param {Number} duration in milliseconds
     * @memberof Tippy
     * @public
     */

  }, {
    key: 'show',
    value: function show(duration) {
      var _this = this;

      if (this.state.destroyed || !this.state.enabled) return;

      var popper = this.popper,
          reference = this.reference,
          options = this.options;

      var _getInnerElements = getInnerElements(popper),
          tooltip = _getInnerElements.tooltip,
          backdrop = _getInnerElements.backdrop,
          content = _getInnerElements.content;

      // If the `dynamicTitle` option is true, the instance is allowed
      // to be created with an empty title. Make sure that the tooltip
      // content is not empty before showing it


      if (options.dynamicTitle && !reference.getAttribute('data-original-title')) {
        return;
      }

      // Do not show tooltip if reference contains 'disabled' attribute. FF fix for #221
      if (reference.hasAttribute('disabled')) return;

      // Destroy tooltip if the reference element is no longer on the DOM
      if (!reference.refObj && !document.documentElement.contains(reference)) {
        this.destroy();
        return;
      }

      options.onShow.call(popper, this);

      duration = getValue(duration !== undefined ? duration : options.duration, 0);

      // Prevent a transition when popper changes position
      applyTransitionDuration([popper, tooltip, backdrop], 0);

      popper.style.visibility = 'visible';
      this.state.visible = true;

      _mount.call(this, function () {
        if (!_this.state.visible) return;

        if (!_hasFollowCursorBehavior.call(_this)) {
          // FIX: Arrow will sometimes not be positioned correctly. Force another update.
          _this.popperInstance.scheduleUpdate();
        }

        // Set initial position near the cursor
        if (_hasFollowCursorBehavior.call(_this)) {
          _this.popperInstance.disableEventListeners();
          var delay = getValue(options.delay, 0);
          var lastTriggerEvent = _this._(key).lastTriggerEvent;
          if (lastTriggerEvent) {
            _this._(key).followCursorListener(delay && _this._(key).lastMouseMoveEvent ? _this._(key).lastMouseMoveEvent : lastTriggerEvent);
          }
        }

        // Re-apply transition durations
        applyTransitionDuration([tooltip, backdrop, backdrop ? content : null], duration);

        if (backdrop) {
          getComputedStyle(backdrop)[prefix('transform')];
        }

        if (options.interactive) {
          reference.classList.add('tippy-active');
        }

        if (options.sticky) {
          _makeSticky.call(_this);
        }

        setVisibilityState([tooltip, backdrop], 'visible');

        _onTransitionEnd.call(_this, duration, function () {
          if (!options.updateDuration) {
            tooltip.classList.add('tippy-notransition');
          }

          if (options.interactive) {
            focus(popper);
          }

          reference.setAttribute('aria-describedby', 'tippy-' + _this.id);

          options.onShown.call(popper, _this);
        });
      });
    }

    /**
     * Hides the tooltip
     * @param {Number} duration in milliseconds
     * @memberof Tippy
     * @public
     */

  }, {
    key: 'hide',
    value: function hide(duration) {
      var _this2 = this;

      if (this.state.destroyed || !this.state.enabled) return;

      var popper = this.popper,
          reference = this.reference,
          options = this.options;

      var _getInnerElements2 = getInnerElements(popper),
          tooltip = _getInnerElements2.tooltip,
          backdrop = _getInnerElements2.backdrop,
          content = _getInnerElements2.content;

      options.onHide.call(popper, this);

      duration = getValue(duration !== undefined ? duration : options.duration, 1);

      if (!options.updateDuration) {
        tooltip.classList.remove('tippy-notransition');
      }

      if (options.interactive) {
        reference.classList.remove('tippy-active');
      }

      popper.style.visibility = 'hidden';
      this.state.visible = false;

      applyTransitionDuration([tooltip, backdrop, backdrop ? content : null], duration);

      setVisibilityState([tooltip, backdrop], 'hidden');

      if (options.interactive && options.trigger.indexOf('click') > -1) {
        focus(reference);
      }

      /*
      * This call is deferred because sometimes when the tooltip is still transitioning in but hide()
      * is called before it finishes, the CSS transition won't reverse quickly enough, meaning
      * the CSS transition will finish 1-2 frames later, and onHidden() will run since the JS set it
      * more quickly. It should actually be onShown(). Seems to be something Chrome does, not Safari
      */
      defer(function () {
        _onTransitionEnd.call(_this2, duration, function () {
          if (_this2.state.visible || !options.appendTo.contains(popper)) return;

          if (!_this2._(key).isPreparingToShow) {
            document.removeEventListener('mousemove', _this2._(key).followCursorListener);
            _this2._(key).lastMouseMoveEvent = null;
          }

          if (_this2.popperInstance) {
            _this2.popperInstance.disableEventListeners();
          }

          reference.removeAttribute('aria-describedby');

          options.appendTo.removeChild(popper);

          options.onHidden.call(popper, _this2);
        });
      });
    }

    /**
     * Destroys the tooltip instance
     * @param {Boolean} destroyTargetInstances - relevant only when destroying delegates
     * @memberof Tippy
     * @public
     */

  }, {
    key: 'destroy',
    value: function destroy() {
      var _this3 = this;

      var destroyTargetInstances = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;

      if (this.state.destroyed) return;

      // Ensure the popper is hidden
      if (this.state.visible) {
        this.hide(0);
      }

      this.listeners.forEach(function (listener) {
        _this3.reference.removeEventListener(listener.event, listener.handler);
      });

      // Restore title
      if (this.title) {
        this.reference.setAttribute('title', this.title);
      }

      delete this.reference._tippy;

      var attributes = ['data-original-title', 'data-tippy', 'data-tippy-delegate'];
      attributes.forEach(function (attr) {
        _this3.reference.removeAttribute(attr);
      });

      if (this.options.target && destroyTargetInstances) {
        toArray(this.reference.querySelectorAll(this.options.target)).forEach(function (child) {
          return child._tippy && child._tippy.destroy();
        });
      }

      if (this.popperInstance) {
        this.popperInstance.destroy();
      }

      this._(key).mutationObservers.forEach(function (observer) {
        observer.disconnect();
      });

      this.state.destroyed = true;
    }
  }]);
  return Tippy;
}();

/**
 * ------------------------------------------------------------------------
 * Private methods
 * ------------------------------------------------------------------------
 * Standalone functions to be called with the instance's `this` context to make
 * them truly private and not accessible on the prototype
 */

/**
 * Determines if the tooltip instance has followCursor behavior
 * @return {Boolean}
 * @memberof Tippy
 * @private
 */
function _hasFollowCursorBehavior() {
  var lastTriggerEvent = this._(key).lastTriggerEvent;
  return this.options.followCursor && !browser.usingTouch && lastTriggerEvent && lastTriggerEvent.type !== 'focus';
}

/**
 * Creates the Tippy instance for the child target of the delegate container
 * @param {Event} event
 * @memberof Tippy
 * @private
 */
function _createDelegateChildTippy(event) {
  var targetEl = closest(event.target, this.options.target);
  if (targetEl && !targetEl._tippy) {
    var title = targetEl.getAttribute('title') || this.title;
    if (title) {
      targetEl.setAttribute('title', title);
      tippy$1(targetEl, _extends({}, this.options, { target: null }));
      _enter.call(targetEl._tippy, event);
    }
  }
}

/**
 * Method used by event listeners to invoke the show method, taking into account delays and
 * the `wait` option
 * @param {Event} event
 * @memberof Tippy
 * @private
 */
function _enter(event) {
  var _this4 = this;

  var options = this.options;


  _clearDelayTimeouts.call(this);

  if (this.state.visible) return;

  // Is a delegate, create Tippy instance for the child target
  if (options.target) {
    _createDelegateChildTippy.call(this, event);
    return;
  }

  this._(key).isPreparingToShow = true;

  if (options.wait) {
    options.wait.call(this.popper, this.show.bind(this), event);
    return;
  }

  // If the tooltip has a delay, we need to be listening to the mousemove as soon as the trigger
  // event is fired so that it's in the correct position upon mount.
  if (_hasFollowCursorBehavior.call(this)) {
    if (!this._(key).followCursorListener) {
      _setFollowCursorListener.call(this);
    }

    var _getInnerElements3 = getInnerElements(this.popper),
        arrow = _getInnerElements3.arrow;

    if (arrow) arrow.style.margin = '0';
    document.addEventListener('mousemove', this._(key).followCursorListener);
  }

  var delay = getValue(options.delay, 0);

  if (delay) {
    this._(key).showTimeout = setTimeout(function () {
      _this4.show();
    }, delay);
  } else {
    this.show();
  }
}

/**
 * Method used by event listeners to invoke the hide method, taking into account delays
 * @memberof Tippy
 * @private
 */
function _leave() {
  var _this5 = this;

  _clearDelayTimeouts.call(this);

  if (!this.state.visible) return;

  this._(key).isPreparingToShow = false;

  var delay = getValue(this.options.delay, 1);

  if (delay) {
    this._(key).hideTimeout = setTimeout(function () {
      if (_this5.state.visible) {
        _this5.hide();
      }
    }, delay);
  } else {
    this.hide();
  }
}

/**
 * Returns relevant listeners for the instance
 * @return {Object} of listeners
 * @memberof Tippy
 * @private
 */
function _getEventListeners() {
  var _this6 = this;

  var onTrigger = function onTrigger(event) {
    if (!_this6.state.enabled) return;

    var shouldStopEvent = browser.supportsTouch && browser.usingTouch && ['mouseenter', 'mouseover', 'focus'].indexOf(event.type) > -1;

    if (shouldStopEvent && _this6.options.touchHold) return;

    _this6._(key).lastTriggerEvent = event;

    // Toggle show/hide when clicking click-triggered tooltips
    if (event.type === 'click' && _this6.options.hideOnClick !== 'persistent' && _this6.state.visible) {
      _leave.call(_this6);
    } else {
      _enter.call(_this6, event);
    }
  };

  var onMouseLeave = function onMouseLeave(event) {
    if (['mouseleave', 'mouseout'].indexOf(event.type) > -1 && browser.supportsTouch && browser.usingTouch && _this6.options.touchHold) return;

    if (_this6.options.interactive) {
      var hide = _leave.bind(_this6);

      var onMouseMove = function onMouseMove(event) {
        var referenceCursorIsOver = closest(event.target, selectors.REFERENCE);
        var cursorIsOverPopper = closest(event.target, selectors.POPPER) === _this6.popper;
        var cursorIsOverReference = referenceCursorIsOver === _this6.reference;

        if (cursorIsOverPopper || cursorIsOverReference) return;

        if (cursorIsOutsideInteractiveBorder(event, _this6.popper, _this6.options)) {
          document.body.removeEventListener('mouseleave', hide);
          document.removeEventListener('mousemove', onMouseMove);

          _leave.call(_this6, onMouseMove);
        }
      };

      document.body.addEventListener('mouseleave', hide);
      document.addEventListener('mousemove', onMouseMove);
      return;
    }

    _leave.call(_this6);
  };

  var onBlur = function onBlur(event) {
    if (event.target !== _this6.reference || browser.usingTouch) return;

    if (_this6.options.interactive) {
      if (!event.relatedTarget) return;
      if (closest(event.relatedTarget, selectors.POPPER)) return;
    }

    _leave.call(_this6);
  };

  var onDelegateShow = function onDelegateShow(event) {
    if (closest(event.target, _this6.options.target)) {
      _enter.call(_this6, event);
    }
  };

  var onDelegateHide = function onDelegateHide(event) {
    if (closest(event.target, _this6.options.target)) {
      _leave.call(_this6);
    }
  };

  return {
    onTrigger: onTrigger,
    onMouseLeave: onMouseLeave,
    onBlur: onBlur,
    onDelegateShow: onDelegateShow,
    onDelegateHide: onDelegateHide
  };
}

/**
 * Creates and returns a new popper instance
 * @return {Popper}
 * @memberof Tippy
 * @private
 */
function _createPopperInstance() {
  var _this7 = this;

  var popper = this.popper,
      reference = this.reference,
      options = this.options;

  var _getInnerElements4 = getInnerElements(popper),
      tooltip = _getInnerElements4.tooltip;

  var popperOptions = options.popperOptions;

  var arrowSelector = options.arrowType === 'round' ? selectors.ROUND_ARROW : selectors.ARROW;
  var arrow = tooltip.querySelector(arrowSelector);

  var config = _extends({
    placement: options.placement
  }, popperOptions || {}, {
    modifiers: _extends({}, popperOptions ? popperOptions.modifiers : {}, {
      arrow: _extends({
        element: arrowSelector
      }, popperOptions && popperOptions.modifiers ? popperOptions.modifiers.arrow : {}),
      flip: _extends({
        enabled: options.flip,
        padding: options.distance + 5 /* 5px from viewport boundary */
        , behavior: options.flipBehavior
      }, popperOptions && popperOptions.modifiers ? popperOptions.modifiers.flip : {}),
      offset: _extends({
        offset: options.offset
      }, popperOptions && popperOptions.modifiers ? popperOptions.modifiers.offset : {})
    }),
    onCreate: function onCreate() {
      tooltip.style[getPopperPlacement(popper)] = getOffsetDistanceInPx(options.distance);

      if (arrow && options.arrowTransform) {
        computeArrowTransform(popper, arrow, options.arrowTransform);
      }
    },
    onUpdate: function onUpdate() {
      var styles = tooltip.style;
      styles.top = '';
      styles.bottom = '';
      styles.left = '';
      styles.right = '';
      styles[getPopperPlacement(popper)] = getOffsetDistanceInPx(options.distance);

      if (arrow && options.arrowTransform) {
        computeArrowTransform(popper, arrow, options.arrowTransform);
      }
    }
  });

  _addMutationObserver.call(this, {
    target: popper,
    callback: function callback() {
      _this7.popperInstance.update();
    },
    options: {
      childList: true,
      subtree: true,
      characterData: true
    }
  });

  return new Popper(reference, popper, config);
}

/**
 * Appends the popper element to the DOM, updating or creating the popper instance
 * @param {Function} callback
 * @memberof Tippy
 * @private
 */
function _mount(callback) {
  var options = this.options;


  if (!this.popperInstance) {
    this.popperInstance = _createPopperInstance.call(this);
    if (!options.livePlacement) {
      this.popperInstance.disableEventListeners();
    }
  } else {
    this.popperInstance.scheduleUpdate();
    if (options.livePlacement && !_hasFollowCursorBehavior.call(this)) {
      this.popperInstance.enableEventListeners();
    }
  }

  // If the instance previously had followCursor behavior, it will be positioned incorrectly
  // if triggered by `focus` afterwards - update the reference back to the real DOM element
  if (!_hasFollowCursorBehavior.call(this)) {
    var _getInnerElements5 = getInnerElements(this.popper),
        arrow = _getInnerElements5.arrow;

    if (arrow) arrow.style.margin = '';
    this.popperInstance.reference = this.reference;
  }

  updatePopperPosition(this.popperInstance, callback, true);

  if (!options.appendTo.contains(this.popper)) {
    options.appendTo.appendChild(this.popper);
  }
}

/**
 * Clears the show and hide delay timeouts
 * @memberof Tippy
 * @private
 */
function _clearDelayTimeouts() {
  var _ref = this._(key),
      showTimeout = _ref.showTimeout,
      hideTimeout = _ref.hideTimeout;

  clearTimeout(showTimeout);
  clearTimeout(hideTimeout);
}

/**
 * Sets the mousemove event listener function for `followCursor` option
 * @memberof Tippy
 * @private
 */
function _setFollowCursorListener() {
  var _this8 = this;

  this._(key).followCursorListener = function (event) {
    var _$lastMouseMoveEvent = _this8._(key).lastMouseMoveEvent = event,
        clientX = _$lastMouseMoveEvent.clientX,
        clientY = _$lastMouseMoveEvent.clientY;

    if (!_this8.popperInstance) return;

    _this8.popperInstance.reference = {
      getBoundingClientRect: function getBoundingClientRect() {
        return {
          width: 0,
          height: 0,
          top: clientY,
          left: clientX,
          right: clientX,
          bottom: clientY
        };
      },
      clientWidth: 0,
      clientHeight: 0
    };

    _this8.popperInstance.scheduleUpdate();
  };
}

/**
 * Updates the popper's position on each animation frame
 * @memberof Tippy
 * @private
 */
function _makeSticky() {
  var _this9 = this;

  var applyTransitionDuration$$1 = function applyTransitionDuration$$1() {
    _this9.popper.style[prefix('transitionDuration')] = _this9.options.updateDuration + 'ms';
  };

  var removeTransitionDuration = function removeTransitionDuration() {
    _this9.popper.style[prefix('transitionDuration')] = '';
  };

  var updatePosition = function updatePosition() {
    if (_this9.popperInstance) {
      _this9.popperInstance.update();
    }

    applyTransitionDuration$$1();

    if (_this9.state.visible) {
      requestAnimationFrame(updatePosition);
    } else {
      removeTransitionDuration();
    }
  };

  updatePosition();
}

/**
 * Adds a mutation observer to an element and stores it in the instance
 * @param {Object}
 * @memberof Tippy
 * @private
 */
function _addMutationObserver(_ref2) {
  var target = _ref2.target,
      callback = _ref2.callback,
      options = _ref2.options;

  if (!window.MutationObserver) return;

  var observer = new MutationObserver(callback);
  observer.observe(target, options);

  this._(key).mutationObservers.push(observer);
}

/**
 * Fires the callback functions once the CSS transition ends for `show` and `hide` methods
 * @param {Number} duration
 * @param {Function} callback - callback function to fire once transition completes
 * @memberof Tippy
 * @private
 */
function _onTransitionEnd(duration, callback) {
  // Make callback synchronous if duration is 0
  if (!duration) {
    return callback();
  }

  var _getInnerElements6 = getInnerElements(this.popper),
      tooltip = _getInnerElements6.tooltip;

  var toggleListeners = function toggleListeners(action, listener) {
    if (!listener) return;
    tooltip[action + 'EventListener']('transition' in document.body.style ? 'transitionend' : 'webkitTransitionEnd', listener);
  };

  var listener = function listener(e) {
    if (e.target === tooltip) {
      toggleListeners('remove', listener);
      callback();
    }
  };

  toggleListeners('remove', this._(key).transitionendListener);
  toggleListeners('add', listener);

  this._(key).transitionendListener = listener;
}

var idCounter = 1;

/**
 * Creates tooltips for each reference element
 * @param {Element[]} els
 * @param {Object} config
 * @return {Tippy[]} Array of Tippy instances
 */
function createTooltips(els, config) {
  return els.reduce(function (acc, reference) {
    var id = idCounter;

    var options = evaluateOptions(reference, config.performance ? config : getIndividualOptions(reference, config));

    var title = reference.getAttribute('title');

    // Don't create an instance when:
    // * the `title` attribute is falsy (null or empty string), and
    // * it's not a delegate for tooltips, and
    // * there is no html template specified, and
    // * `dynamicTitle` option is false
    if (!title && !options.target && !options.html && !options.dynamicTitle) {
      return acc;
    }

    // Delegates should be highlighted as different
    reference.setAttribute(options.target ? 'data-tippy-delegate' : 'data-tippy', '');

    removeTitle(reference);

    var popper = createPopperElement(id, title, options);

    var tippy = new Tippy({
      id: id,
      reference: reference,
      popper: popper,
      options: options,
      title: title,
      popperInstance: null
    });

    if (options.createPopperInstanceOnInit) {
      tippy.popperInstance = _createPopperInstance.call(tippy);
      tippy.popperInstance.disableEventListeners();
    }

    var listeners = _getEventListeners.call(tippy);
    tippy.listeners = options.trigger.trim().split(' ').reduce(function (acc, eventType) {
      return acc.concat(createTrigger(eventType, reference, listeners, options));
    }, []);

    // Update tooltip content whenever the title attribute on the reference changes
    if (options.dynamicTitle) {
      _addMutationObserver.call(tippy, {
        target: reference,
        callback: function callback() {
          var _getInnerElements = getInnerElements(popper),
              content = _getInnerElements.content;

          var title = reference.getAttribute('title');
          if (title) {
            content[options.allowTitleHTML ? 'innerHTML' : 'textContent'] = tippy.title = title;
            removeTitle(reference);
          }
        },

        options: {
          attributes: true
        }
      });
    }

    // Shortcuts
    reference._tippy = tippy;
    popper._tippy = tippy;
    popper._reference = reference;

    acc.push(tippy);

    idCounter++;

    return acc;
  }, []);
}

/**
 * Hides all poppers
 * @param {Tippy} excludeTippy - tippy to exclude if needed
 */
function hideAllPoppers(excludeTippy) {
  var poppers = toArray(document.querySelectorAll(selectors.POPPER));

  poppers.forEach(function (popper) {
    var tippy = popper._tippy;
    if (!tippy) return;

    var options = tippy.options;


    if ((options.hideOnClick === true || options.trigger.indexOf('focus') > -1) && (!excludeTippy || popper !== excludeTippy.popper)) {
      tippy.hide();
    }
  });
}

/**
 * Adds the needed event listeners
 */
function bindEventListeners() {
  var onDocumentTouch = function onDocumentTouch() {
    if (browser.usingTouch) return;

    browser.usingTouch = true;

    if (browser.iOS) {
      document.body.classList.add('tippy-touch');
    }

    if (browser.dynamicInputDetection && window.performance) {
      document.addEventListener('mousemove', onDocumentMouseMove);
    }

    browser.onUserInputChange('touch');
  };

  var onDocumentMouseMove = function () {
    var time = void 0;

    return function () {
      var now = performance.now();

      // Chrome 60+ is 1 mousemove per animation frame, use 20ms time difference
      if (now - time < 20) {
        browser.usingTouch = false;
        document.removeEventListener('mousemove', onDocumentMouseMove);
        if (!browser.iOS) {
          document.body.classList.remove('tippy-touch');
        }
        browser.onUserInputChange('mouse');
      }

      time = now;
    };
  }();

  var onDocumentClick = function onDocumentClick(event) {
    // Simulated events dispatched on the document
    if (!(event.target instanceof Element)) {
      return hideAllPoppers();
    }

    var reference = closest(event.target, selectors.REFERENCE);
    var popper = closest(event.target, selectors.POPPER);

    if (popper && popper._tippy && popper._tippy.options.interactive) {
      return;
    }

    if (reference && reference._tippy) {
      var options = reference._tippy.options;

      var isClickTrigger = options.trigger.indexOf('click') > -1;
      var isMultiple = options.multiple;

      // Hide all poppers except the one belonging to the element that was clicked
      if (!isMultiple && browser.usingTouch || !isMultiple && isClickTrigger) {
        return hideAllPoppers(reference._tippy);
      }

      if (options.hideOnClick !== true || isClickTrigger) {
        return;
      }
    }

    hideAllPoppers();
  };

  var onWindowBlur = function onWindowBlur() {
    var _document = document,
        el = _document.activeElement;

    if (el && el.blur && matches$1.call(el, selectors.REFERENCE)) {
      el.blur();
    }
  };

  var onWindowResize = function onWindowResize() {
    toArray(document.querySelectorAll(selectors.POPPER)).forEach(function (popper) {
      var tippyInstance = popper._tippy;
      if (tippyInstance && !tippyInstance.options.livePlacement) {
        tippyInstance.popperInstance.scheduleUpdate();
      }
    });
  };

  document.addEventListener('click', onDocumentClick);
  document.addEventListener('touchstart', onDocumentTouch);
  window.addEventListener('blur', onWindowBlur);
  window.addEventListener('resize', onWindowResize);

  if (!browser.supportsTouch && (navigator.maxTouchPoints || navigator.msMaxTouchPoints)) {
    document.addEventListener('pointerdown', onDocumentTouch);
  }
}

var eventListenersBound = false;

/**
 * Exported module
 * @param {String|Element|Element[]|NodeList|Object} selector
 * @param {Object} options
 * @param {Boolean} one - create one tooltip
 * @return {Object}
 */
function tippy$1(selector, options, one) {
  if (browser.supported && !eventListenersBound) {
    bindEventListeners();
    eventListenersBound = true;
  }

  if (isObjectLiteral(selector)) {
    polyfillVirtualReferenceProps(selector);
  }

  options = _extends({}, defaults, options);

  var references = getArrayOfElements(selector);
  var firstReference = references[0];

  return {
    selector: selector,
    options: options,
    tooltips: browser.supported ? createTooltips(one && firstReference ? [firstReference] : references, options) : [],
    destroyAll: function destroyAll() {
      this.tooltips.forEach(function (tooltip) {
        return tooltip.destroy();
      });
      this.tooltips = [];
    }
  };
}

tippy$1.version = version;
tippy$1.browser = browser;
tippy$1.defaults = defaults;
tippy$1.one = function (selector, options) {
  return tippy$1(selector, options, true).tooltips[0];
};
tippy$1.disableAnimations = function () {
  defaults.updateDuration = defaults.duration = 0;
  defaults.animateFill = false;
};

return tippy$1;

})));
