You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							356 lines
						
					
					
						
							11 KiB
						
					
					
				
			
		
		
	
	
							356 lines
						
					
					
						
							11 KiB
						
					
					
				'use strict';Object.defineProperty(exports,'__esModule',{value:true});var react=require('react'),reactDom=require('react-dom');function _inheritsLoose(subClass, superClass) {
 | 
						|
  subClass.prototype = Object.create(superClass.prototype);
 | 
						|
  subClass.prototype.constructor = subClass;
 | 
						|
 | 
						|
  _setPrototypeOf(subClass, superClass);
 | 
						|
}
 | 
						|
 | 
						|
function _setPrototypeOf(o, p) {
 | 
						|
  _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
 | 
						|
    o.__proto__ = p;
 | 
						|
    return o;
 | 
						|
  };
 | 
						|
 | 
						|
  return _setPrototypeOf(o, p);
 | 
						|
}
 | 
						|
 | 
						|
function _objectWithoutPropertiesLoose(source, excluded) {
 | 
						|
  if (source == null) return {};
 | 
						|
  var target = {};
 | 
						|
  var sourceKeys = Object.keys(source);
 | 
						|
  var key, i;
 | 
						|
 | 
						|
  for (i = 0; i < sourceKeys.length; i++) {
 | 
						|
    key = sourceKeys[i];
 | 
						|
    if (excluded.indexOf(key) >= 0) continue;
 | 
						|
    target[key] = source[key];
 | 
						|
  }
 | 
						|
 | 
						|
  return target;
 | 
						|
}
 | 
						|
 | 
						|
function _assertThisInitialized(self) {
 | 
						|
  if (self === void 0) {
 | 
						|
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
 | 
						|
  }
 | 
						|
 | 
						|
  return self;
 | 
						|
}/**
 | 
						|
 * Check whether some DOM node is our Component's node.
 | 
						|
 */
 | 
						|
function isNodeFound(current, componentNode, ignoreClass) {
 | 
						|
  if (current === componentNode) {
 | 
						|
    return true;
 | 
						|
  } // SVG <use/> elements do not technically reside in the rendered DOM, so
 | 
						|
  // they do not have classList directly, but they offer a link to their
 | 
						|
  // corresponding element, which can have classList. This extra check is for
 | 
						|
  // that case.
 | 
						|
  // See: http://www.w3.org/TR/SVG11/struct.html#InterfaceSVGUseElement
 | 
						|
  // Discussion: https://github.com/Pomax/react-onclickoutside/pull/17
 | 
						|
 | 
						|
 | 
						|
  if (current.correspondingElement) {
 | 
						|
    return current.correspondingElement.classList.contains(ignoreClass);
 | 
						|
  }
 | 
						|
 | 
						|
  return current.classList.contains(ignoreClass);
 | 
						|
}
 | 
						|
/**
 | 
						|
 * Try to find our node in a hierarchy of nodes, returning the document
 | 
						|
 * node as highest node if our node is not found in the path up.
 | 
						|
 */
 | 
						|
 | 
						|
function findHighest(current, componentNode, ignoreClass) {
 | 
						|
  if (current === componentNode) {
 | 
						|
    return true;
 | 
						|
  } // If source=local then this event came from 'somewhere'
 | 
						|
  // inside and should be ignored. We could handle this with
 | 
						|
  // a layered approach, too, but that requires going back to
 | 
						|
  // thinking in terms of Dom node nesting, running counter
 | 
						|
  // to React's 'you shouldn't care about the DOM' philosophy.
 | 
						|
  // Also cover shadowRoot node by checking current.host
 | 
						|
 | 
						|
 | 
						|
  while (current.parentNode || current.host) {
 | 
						|
    // Only check normal node without shadowRoot
 | 
						|
    if (current.parentNode && isNodeFound(current, componentNode, ignoreClass)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
 | 
						|
    current = current.parentNode || current.host;
 | 
						|
  }
 | 
						|
 | 
						|
  return current;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * Check if the browser scrollbar was clicked
 | 
						|
 */
 | 
						|
 | 
						|
function clickedScrollbar(evt) {
 | 
						|
  return document.documentElement.clientWidth <= evt.clientX || document.documentElement.clientHeight <= evt.clientY;
 | 
						|
}// ideally will get replaced with external dep
 | 
						|
// when rafrex/detect-passive-events#4 and rafrex/detect-passive-events#5 get merged in
 | 
						|
var testPassiveEventSupport = function testPassiveEventSupport() {
 | 
						|
  if (typeof window === 'undefined' || typeof window.addEventListener !== 'function') {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  var passive = false;
 | 
						|
  var options = Object.defineProperty({}, 'passive', {
 | 
						|
    get: function get() {
 | 
						|
      passive = true;
 | 
						|
    }
 | 
						|
  });
 | 
						|
 | 
						|
  var noop = function noop() {};
 | 
						|
 | 
						|
  window.addEventListener('testPassiveEventSupport', noop, options);
 | 
						|
  window.removeEventListener('testPassiveEventSupport', noop, options);
 | 
						|
  return passive;
 | 
						|
};function autoInc(seed) {
 | 
						|
  if (seed === void 0) {
 | 
						|
    seed = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  return function () {
 | 
						|
    return ++seed;
 | 
						|
  };
 | 
						|
}
 | 
						|
 | 
						|
var uid = autoInc();var passiveEventSupport;
 | 
						|
var handlersMap = {};
 | 
						|
var enabledInstances = {};
 | 
						|
var touchEvents = ['touchstart', 'touchmove'];
 | 
						|
var IGNORE_CLASS_NAME = 'ignore-react-onclickoutside';
 | 
						|
/**
 | 
						|
 * Options for addEventHandler and removeEventHandler
 | 
						|
 */
 | 
						|
 | 
						|
function getEventHandlerOptions(instance, eventName) {
 | 
						|
  var handlerOptions = null;
 | 
						|
  var isTouchEvent = touchEvents.indexOf(eventName) !== -1;
 | 
						|
 | 
						|
  if (isTouchEvent && passiveEventSupport) {
 | 
						|
    handlerOptions = {
 | 
						|
      passive: !instance.props.preventDefault
 | 
						|
    };
 | 
						|
  }
 | 
						|
 | 
						|
  return handlerOptions;
 | 
						|
}
 | 
						|
/**
 | 
						|
 * This function generates the HOC function that you'll use
 | 
						|
 * in order to impart onOutsideClick listening to an
 | 
						|
 * arbitrary component. It gets called at the end of the
 | 
						|
 * bootstrapping code to yield an instance of the
 | 
						|
 * onClickOutsideHOC function defined inside setupHOC().
 | 
						|
 */
 | 
						|
 | 
						|
 | 
						|
function onClickOutsideHOC(WrappedComponent, config) {
 | 
						|
  var _class, _temp;
 | 
						|
 | 
						|
  var componentName = WrappedComponent.displayName || WrappedComponent.name || 'Component';
 | 
						|
  return _temp = _class = /*#__PURE__*/function (_Component) {
 | 
						|
    _inheritsLoose(onClickOutside, _Component);
 | 
						|
 | 
						|
    function onClickOutside(props) {
 | 
						|
      var _this;
 | 
						|
 | 
						|
      _this = _Component.call(this, props) || this;
 | 
						|
 | 
						|
      _this.__outsideClickHandler = function (event) {
 | 
						|
        if (typeof _this.__clickOutsideHandlerProp === 'function') {
 | 
						|
          _this.__clickOutsideHandlerProp(event);
 | 
						|
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        var instance = _this.getInstance();
 | 
						|
 | 
						|
        if (typeof instance.props.handleClickOutside === 'function') {
 | 
						|
          instance.props.handleClickOutside(event);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof instance.handleClickOutside === 'function') {
 | 
						|
          instance.handleClickOutside(event);
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        throw new Error("WrappedComponent: " + componentName + " lacks a handleClickOutside(event) function for processing outside click events.");
 | 
						|
      };
 | 
						|
 | 
						|
      _this.__getComponentNode = function () {
 | 
						|
        var instance = _this.getInstance();
 | 
						|
 | 
						|
        if (config && typeof config.setClickOutsideRef === 'function') {
 | 
						|
          return config.setClickOutsideRef()(instance);
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof instance.setClickOutsideRef === 'function') {
 | 
						|
          return instance.setClickOutsideRef();
 | 
						|
        }
 | 
						|
 | 
						|
        return reactDom.findDOMNode(instance);
 | 
						|
      };
 | 
						|
 | 
						|
      _this.enableOnClickOutside = function () {
 | 
						|
        if (typeof document === 'undefined' || enabledInstances[_this._uid]) {
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        if (typeof passiveEventSupport === 'undefined') {
 | 
						|
          passiveEventSupport = testPassiveEventSupport();
 | 
						|
        }
 | 
						|
 | 
						|
        enabledInstances[_this._uid] = true;
 | 
						|
        var events = _this.props.eventTypes;
 | 
						|
 | 
						|
        if (!events.forEach) {
 | 
						|
          events = [events];
 | 
						|
        }
 | 
						|
 | 
						|
        handlersMap[_this._uid] = function (event) {
 | 
						|
          if (_this.componentNode === null) return;
 | 
						|
 | 
						|
          if (_this.props.preventDefault) {
 | 
						|
            event.preventDefault();
 | 
						|
          }
 | 
						|
 | 
						|
          if (_this.props.stopPropagation) {
 | 
						|
            event.stopPropagation();
 | 
						|
          }
 | 
						|
 | 
						|
          if (_this.props.excludeScrollbar && clickedScrollbar(event)) return;
 | 
						|
          var current = event.composed && event.composedPath && event.composedPath().shift() || event.target;
 | 
						|
 | 
						|
          if (findHighest(current, _this.componentNode, _this.props.outsideClickIgnoreClass) !== document) {
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          _this.__outsideClickHandler(event);
 | 
						|
        };
 | 
						|
 | 
						|
        events.forEach(function (eventName) {
 | 
						|
          document.addEventListener(eventName, handlersMap[_this._uid], getEventHandlerOptions(_assertThisInitialized(_this), eventName));
 | 
						|
        });
 | 
						|
      };
 | 
						|
 | 
						|
      _this.disableOnClickOutside = function () {
 | 
						|
        delete enabledInstances[_this._uid];
 | 
						|
        var fn = handlersMap[_this._uid];
 | 
						|
 | 
						|
        if (fn && typeof document !== 'undefined') {
 | 
						|
          var events = _this.props.eventTypes;
 | 
						|
 | 
						|
          if (!events.forEach) {
 | 
						|
            events = [events];
 | 
						|
          }
 | 
						|
 | 
						|
          events.forEach(function (eventName) {
 | 
						|
            return document.removeEventListener(eventName, fn, getEventHandlerOptions(_assertThisInitialized(_this), eventName));
 | 
						|
          });
 | 
						|
          delete handlersMap[_this._uid];
 | 
						|
        }
 | 
						|
      };
 | 
						|
 | 
						|
      _this.getRef = function (ref) {
 | 
						|
        return _this.instanceRef = ref;
 | 
						|
      };
 | 
						|
 | 
						|
      _this._uid = uid();
 | 
						|
      return _this;
 | 
						|
    }
 | 
						|
    /**
 | 
						|
     * Access the WrappedComponent's instance.
 | 
						|
     */
 | 
						|
 | 
						|
 | 
						|
    var _proto = onClickOutside.prototype;
 | 
						|
 | 
						|
    _proto.getInstance = function getInstance() {
 | 
						|
      if (WrappedComponent.prototype && !WrappedComponent.prototype.isReactComponent) {
 | 
						|
        return this;
 | 
						|
      }
 | 
						|
 | 
						|
      var ref = this.instanceRef;
 | 
						|
      return ref.getInstance ? ref.getInstance() : ref;
 | 
						|
    };
 | 
						|
 | 
						|
    /**
 | 
						|
     * Add click listeners to the current document,
 | 
						|
     * linked to this component's state.
 | 
						|
     */
 | 
						|
    _proto.componentDidMount = function componentDidMount() {
 | 
						|
      // If we are in an environment without a DOM such
 | 
						|
      // as shallow rendering or snapshots then we exit
 | 
						|
      // early to prevent any unhandled errors being thrown.
 | 
						|
      if (typeof document === 'undefined' || !document.createElement) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      var instance = this.getInstance();
 | 
						|
 | 
						|
      if (config && typeof config.handleClickOutside === 'function') {
 | 
						|
        this.__clickOutsideHandlerProp = config.handleClickOutside(instance);
 | 
						|
 | 
						|
        if (typeof this.__clickOutsideHandlerProp !== 'function') {
 | 
						|
          throw new Error("WrappedComponent: " + componentName + " lacks a function for processing outside click events specified by the handleClickOutside config option.");
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      this.componentNode = this.__getComponentNode(); // return early so we dont initiate onClickOutside
 | 
						|
 | 
						|
      if (this.props.disableOnClickOutside) return;
 | 
						|
      this.enableOnClickOutside();
 | 
						|
    };
 | 
						|
 | 
						|
    _proto.componentDidUpdate = function componentDidUpdate() {
 | 
						|
      this.componentNode = this.__getComponentNode();
 | 
						|
    }
 | 
						|
    /**
 | 
						|
     * Remove all document's event listeners for this component
 | 
						|
     */
 | 
						|
    ;
 | 
						|
 | 
						|
    _proto.componentWillUnmount = function componentWillUnmount() {
 | 
						|
      this.disableOnClickOutside();
 | 
						|
    }
 | 
						|
    /**
 | 
						|
     * Can be called to explicitly enable event listening
 | 
						|
     * for clicks and touches outside of this element.
 | 
						|
     */
 | 
						|
    ;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Pass-through render
 | 
						|
     */
 | 
						|
    _proto.render = function render() {
 | 
						|
      // eslint-disable-next-line no-unused-vars
 | 
						|
      var _this$props = this.props;
 | 
						|
          _this$props.excludeScrollbar;
 | 
						|
          var props = _objectWithoutPropertiesLoose(_this$props, ["excludeScrollbar"]);
 | 
						|
 | 
						|
      if (WrappedComponent.prototype && WrappedComponent.prototype.isReactComponent) {
 | 
						|
        props.ref = this.getRef;
 | 
						|
      } else {
 | 
						|
        props.wrappedRef = this.getRef;
 | 
						|
      }
 | 
						|
 | 
						|
      props.disableOnClickOutside = this.disableOnClickOutside;
 | 
						|
      props.enableOnClickOutside = this.enableOnClickOutside;
 | 
						|
      return react.createElement(WrappedComponent, props);
 | 
						|
    };
 | 
						|
 | 
						|
    return onClickOutside;
 | 
						|
  }(react.Component), _class.displayName = "OnClickOutside(" + componentName + ")", _class.defaultProps = {
 | 
						|
    eventTypes: ['mousedown', 'touchstart'],
 | 
						|
    excludeScrollbar: config && config.excludeScrollbar || false,
 | 
						|
    outsideClickIgnoreClass: IGNORE_CLASS_NAME,
 | 
						|
    preventDefault: false,
 | 
						|
    stopPropagation: false
 | 
						|
  }, _class.getClass = function () {
 | 
						|
    return WrappedComponent.getClass ? WrappedComponent.getClass() : WrappedComponent;
 | 
						|
  }, _temp;
 | 
						|
}exports.IGNORE_CLASS_NAME=IGNORE_CLASS_NAME;exports.default=onClickOutsideHOC; |