text: /* eslint-disable react/prop-types */
  'use strict';
  
  var _extends = require('babel-runtime/helpers/extends')['default'];
  
  var _Object$keys = require('babel-runtime/core-js/object/keys')['default'];
  
  var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];
  
  exports.__esModule = true;
  
  var _react = require('react');
  
  var _react2 = _interopRequireDefault(_react);
  
  var _domHelpersQueryContains = require('dom-helpers/query/contains');
  
  var _domHelpersQueryContains2 = _interopRequireDefault(_domHelpersQueryContains);
  
  var _utilsCreateChainedFunction = require('./utils/createChainedFunction');
  
  var _utilsCreateChainedFunction2 = _interopRequireDefault(_utilsCreateChainedFunction);
  
  var _utilsCreateContextWrapper = require('./utils/createContextWrapper');
  
  var _utilsCreateContextWrapper2 = _interopRequireDefault(_utilsCreateContextWrapper);
  
  var _Overlay = require('./Overlay');
  
  var _Overlay2 = _interopRequireDefault(_Overlay);
  
  var _reactLibWarning = require('react/lib/warning');
  
  var _reactLibWarning2 = _interopRequireDefault(_reactLibWarning);
  
  var _lodashObjectPick = require('lodash/object/pick');
  
  var _lodashObjectPick2 = _interopRequireDefault(_lodashObjectPick);
  
  /**
   * Check if value one is inside or equal to the of value
   *
   * @param {string} one
   * @param {string|array} of
   * @returns {boolean}
   */
  function isOneOf(one, of) {
    if (Array.isArray(of)) {
      return of.indexOf(one) >= 0;
    }
    return one === of;
  }
  
  var OverlayTrigger = _react2['default'].createClass({
    displayName: 'OverlayTrigger',
  
    propTypes: _extends({}, _Overlay2['default'].propTypes, {
  
      /**
      * Specify which action or actions trigger Overlay visibility
      */
      trigger: _react2['default'].PropTypes.oneOfType([_react2['default'].PropTypes.oneOf(['click', 'hover', 'focus']), _react2['default'].PropTypes.arrayOf(_react2['default'].PropTypes.oneOf(['click', 'hover', 'focus']))]),
  
      /**
       * A millisecond delay amount to show and hide the Overlay once triggered
       */
      delay: _react2['default'].PropTypes.number,
      /**
       * A millisecond delay amount before showing the Overlay once triggered.
       */
      delayShow: _react2['default'].PropTypes.number,
      /**
       * A millisecond delay amount before hiding the Overlay once triggered.
       */
      delayHide: _react2['default'].PropTypes.number,
  
      /**
       * The initial visibility state of the Overlay, for more nuanced visibility controll consider
       * using the Overlay component directly.
       */
      defaultOverlayShown: _react2['default'].PropTypes.bool,
  
      /**
       * An element or text to overlay next to the target.
       */
      overlay: _react2['default'].PropTypes.node.isRequired,
  
      /**
       * @private
       */
      onBlur: _react2['default'].PropTypes.func,
      /**
       * @private
       */
      onClick: _react2['default'].PropTypes.func,
      /**
       * @private
       */
      onFocus: _react2['default'].PropTypes.func,
      /**
       * @private
       */
      onMouseEnter: _react2['default'].PropTypes.func,
      /**
       * @private
       */
      onMouseLeave: _react2['default'].PropTypes.func,
  
      // override specific overlay props
      /**
       * @private
       */
      target: function target() {},
      /**
      * @private
      */
      onHide: function onHide() {},
      /**
       * @private
       */
      show: function show() {}
    }),
  
    getDefaultProps: function getDefaultProps() {
      return {
        defaultOverlayShown: false,
        trigger: ['hover', 'focus']
      };
    },
  
    getInitialState: function getInitialState() {
      return {
        isOverlayShown: this.props.defaultOverlayShown
      };
    },
  
    show: function show() {
      this.setState({
        isOverlayShown: true
      });
    },
  
    hide: function hide() {
      this.setState({
        isOverlayShown: false
      });
    },
  
    toggle: function toggle() {
      if (this.state.isOverlayShown) {
        this.hide();
      } else {
        this.show();
      }
    },
  
    componentWillMount: function componentWillMount() {
      this.handleMouseOver = this.handleMouseOverOut.bind(null, this.handleDelayedShow);
      this.handleMouseOut = this.handleMouseOverOut.bind(null, this.handleDelayedHide);
    },
  
    componentDidMount: function componentDidMount() {
      this._mountNode = document.createElement('div');
      _react2['default'].render(this._overlay, this._mountNode);
    },
  
    componentWillUnmount: function componentWillUnmount() {
      _react2['default'].unmountComponentAtNode(this._mountNode);
      this._mountNode = null;
      clearTimeout(this._hoverDelay);
    },
  
    componentDidUpdate: function componentDidUpdate() {
      if (this._mountNode) {
        _react2['default'].render(this._overlay, this._mountNode);
      }
    },
  
    getOverlayTarget: function getOverlayTarget() {
      return _react2['default'].findDOMNode(this);
    },
  
    getOverlay: function getOverlay() {
      var overlayProps = _extends({}, _lodashObjectPick2['default'](this.props, _Object$keys(_Overlay2['default'].propTypes)), {
        show: this.state.isOverlayShown,
        onHide: this.hide,
        target: this.getOverlayTarget,
        onExit: this.props.onExit,
        onExiting: this.props.onExiting,
        onExited: this.props.onExited,
        onEnter: this.props.onEnter,
        onEntering: this.props.onEntering,
        onEntered: this.props.onEntered
      });
  
      var overlay = _react.cloneElement(this.props.overlay, {
        placement: overlayProps.placement,
        container: overlayProps.container
      });
  
      return _react2['default'].createElement(
        _Overlay2['default'],
        overlayProps,
        overlay
      );
    },
  
    render: function render() {
      var trigger = _react2['default'].Children.only(this.props.children);
      var triggerProps = trigger.props;
  
      var props = {
        'aria-describedby': this.props.overlay.props.id
      };
  
      // create in render otherwise owner is lost...
      this._overlay = this.getOverlay();
  
      props.onClick = _utilsCreateChainedFunction2['default'](triggerProps.onClick, this.props.onClick);
  
      if (isOneOf('click', this.props.trigger)) {
        props.onClick = _utilsCreateChainedFunction2['default'](this.toggle, props.onClick);
      }
  
      if (isOneOf('hover', this.props.trigger)) {
        _reactLibWarning2['default'](!(this.props.trigger === 'hover'), '[react-bootstrap] Specifying only the `"hover"` trigger limits the visibilty of the overlay to just mouse users. ' + 'Consider also including the `"focus"` trigger so that touch and keyboard only users can see the overlay as well.');
  
        props.onMouseOver = _utilsCreateChainedFunction2['default'](this.handleMouseOver, this.props.onMouseOver, triggerProps.onMouseOver);
        props.onMouseOut = _utilsCreateChainedFunction2['default'](this.handleMouseOut, this.props.onMouseOut, triggerProps.onMouseOut);
      }
  
      if (isOneOf('focus', this.props.trigger)) {
        props.onFocus = _utilsCreateChainedFunction2['default'](this.handleDelayedShow, this.props.onFocus, triggerProps.onFocus);
        props.onBlur = _utilsCreateChainedFunction2['default'](this.handleDelayedHide, this.props.onBlur, triggerProps.onBlur);
      }
  
      return _react.cloneElement(trigger, props);
    },
  
    handleDelayedShow: function handleDelayedShow() {
      var _this = this;
  
      if (this._hoverDelay != null) {
        clearTimeout(this._hoverDelay);
        this._hoverDelay = null;
        return;
      }
  
      var delay = this.props.delayShow != null ? this.props.delayShow : this.props.delay;
  
      if (!delay) {
        this.show();
        return;
      }
  
      this._hoverDelay = setTimeout(function () {
        _this._hoverDelay = null;
        _this.show();
      }, delay);
    },
  
    handleDelayedHide: function handleDelayedHide() {
      var _this2 = this;
  
      if (this._hoverDelay != null) {
        clearTimeout(this._hoverDelay);
        this._hoverDelay = null;
        return;
      }
  
      var delay = this.props.delayHide != null ? this.props.delayHide : this.props.delay;
  
      if (!delay) {
        this.hide();
        return;
      }
  
      this._hoverDelay = setTimeout(function () {
        _this2._hoverDelay = null;
        _this2.hide();
      }, delay);
    },
  
    // Simple implementation of mouseEnter and mouseLeave.
    // React's built version is broken: https://github.com/facebook/react/issues/4251
    // for cases when the trigger is disabled and mouseOut/Over can cause flicker moving
    // from one child element to another.
    handleMouseOverOut: function handleMouseOverOut(handler, e) {
      var target = e.currentTarget;
      var related = e.relatedTarget || e.nativeEvent.toElement;
  
      if (!related || related !== target && !_domHelpersQueryContains2['default'](target, related)) {
        handler(e);
      }
    }
  
  });
  
  /**
   * Creates a new OverlayTrigger class that forwards the relevant context
   *
   * This static method should only be called at the module level, instead of in
   * e.g. a render() method, because it's expensive to create new classes.
   *
   * For example, you would want to have:
   *
   * > export default OverlayTrigger.withContext({
   * >   myContextKey: React.PropTypes.object
   * > });
   *
   * and import this when needed.
   */
  OverlayTrigger.withContext = _utilsCreateContextWrapper2['default'](OverlayTrigger, 'overlay');
  
  exports['default'] = OverlayTrigger;
  module.exports = exports['default'];