content: /*! ReactInstantSearch 4.1.0-beta.2 | © Algolia, inc. | https://community.algolia.com/react-instantsearch/ */
  (function webpackUniversalModuleDefinition(root, factory) {
  	if(typeof exports === 'object' && typeof module === 'object')
  		module.exports = factory(require("react"));
  	else if(typeof define === 'function' && define.amd)
  		define(["react"], factory);
  	else if(typeof exports === 'object')
  		exports["Connectors"] = factory(require("react"));
  	else
  		root["ReactInstantSearch"] = root["ReactInstantSearch"] || {}, root["ReactInstantSearch"]["Connectors"] = factory(root["React"]);
  })(this, function(__WEBPACK_EXTERNAL_MODULE_4__) {
  return /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId]) {
  /******/ 			return installedModules[moduleId].exports;
  /******/ 		}
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			i: moduleId,
  /******/ 			l: false,
  /******/ 			exports: {}
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.l = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  /******/
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  /******/
  /******/ 	// define getter function for harmony exports
  /******/ 	__webpack_require__.d = function(exports, name, getter) {
  /******/ 		if(!__webpack_require__.o(exports, name)) {
  /******/ 			Object.defineProperty(exports, name, {
  /******/ 				configurable: false,
  /******/ 				enumerable: true,
  /******/ 				get: getter
  /******/ 			});
  /******/ 		}
  /******/ 	};
  /******/
  /******/ 	// getDefaultExport function for compatibility with non-harmony modules
  /******/ 	__webpack_require__.n = function(module) {
  /******/ 		var getter = module && module.__esModule ?
  /******/ 			function getDefault() { return module['default']; } :
  /******/ 			function getModuleExports() { return module; };
  /******/ 		__webpack_require__.d(getter, 'a', getter);
  /******/ 		return getter;
  /******/ 	};
  /******/
  /******/ 	// Object.prototype.hasOwnProperty.call
  /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  /******/
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  /******/
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(__webpack_require__.s = 433);
  /******/ })
  /************************************************************************/
  /******/ ([
  /* 0 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is classified as an `Array` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array, else `false`.
   * @example
   *
   * _.isArray([1, 2, 3]);
   * // => true
   *
   * _.isArray(document.body.children);
   * // => false
   *
   * _.isArray('abc');
   * // => false
   *
   * _.isArray(_.noop);
   * // => false
   */
  var isArray = Array.isArray;
  
  module.exports = isArray;
  
  
  /***/ }),
  /* 1 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /**
   * Copyright 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   */
  
  if (false) {
    var REACT_ELEMENT_TYPE = (typeof Symbol === 'function' &&
      Symbol.for &&
      Symbol.for('react.element')) ||
      0xeac7;
  
    var isValidElement = function(object) {
      return typeof object === 'object' &&
        object !== null &&
        object.$$typeof === REACT_ELEMENT_TYPE;
    };
  
    // By explicitly using `prop-types` you are opting into new development behavior.
    // http://fb.me/prop-types-in-prod
    var throwOnDirectAccess = true;
    module.exports = require('./factoryWithTypeCheckers')(isValidElement, throwOnDirectAccess);
  } else {
    // By explicitly using `prop-types` you are opting into new production behavior.
    // http://fb.me/prop-types-in-prod
    module.exports = __webpack_require__(159)();
  }
  
  
  /***/ }),
  /* 2 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _isEqual2 = __webpack_require__(81);
  
  var _isEqual3 = _interopRequireDefault(_isEqual2);
  
  var _has2 = __webpack_require__(57);
  
  var _has3 = _interopRequireDefault(_has2);
  
  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; };
  
  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; }; }();
  
  exports.default = createConnector;
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _react = __webpack_require__(4);
  
  var _react2 = _interopRequireDefault(_react);
  
  var _utils = __webpack_require__(66);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
  
  function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
  
  /**
   * @typedef {object} ConnectorDescription
   * @property {string} displayName - the displayName used by the wrapper
   * @property {function} refine - a function to filter the local state
   * @property {function} getSearchParameters - function transforming the local state to a SearchParameters
   * @property {function} getMetadata - metadata of the widget
   * @property {function} transitionState - hook after the state has changed
   * @property {function} getProvidedProps - transform the state into props passed to the wrapped component.
   * Receives (props, widgetStates, searchState, metadata) and returns the local state.
   * @property {function} getId - Receives props and return the id that will be used to identify the widget
   * @property {function} cleanUp - hook when the widget will unmount. Receives (props, searchState) and return a cleaned state.
   * @property {object} propTypes - PropTypes forwarded to the wrapped component.
   * @property {object} defaultProps - default values for the props
   */
  
  /**
   * Connectors are the HOC used to transform React components
   * into InstantSearch widgets.
   * In order to simplify the construction of such connectors
   * `createConnector` takes a description and transform it into
   * a connector.
   * @param {ConnectorDescription} connectorDesc the description of the connector
   * @return {Connector} a function that wraps a component into
   * an instantsearch connected one.
   */
  function createConnector(connectorDesc) {
    if (!connectorDesc.displayName) {
      throw new Error('`createConnector` requires you to provide a `displayName` property.');
    }
  
    var hasRefine = (0, _has3.default)(connectorDesc, 'refine');
    var hasSearchForFacetValues = (0, _has3.default)(connectorDesc, 'searchForFacetValues');
    var hasSearchParameters = (0, _has3.default)(connectorDesc, 'getSearchParameters');
    var hasMetadata = (0, _has3.default)(connectorDesc, 'getMetadata');
    var hasTransitionState = (0, _has3.default)(connectorDesc, 'transitionState');
    var hasCleanUp = (0, _has3.default)(connectorDesc, 'cleanUp');
    var isWidget = hasSearchParameters || hasMetadata || hasTransitionState;
  
    return function (Composed) {
      var _class, _temp, _initialiseProps;
  
      return _temp = _class = function (_Component) {
        _inherits(Connector, _Component);
  
        function Connector(props, context) {
          _classCallCheck(this, Connector);
  
          var _this = _possibleConstructorReturn(this, (Connector.__proto__ || Object.getPrototypeOf(Connector)).call(this, props, context));
  
          _initialiseProps.call(_this);
  
          var _context$ais = context.ais,
              store = _context$ais.store,
              widgetsManager = _context$ais.widgetsManager,
              multiIndexContext = context.multiIndexContext;
  
          _this.state = {
            props: _this.getProvidedProps(props),
            canRender: false //use to know if a component is rendered (browser), or not (server).
          };
  
          _this.unsubscribe = store.subscribe(function () {
            if (_this.state.canRender) {
              _this.setState({
                props: _this.getProvidedProps(_this.props)
              });
            }
          });
  
          var getSearchParameters = hasSearchParameters ? function (searchParameters) {
            return connectorDesc.getSearchParameters.call(_this, searchParameters, _this.props, store.getState().widgets);
          } : null;
          var getMetadata = hasMetadata ? function (nextWidgetsState) {
            return connectorDesc.getMetadata.call(_this, _this.props, nextWidgetsState);
          } : null;
          var transitionState = hasTransitionState ? function (prevWidgetsState, nextWidgetsState) {
            return connectorDesc.transitionState.call(_this, _this.props, prevWidgetsState, nextWidgetsState);
          } : null;
          if (isWidget) {
            _this.unregisterWidget = widgetsManager.registerWidget({
              getSearchParameters: getSearchParameters,
              getMetadata: getMetadata,
              transitionState: transitionState,
              multiIndexContext: multiIndexContext
            });
          }
          return _this;
        }
  
        _createClass(Connector, [{
          key: 'componentDidMount',
          value: function componentDidMount() {
            this.setState({
              canRender: true
            });
          }
        }, {
          key: 'componentWillMount',
          value: function componentWillMount() {
            if (connectorDesc.getSearchParameters) {
              this.context.ais.onSearchParameters(connectorDesc.getSearchParameters, this.context, this.props);
            }
          }
        }, {
          key: 'componentWillReceiveProps',
          value: function componentWillReceiveProps(nextProps) {
            if (!(0, _isEqual3.default)(this.props, nextProps)) {
              this.setState({
                props: this.getProvidedProps(nextProps)
              });
  
              if (isWidget) {
                // Since props might have changed, we need to re-run getSearchParameters
                // and getMetadata with the new props.
                this.context.ais.widgetsManager.update();
                if (connectorDesc.transitionState) {
                  this.context.ais.onSearchStateChange(connectorDesc.transitionState.call(this, nextProps, this.context.ais.store.getState().widgets, this.context.ais.store.getState().widgets));
                }
              }
            }
          }
        }, {
          key: 'componentWillUnmount',
          value: function componentWillUnmount() {
            this.unsubscribe();
            if (isWidget) {
              this.unregisterWidget(); //will schedule an update
              if (hasCleanUp) {
                var newState = connectorDesc.cleanUp.call(this, this.props, this.context.ais.store.getState().widgets);
                this.context.ais.store.setState(_extends({}, this.context.ais.store.getState(), {
                  widgets: newState
                }));
                this.context.ais.onSearchStateChange((0, _utils.removeEmptyKey)(newState));
              }
            }
          }
        }, {
          key: 'shouldComponentUpdate',
          value: function shouldComponentUpdate(nextProps, nextState) {
            var propsEqual = (0, _utils.shallowEqual)(this.props, nextProps);
            if (this.state.props === null || nextState.props === null) {
              if (this.state.props === nextState.props) {
                return !propsEqual;
              }
              return true;
            }
            return !propsEqual || !(0, _utils.shallowEqual)(this.state.props, nextState.props);
          }
        }, {
          key: 'render',
          value: function render() {
            var _this2 = this;
  
            if (this.state.props === null) {
              return null;
            }
  
            var refineProps = hasRefine ? { refine: this.refine, createURL: this.createURL } : {};
            var searchForFacetValuesProps = hasSearchForFacetValues ? {
              searchForItems: this.searchForFacetValues,
              searchForFacetValues: function searchForFacetValues(facetName, query) {
                if (false) {
                  // eslint-disable-next-line no-console
                  console.warn('react-instantsearch: `searchForFacetValues` has been renamed to' + '`searchForItems`, this will break in the next major version.');
                }
                _this2.searchForFacetValues(facetName, query);
              }
            } : {};
  
            return _react2.default.createElement(Composed, _extends({}, this.props, this.state.props, refineProps, searchForFacetValuesProps));
          }
        }]);
  
        return Connector;
      }(_react.Component), _class.displayName = connectorDesc.displayName + '(' + (0, _utils.getDisplayName)(Composed) + ')', _class.defaultClassNames = Composed.defaultClassNames, _class.propTypes = connectorDesc.propTypes, _class.defaultProps = connectorDesc.defaultProps, _class.contextTypes = {
        // @TODO: more precise state manager propType
        ais: _propTypes2.default.object.isRequired,
        multiIndexContext: _propTypes2.default.object
      }, _initialiseProps = function _initialiseProps() {
        var _this3 = this;
  
        this.getProvidedProps = function (props) {
          var store = _this3.context.ais.store;
  
          var _store$getState = store.getState(),
              results = _store$getState.results,
              searching = _store$getState.searching,
              error = _store$getState.error,
              widgets = _store$getState.widgets,
              metadata = _store$getState.metadata,
              resultsFacetValues = _store$getState.resultsFacetValues,
              searchingForFacetValues = _store$getState.searchingForFacetValues;
  
          var searchState = {
            results: results,
            searching: searching,
            error: error,
            searchingForFacetValues: searchingForFacetValues
          };
          return connectorDesc.getProvidedProps.call(_this3, props, widgets, searchState, metadata, resultsFacetValues);
        };
  
        this.refine = function () {
          var _connectorDesc$refine;
  
          for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
            args[_key] = arguments[_key];
          }
  
          _this3.context.ais.onInternalStateUpdate((_connectorDesc$refine = connectorDesc.refine).call.apply(_connectorDesc$refine, [_this3, _this3.props, _this3.context.ais.store.getState().widgets].concat(args)));
        };
  
        this.searchForFacetValues = function () {
          for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
            args[_key2] = arguments[_key2];
          }
  
          _this3.context.ais.onSearchForFacetValues(connectorDesc.searchForFacetValues.apply(connectorDesc, [_this3.props, _this3.context.ais.store.getState().widgets].concat(args)));
        };
  
        this.createURL = function () {
          var _connectorDesc$refine2;
  
          for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
            args[_key3] = arguments[_key3];
          }
  
          return _this3.context.ais.createHrefForState((_connectorDesc$refine2 = connectorDesc.refine).call.apply(_connectorDesc$refine2, [_this3, _this3.props, _this3.context.ais.store.getState().widgets].concat(args)));
        };
  
        this.cleanUp = function () {
          var _connectorDesc$cleanU;
  
          for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
            args[_key4] = arguments[_key4];
          }
  
          return (_connectorDesc$cleanU = connectorDesc.cleanUp).call.apply(_connectorDesc$cleanU, [_this3].concat(args));
        };
      }, _temp;
    };
  }
  
  /***/ }),
  /* 3 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var freeGlobal = __webpack_require__(76);
  
  /** Detect free variable `self`. */
  var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
  
  /** Used as a reference to the global object. */
  var root = freeGlobal || freeSelf || Function('return this')();
  
  module.exports = root;
  
  
  /***/ }),
  /* 4 */
  /***/ (function(module, exports) {
  
  module.exports = __WEBPACK_EXTERNAL_MODULE_4__;
  
  /***/ }),
  /* 5 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _get2 = __webpack_require__(72);
  
  var _get3 = _interopRequireDefault(_get2);
  
  var _omit2 = __webpack_require__(45);
  
  var _omit3 = _interopRequireDefault(_omit2);
  
  var _has2 = __webpack_require__(57);
  
  var _has3 = _interopRequireDefault(_has2);
  
  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; };
  
  exports.getIndex = getIndex;
  exports.getResults = getResults;
  exports.hasMultipleIndex = hasMultipleIndex;
  exports.refineValue = refineValue;
  exports.getCurrentRefinementValue = getCurrentRefinementValue;
  exports.cleanUpValue = cleanUpValue;
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getIndex(context) {
    return context && context.multiIndexContext ? context.multiIndexContext.targetedIndex : context.ais.mainTargetedIndex;
  }
  
  function getResults(searchResults, context) {
    if (searchResults.results && !searchResults.results.hits) {
      return searchResults.results[getIndex(context)] ? searchResults.results[getIndex(context)] : null;
    } else {
      return searchResults.results ? searchResults.results : null;
    }
  }
  
  function hasMultipleIndex(context) {
    return context && context.multiIndexContext;
  }
  
  // eslint-disable-next-line max-params
  function refineValue(searchState, nextRefinement, context, resetPage, namespace) {
    if (hasMultipleIndex(context)) {
      return namespace ? refineMultiIndexWithNamespace(searchState, nextRefinement, context, resetPage, namespace) : refineMultiIndex(searchState, nextRefinement, context, resetPage);
    } else {
      return namespace ? refineSingleIndexWithNamespace(searchState, nextRefinement, resetPage, namespace) : refineSingleIndex(searchState, nextRefinement, resetPage);
    }
  }
  
  function refineMultiIndex(searchState, nextRefinement, context, resetPage) {
    var page = resetPage ? { page: 1 } : undefined;
    var index = getIndex(context);
    var state = (0, _has3.default)(searchState, 'indices.' + index) ? _extends({}, searchState.indices, _defineProperty({}, index, _extends({}, searchState.indices[index], nextRefinement, page))) : _extends({}, searchState.indices, _defineProperty({}, index, _extends({}, nextRefinement, page)));
    return _extends({}, searchState, { indices: state });
  }
  
  function refineSingleIndex(searchState, nextRefinement, resetPage) {
    var page = resetPage ? { page: 1 } : undefined;
    return _extends({}, searchState, nextRefinement, page);
  }
  
  // eslint-disable-next-line max-params
  function refineMultiIndexWithNamespace(searchState, nextRefinement, context, resetPage, namespace) {
    var _extends4;
  
    var index = getIndex(context);
    var page = resetPage ? { page: 1 } : undefined;
    var state = (0, _has3.default)(searchState, 'indices.' + index) ? _extends({}, searchState.indices, _defineProperty({}, index, _extends({}, searchState.indices[index], (_extends4 = {}, _defineProperty(_extends4, namespace, _extends({}, searchState.indices[index][namespace], nextRefinement)), _defineProperty(_extends4, 'page', 1), _extends4)))) : _extends({}, searchState.indices, _defineProperty({}, index, _extends(_defineProperty({}, namespace, nextRefinement), page)));
    return _extends({}, searchState, { indices: state });
  }
  
  function refineSingleIndexWithNamespace(searchState, nextRefinement, resetPage, namespace) {
    var page = resetPage ? { page: 1 } : undefined;
    return _extends({}, searchState, _defineProperty({}, namespace, _extends({}, searchState[namespace], nextRefinement)), page);
  }
  
  function getNamespaceAndAttributeName(id) {
    var parts = id.match(/^([^.]*)\.(.*)/);
    var namespace = parts && parts[1];
    var attributeName = parts && parts[2];
  
    return { namespace: namespace, attributeName: attributeName };
  }
  
  // eslint-disable-next-line max-params
  function getCurrentRefinementValue(props, searchState, context, id, defaultValue, refinementsCallback) {
    var index = getIndex(context);
  
    var _getNamespaceAndAttri = getNamespaceAndAttributeName(id),
        namespace = _getNamespaceAndAttri.namespace,
        attributeName = _getNamespaceAndAttri.attributeName;
  
    var refinements = hasMultipleIndex(context) && searchState.indices && namespace && searchState.indices['' + index] && (0, _has3.default)(searchState.indices['' + index][namespace], '' + attributeName) || hasMultipleIndex(context) && searchState.indices && (0, _has3.default)(searchState, 'indices.' + index + '.' + id) || !hasMultipleIndex(context) && namespace && (0, _has3.default)(searchState[namespace], attributeName) || !hasMultipleIndex(context) && (0, _has3.default)(searchState, id);
    if (refinements) {
      var currentRefinement = void 0;
  
      if (hasMultipleIndex(context)) {
        currentRefinement = namespace ? (0, _get3.default)(searchState.indices['' + index][namespace], attributeName) : (0, _get3.default)(searchState.indices[index], id);
      } else {
        currentRefinement = namespace ? (0, _get3.default)(searchState[namespace], attributeName) : (0, _get3.default)(searchState, id);
      }
  
      return refinementsCallback(currentRefinement);
    }
  
    if (props.defaultRefinement) {
      return props.defaultRefinement;
    }
  
    return defaultValue;
  }
  
  function cleanUpValue(searchState, context, id) {
    var index = getIndex(context);
  
    var _getNamespaceAndAttri2 = getNamespaceAndAttributeName(id),
        namespace = _getNamespaceAndAttri2.namespace,
        attributeName = _getNamespaceAndAttri2.attributeName;
  
    if (hasMultipleIndex(context)) {
      return namespace ? _extends({}, searchState, {
        indices: _extends({}, searchState.indices, _defineProperty({}, index, _extends({}, searchState.indices[index], _defineProperty({}, namespace, (0, _omit3.default)(searchState.indices[index][namespace], '' + attributeName)))))
      }) : (0, _omit3.default)(searchState, 'indices.' + index + '.' + id);
    } else {
      return namespace ? _extends({}, searchState, _defineProperty({}, namespace, (0, _omit3.default)(searchState[namespace], '' + attributeName))) : (0, _omit3.default)(searchState, '' + id);
    }
  }
  
  /***/ }),
  /* 6 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is the
   * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
   * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(_.noop);
   * // => true
   *
   * _.isObject(null);
   * // => false
   */
  function isObject(value) {
    var type = typeof value;
    return value != null && (type == 'object' || type == 'function');
  }
  
  module.exports = isObject;
  
  
  /***/ }),
  /* 7 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is object-like. A value is object-like if it's not `null`
   * and has a `typeof` result of "object".
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   * @example
   *
   * _.isObjectLike({});
   * // => true
   *
   * _.isObjectLike([1, 2, 3]);
   * // => true
   *
   * _.isObjectLike(_.noop);
   * // => false
   *
   * _.isObjectLike(null);
   * // => false
   */
  function isObjectLike(value) {
    return value != null && typeof value == 'object';
  }
  
  module.exports = isObjectLike;
  
  
  /***/ }),
  /* 8 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14),
      getRawTag = __webpack_require__(124),
      objectToString = __webpack_require__(125);
  
  /** `Object#toString` result references. */
  var nullTag = '[object Null]',
      undefinedTag = '[object Undefined]';
  
  /** Built-in value references. */
  var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
  
  /**
   * The base implementation of `getTag` without fallbacks for buggy environments.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  function baseGetTag(value) {
    if (value == null) {
      return value === undefined ? undefinedTag : nullTag;
    }
    return (symToStringTag && symToStringTag in Object(value))
      ? getRawTag(value)
      : objectToString(value);
  }
  
  module.exports = baseGetTag;
  
  
  /***/ }),
  /* 9 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayLikeKeys = __webpack_require__(89),
      baseKeys = __webpack_require__(79),
      isArrayLike = __webpack_require__(11);
  
  /**
   * Creates an array of the own enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects. See the
   * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
   * for more details.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keys(new Foo);
   * // => ['a', 'b'] (iteration order is not guaranteed)
   *
   * _.keys('hi');
   * // => ['0', '1']
   */
  function keys(object) {
    return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
  }
  
  module.exports = keys;
  
  
  /***/ }),
  /* 10 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsNative = __webpack_require__(123),
      getValue = __webpack_require__(128);
  
  /**
   * Gets the native function at `key` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {string} key The key of the method to get.
   * @returns {*} Returns the function if it's native, else `undefined`.
   */
  function getNative(object, key) {
    var value = getValue(object, key);
    return baseIsNative(value) ? value : undefined;
  }
  
  module.exports = getNative;
  
  
  /***/ }),
  /* 11 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isFunction = __webpack_require__(19),
      isLength = __webpack_require__(41);
  
  /**
   * Checks if `value` is array-like. A value is considered array-like if it's
   * not a function and has a `value.length` that's an integer greater than or
   * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   * @example
   *
   * _.isArrayLike([1, 2, 3]);
   * // => true
   *
   * _.isArrayLike(document.body.children);
   * // => true
   *
   * _.isArrayLike('abc');
   * // => true
   *
   * _.isArrayLike(_.noop);
   * // => false
   */
  function isArrayLike(value) {
    return value != null && isLength(value.length) && !isFunction(value);
  }
  
  module.exports = isArrayLike;
  
  
  /***/ }),
  /* 12 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.map` for arrays without support for iteratee
   * shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the new mapped array.
   */
  function arrayMap(array, iteratee) {
    var index = -1,
        length = array == null ? 0 : array.length,
        result = Array(length);
  
    while (++index < length) {
      result[index] = iteratee(array[index], index, array);
    }
    return result;
  }
  
  module.exports = arrayMap;
  
  
  /***/ }),
  /* 13 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseMatches = __webpack_require__(256),
      baseMatchesProperty = __webpack_require__(259),
      identity = __webpack_require__(26),
      isArray = __webpack_require__(0),
      property = __webpack_require__(261);
  
  /**
   * The base implementation of `_.iteratee`.
   *
   * @private
   * @param {*} [value=_.identity] The value to convert to an iteratee.
   * @returns {Function} Returns the iteratee.
   */
  function baseIteratee(value) {
    // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
    // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
    if (typeof value == 'function') {
      return value;
    }
    if (value == null) {
      return identity;
    }
    if (typeof value == 'object') {
      return isArray(value)
        ? baseMatchesProperty(value[0], value[1])
        : baseMatches(value);
    }
    return property(value);
  }
  
  module.exports = baseIteratee;
  
  
  /***/ }),
  /* 14 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var root = __webpack_require__(3);
  
  /** Built-in value references. */
  var Symbol = root.Symbol;
  
  module.exports = Symbol;
  
  
  /***/ }),
  /* 15 */,
  /* 16 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseKeys = __webpack_require__(79),
      getTag = __webpack_require__(56),
      isArguments = __webpack_require__(20),
      isArray = __webpack_require__(0),
      isArrayLike = __webpack_require__(11),
      isBuffer = __webpack_require__(21),
      isPrototype = __webpack_require__(37),
      isTypedArray = __webpack_require__(33);
  
  /** `Object#toString` result references. */
  var mapTag = '[object Map]',
      setTag = '[object Set]';
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Checks if `value` is an empty object, collection, map, or set.
   *
   * Objects are considered empty if they have no own enumerable string keyed
   * properties.
   *
   * Array-like values such as `arguments` objects, arrays, buffers, strings, or
   * jQuery-like collections are considered empty if they have a `length` of `0`.
   * Similarly, maps and sets are considered empty if they have a `size` of `0`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is empty, else `false`.
   * @example
   *
   * _.isEmpty(null);
   * // => true
   *
   * _.isEmpty(true);
   * // => true
   *
   * _.isEmpty(1);
   * // => true
   *
   * _.isEmpty([1, 2, 3]);
   * // => false
   *
   * _.isEmpty({ 'a': 1 });
   * // => false
   */
  function isEmpty(value) {
    if (value == null) {
      return true;
    }
    if (isArrayLike(value) &&
        (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
          isBuffer(value) || isTypedArray(value) || isArguments(value))) {
      return !value.length;
    }
    var tag = getTag(value);
    if (tag == mapTag || tag == setTag) {
      return !value.size;
    }
    if (isPrototype(value)) {
      return !baseKeys(value).length;
    }
    for (var key in value) {
      if (hasOwnProperty.call(value, key)) {
        return false;
      }
    }
    return true;
  }
  
  module.exports = isEmpty;
  
  
  /***/ }),
  /* 17 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12),
      baseIteratee = __webpack_require__(13),
      baseMap = __webpack_require__(183),
      isArray = __webpack_require__(0);
  
  /**
   * Creates an array of values by running each element in `collection` thru
   * `iteratee`. The iteratee is invoked with three arguments:
   * (value, index|key, collection).
   *
   * Many lodash methods are guarded to work as iteratees for methods like
   * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
   *
   * The guarded methods are:
   * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
   * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
   * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
   * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Collection
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @returns {Array} Returns the new mapped array.
   * @example
   *
   * function square(n) {
   *   return n * n;
   * }
   *
   * _.map([4, 8], square);
   * // => [16, 64]
   *
   * _.map({ 'a': 4, 'b': 8 }, square);
   * // => [16, 64] (iteration order is not guaranteed)
   *
   * var users = [
   *   { 'user': 'barney' },
   *   { 'user': 'fred' }
   * ];
   *
   * // The `_.property` iteratee shorthand.
   * _.map(users, 'user');
   * // => ['barney', 'fred']
   */
  function map(collection, iteratee) {
    var func = isArray(collection) ? arrayMap : baseMap;
    return func(collection, baseIteratee(iteratee, 3));
  }
  
  module.exports = map;
  
  
  /***/ }),
  /* 18 */
  /***/ (function(module, exports) {
  
  /**
   * Performs a
   * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * comparison between two values to determine if they are equivalent.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   * @example
   *
   * var object = { 'a': 1 };
   * var other = { 'a': 1 };
   *
   * _.eq(object, object);
   * // => true
   *
   * _.eq(object, other);
   * // => false
   *
   * _.eq('a', 'a');
   * // => true
   *
   * _.eq('a', Object('a'));
   * // => false
   *
   * _.eq(NaN, NaN);
   * // => true
   */
  function eq(value, other) {
    return value === other || (value !== value && other !== other);
  }
  
  module.exports = eq;
  
  
  /***/ }),
  /* 19 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isObject = __webpack_require__(6);
  
  /** `Object#toString` result references. */
  var asyncTag = '[object AsyncFunction]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]',
      proxyTag = '[object Proxy]';
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a function, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    if (!isObject(value)) {
      return false;
    }
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in Safari 9 which returns 'object' for typed arrays and other constructors.
    var tag = baseGetTag(value);
    return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
  }
  
  module.exports = isFunction;
  
  
  /***/ }),
  /* 20 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsArguments = __webpack_require__(147),
      isObjectLike = __webpack_require__(7);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /** Built-in value references. */
  var propertyIsEnumerable = objectProto.propertyIsEnumerable;
  
  /**
   * Checks if `value` is likely an `arguments` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   *  else `false`.
   * @example
   *
   * _.isArguments(function() { return arguments; }());
   * // => true
   *
   * _.isArguments([1, 2, 3]);
   * // => false
   */
  var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
    return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
      !propertyIsEnumerable.call(value, 'callee');
  };
  
  module.exports = isArguments;
  
  
  /***/ }),
  /* 21 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(3),
      stubFalse = __webpack_require__(148);
  
  /** Detect free variable `exports`. */
  var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
  
  /** Detect free variable `module`. */
  var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
  
  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;
  
  /** Built-in value references. */
  var Buffer = moduleExports ? root.Buffer : undefined;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined;
  
  /**
   * Checks if `value` is a buffer.
   *
   * @static
   * @memberOf _
   * @since 4.3.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
   * @example
   *
   * _.isBuffer(new Buffer(2));
   * // => true
   *
   * _.isBuffer(new Uint8Array(2));
   * // => false
   */
  var isBuffer = nativeIsBuffer || stubFalse;
  
  module.exports = isBuffer;
  
  /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(55)(module)))
  
  /***/ }),
  /* 22 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isArray = __webpack_require__(0),
      isKey = __webpack_require__(63),
      stringToPath = __webpack_require__(156),
      toString = __webpack_require__(64);
  
  /**
   * Casts `value` to a path array if it's not one.
   *
   * @private
   * @param {*} value The value to inspect.
   * @param {Object} [object] The object to query keys on.
   * @returns {Array} Returns the cast property path array.
   */
  function castPath(value, object) {
    if (isArray(value)) {
      return value;
    }
    return isKey(value, object) ? [value] : stringToPath(toString(value));
  }
  
  module.exports = castPath;
  
  
  /***/ }),
  /* 23 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var symbolTag = '[object Symbol]';
  
  /**
   * Checks if `value` is classified as a `Symbol` primitive or object.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
   * @example
   *
   * _.isSymbol(Symbol.iterator);
   * // => true
   *
   * _.isSymbol('abc');
   * // => false
   */
  function isSymbol(value) {
    return typeof value == 'symbol' ||
      (isObjectLike(value) && baseGetTag(value) == symbolTag);
  }
  
  module.exports = isSymbol;
  
  
  /***/ }),
  /* 24 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isSymbol = __webpack_require__(23);
  
  /** Used as references for various `Number` constants. */
  var INFINITY = 1 / 0;
  
  /**
   * Converts `value` to a string key if it's not a string or symbol.
   *
   * @private
   * @param {*} value The value to inspect.
   * @returns {string|symbol} Returns the key.
   */
  function toKey(value) {
    if (typeof value == 'string' || isSymbol(value)) {
      return value;
    }
    var result = (value + '');
    return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  }
  
  module.exports = toKey;
  
  
  /***/ }),
  /* 25 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var identity = __webpack_require__(26),
      overRest = __webpack_require__(166),
      setToString = __webpack_require__(93);
  
  /**
   * The base implementation of `_.rest` which doesn't validate or coerce arguments.
   *
   * @private
   * @param {Function} func The function to apply a rest parameter to.
   * @param {number} [start=func.length-1] The start position of the rest parameter.
   * @returns {Function} Returns the new function.
   */
  function baseRest(func, start) {
    return setToString(overRest(func, start, identity), func + '');
  }
  
  module.exports = baseRest;
  
  
  /***/ }),
  /* 26 */
  /***/ (function(module, exports) {
  
  /**
   * This method returns the first argument it receives.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Util
   * @param {*} value Any value.
   * @returns {*} Returns `value`.
   * @example
   *
   * var object = { 'a': 1 };
   *
   * console.log(_.identity(object) === object);
   * // => true
   */
  function identity(value) {
    return value;
  }
  
  module.exports = identity;
  
  
  /***/ }),
  /* 27 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assignValue = __webpack_require__(96),
      baseAssignValue = __webpack_require__(46);
  
  /**
   * Copies properties of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy properties from.
   * @param {Array} props The property identifiers to copy.
   * @param {Object} [object={}] The object to copy properties to.
   * @param {Function} [customizer] The function to customize copied values.
   * @returns {Object} Returns `object`.
   */
  function copyObject(source, props, object, customizer) {
    var isNew = !object;
    object || (object = {});
  
    var index = -1,
        length = props.length;
  
    while (++index < length) {
      var key = props[index];
  
      var newValue = customizer
        ? customizer(object[key], source[key], key, object, source)
        : undefined;
  
      if (newValue === undefined) {
        newValue = source[key];
      }
      if (isNew) {
        baseAssignValue(object, key, newValue);
      } else {
        assignValue(object, key, newValue);
      }
    }
    return object;
  }
  
  module.exports = copyObject;
  
  
  /***/ }),
  /* 28 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var listCacheClear = __webpack_require__(113),
      listCacheDelete = __webpack_require__(114),
      listCacheGet = __webpack_require__(115),
      listCacheHas = __webpack_require__(116),
      listCacheSet = __webpack_require__(117);
  
  /**
   * Creates an list cache object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function ListCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  // Add methods to `ListCache`.
  ListCache.prototype.clear = listCacheClear;
  ListCache.prototype['delete'] = listCacheDelete;
  ListCache.prototype.get = listCacheGet;
  ListCache.prototype.has = listCacheHas;
  ListCache.prototype.set = listCacheSet;
  
  module.exports = ListCache;
  
  
  /***/ }),
  /* 29 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var eq = __webpack_require__(18);
  
  /**
   * Gets the index at which the `key` is found in `array` of key-value pairs.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} key The key to search for.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function assocIndexOf(array, key) {
    var length = array.length;
    while (length--) {
      if (eq(array[length][0], key)) {
        return length;
      }
    }
    return -1;
  }
  
  module.exports = assocIndexOf;
  
  
  /***/ }),
  /* 30 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10);
  
  /* Built-in method references that are verified to be native. */
  var nativeCreate = getNative(Object, 'create');
  
  module.exports = nativeCreate;
  
  
  /***/ }),
  /* 31 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isKeyable = __webpack_require__(137);
  
  /**
   * Gets the data for `map`.
   *
   * @private
   * @param {Object} map The map to query.
   * @param {string} key The reference key.
   * @returns {*} Returns the map data.
   */
  function getMapData(map, key) {
    var data = map.__data__;
    return isKeyable(key)
      ? data[typeof key == 'string' ? 'string' : 'hash']
      : data.map;
  }
  
  module.exports = getMapData;
  
  
  /***/ }),
  /* 32 */
  /***/ (function(module, exports) {
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^(?:0|[1-9]\d*)$/;
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    length = length == null ? MAX_SAFE_INTEGER : length;
    return !!length &&
      (typeof value == 'number' || reIsUint.test(value)) &&
      (value > -1 && value % 1 == 0 && value < length);
  }
  
  module.exports = isIndex;
  
  
  /***/ }),
  /* 33 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsTypedArray = __webpack_require__(149),
      baseUnary = __webpack_require__(42),
      nodeUtil = __webpack_require__(150);
  
  /* Node.js helper references. */
  var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
  
  /**
   * Checks if `value` is classified as a typed array.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
   * @example
   *
   * _.isTypedArray(new Uint8Array);
   * // => true
   *
   * _.isTypedArray([]);
   * // => false
   */
  var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
  
  module.exports = isTypedArray;
  
  
  /***/ }),
  /* 34 */,
  /* 35 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayEach = __webpack_require__(95),
      baseEach = __webpack_require__(73),
      castFunction = __webpack_require__(179),
      isArray = __webpack_require__(0);
  
  /**
   * Iterates over elements of `collection` and invokes `iteratee` for each element.
   * The iteratee is invoked with three arguments: (value, index|key, collection).
   * Iteratee functions may exit iteration early by explicitly returning `false`.
   *
   * **Note:** As with other "Collections" methods, objects with a "length"
   * property are iterated like arrays. To avoid this behavior use `_.forIn`
   * or `_.forOwn` for object iteration.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @alias each
   * @category Collection
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @returns {Array|Object} Returns `collection`.
   * @see _.forEachRight
   * @example
   *
   * _.forEach([1, 2], function(value) {
   *   console.log(value);
   * });
   * // => Logs `1` then `2`.
   *
   * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
   *   console.log(key);
   * });
   * // => Logs 'a' then 'b' (iteration order is not guaranteed).
   */
  function forEach(collection, iteratee) {
    var func = isArray(collection) ? arrayEach : baseEach;
    return func(collection, castFunction(iteratee));
  }
  
  module.exports = forEach;
  
  
  /***/ }),
  /* 36 */
  /***/ (function(module, exports) {
  
  /** Used as the internal argument placeholder. */
  var PLACEHOLDER = '__lodash_placeholder__';
  
  /**
   * Replaces all `placeholder` elements in `array` with an internal placeholder
   * and returns an array of their indexes.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {*} placeholder The placeholder to replace.
   * @returns {Array} Returns the new array of placeholder indexes.
   */
  function replaceHolders(array, placeholder) {
    var index = -1,
        length = array.length,
        resIndex = 0,
        result = [];
  
    while (++index < length) {
      var value = array[index];
      if (value === placeholder || value === PLACEHOLDER) {
        array[index] = PLACEHOLDER;
        result[resIndex++] = index;
      }
    }
    return result;
  }
  
  module.exports = replaceHolders;
  
  
  /***/ }),
  /* 37 */
  /***/ (function(module, exports) {
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /**
   * Checks if `value` is likely a prototype object.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
   */
  function isPrototype(value) {
    var Ctor = value && value.constructor,
        proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
  
    return value === proto;
  }
  
  module.exports = isPrototype;
  
  
  /***/ }),
  /* 38 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ListCache = __webpack_require__(28),
      stackClear = __webpack_require__(118),
      stackDelete = __webpack_require__(119),
      stackGet = __webpack_require__(120),
      stackHas = __webpack_require__(121),
      stackSet = __webpack_require__(122);
  
  /**
   * Creates a stack cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Stack(entries) {
    var data = this.__data__ = new ListCache(entries);
    this.size = data.size;
  }
  
  // Add methods to `Stack`.
  Stack.prototype.clear = stackClear;
  Stack.prototype['delete'] = stackDelete;
  Stack.prototype.get = stackGet;
  Stack.prototype.has = stackHas;
  Stack.prototype.set = stackSet;
  
  module.exports = Stack;
  
  
  /***/ }),
  /* 39 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10),
      root = __webpack_require__(3);
  
  /* Built-in method references that are verified to be native. */
  var Map = getNative(root, 'Map');
  
  module.exports = Map;
  
  
  /***/ }),
  /* 40 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var mapCacheClear = __webpack_require__(129),
      mapCacheDelete = __webpack_require__(136),
      mapCacheGet = __webpack_require__(138),
      mapCacheHas = __webpack_require__(139),
      mapCacheSet = __webpack_require__(140);
  
  /**
   * Creates a map cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function MapCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  // Add methods to `MapCache`.
  MapCache.prototype.clear = mapCacheClear;
  MapCache.prototype['delete'] = mapCacheDelete;
  MapCache.prototype.get = mapCacheGet;
  MapCache.prototype.has = mapCacheHas;
  MapCache.prototype.set = mapCacheSet;
  
  module.exports = MapCache;
  
  
  /***/ }),
  /* 41 */
  /***/ (function(module, exports) {
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This method is loosely based on
   * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   * @example
   *
   * _.isLength(3);
   * // => true
   *
   * _.isLength(Number.MIN_VALUE);
   * // => false
   *
   * _.isLength(Infinity);
   * // => false
   *
   * _.isLength('3');
   * // => false
   */
  function isLength(value) {
    return typeof value == 'number' &&
      value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  module.exports = isLength;
  
  
  /***/ }),
  /* 42 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.unary` without support for storing metadata.
   *
   * @private
   * @param {Function} func The function to cap arguments for.
   * @returns {Function} Returns the new capped function.
   */
  function baseUnary(func) {
    return function(value) {
      return func(value);
    };
  }
  
  module.exports = baseUnary;
  
  
  /***/ }),
  /* 43 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      getPrototype = __webpack_require__(67),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var objectTag = '[object Object]';
  
  /** Used for built-in method references. */
  var funcProto = Function.prototype,
      objectProto = Object.prototype;
  
  /** Used to resolve the decompiled source of functions. */
  var funcToString = funcProto.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /** Used to infer the `Object` constructor. */
  var objectCtorString = funcToString.call(Object);
  
  /**
   * Checks if `value` is a plain object, that is, an object created by the
   * `Object` constructor or one with a `[[Prototype]]` of `null`.
   *
   * @static
   * @memberOf _
   * @since 0.8.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   * }
   *
   * _.isPlainObject(new Foo);
   * // => false
   *
   * _.isPlainObject([1, 2, 3]);
   * // => false
   *
   * _.isPlainObject({ 'x': 0, 'y': 0 });
   * // => true
   *
   * _.isPlainObject(Object.create(null));
   * // => true
   */
  function isPlainObject(value) {
    if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
      return false;
    }
    var proto = getPrototype(value);
    if (proto === null) {
      return true;
    }
    var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
    return typeof Ctor == 'function' && Ctor instanceof Ctor &&
      funcToString.call(Ctor) == objectCtorString;
  }
  
  module.exports = isPlainObject;
  
  
  /***/ }),
  /* 44 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseFindIndex = __webpack_require__(163),
      baseIsNaN = __webpack_require__(224),
      strictIndexOf = __webpack_require__(225);
  
  /**
   * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseIndexOf(array, value, fromIndex) {
    return value === value
      ? strictIndexOf(array, value, fromIndex)
      : baseFindIndex(array, baseIsNaN, fromIndex);
  }
  
  module.exports = baseIndexOf;
  
  
  /***/ }),
  /* 45 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12),
      baseClone = __webpack_require__(228),
      baseUnset = __webpack_require__(244),
      castPath = __webpack_require__(22),
      copyObject = __webpack_require__(27),
      customOmitClone = __webpack_require__(246),
      flatRest = __webpack_require__(176),
      getAllKeysIn = __webpack_require__(97);
  
  /** Used to compose bitmasks for cloning. */
  var CLONE_DEEP_FLAG = 1,
      CLONE_FLAT_FLAG = 2,
      CLONE_SYMBOLS_FLAG = 4;
  
  /**
   * The opposite of `_.pick`; this method creates an object composed of the
   * own and inherited enumerable property paths of `object` that are not omitted.
   *
   * **Note:** This method is considerably slower than `_.pick`.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The source object.
   * @param {...(string|string[])} [paths] The property paths to omit.
   * @returns {Object} Returns the new object.
   * @example
   *
   * var object = { 'a': 1, 'b': '2', 'c': 3 };
   *
   * _.omit(object, ['a', 'c']);
   * // => { 'b': '2' }
   */
  var omit = flatRest(function(object, paths) {
    var result = {};
    if (object == null) {
      return result;
    }
    var isDeep = false;
    paths = arrayMap(paths, function(path) {
      path = castPath(path, object);
      isDeep || (isDeep = path.length > 1);
      return path;
    });
    copyObject(object, getAllKeysIn(object), result);
    if (isDeep) {
      result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
    }
    var length = paths.length;
    while (length--) {
      baseUnset(result, paths[length]);
    }
    return result;
  });
  
  module.exports = omit;
  
  
  /***/ }),
  /* 46 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var defineProperty = __webpack_require__(168);
  
  /**
   * The base implementation of `assignValue` and `assignMergeValue` without
   * value checks.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {string} key The key of the property to assign.
   * @param {*} value The value to assign.
   */
  function baseAssignValue(object, key, value) {
    if (key == '__proto__' && defineProperty) {
      defineProperty(object, key, {
        'configurable': true,
        'enumerable': true,
        'value': value,
        'writable': true
      });
    } else {
      object[key] = value;
    }
  }
  
  module.exports = baseAssignValue;
  
  
  /***/ }),
  /* 47 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayLikeKeys = __webpack_require__(89),
      baseKeysIn = __webpack_require__(231),
      isArrayLike = __webpack_require__(11);
  
  /**
   * Creates an array of the own and inherited enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keysIn(new Foo);
   * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
   */
  function keysIn(object) {
    return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
  }
  
  module.exports = keysIn;
  
  
  /***/ }),
  /* 48 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseFor = __webpack_require__(178),
      keys = __webpack_require__(9);
  
  /**
   * The base implementation of `_.forOwn` without support for iteratee shorthands.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Object} Returns `object`.
   */
  function baseForOwn(object, iteratee) {
    return object && baseFor(object, iteratee, keys);
  }
  
  module.exports = baseForOwn;
  
  
  /***/ }),
  /* 49 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayReduce = __webpack_require__(99),
      baseEach = __webpack_require__(73),
      baseIteratee = __webpack_require__(13),
      baseReduce = __webpack_require__(264),
      isArray = __webpack_require__(0);
  
  /**
   * Reduces `collection` to a value which is the accumulated result of running
   * each element in `collection` thru `iteratee`, where each successive
   * invocation is supplied the return value of the previous. If `accumulator`
   * is not given, the first element of `collection` is used as the initial
   * value. The iteratee is invoked with four arguments:
   * (accumulator, value, index|key, collection).
   *
   * Many lodash methods are guarded to work as iteratees for methods like
   * `_.reduce`, `_.reduceRight`, and `_.transform`.
   *
   * The guarded methods are:
   * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
   * and `sortBy`
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Collection
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @param {*} [accumulator] The initial value.
   * @returns {*} Returns the accumulated value.
   * @see _.reduceRight
   * @example
   *
   * _.reduce([1, 2], function(sum, n) {
   *   return sum + n;
   * }, 0);
   * // => 3
   *
   * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
   *   (result[value] || (result[value] = [])).push(key);
   *   return result;
   * }, {});
   * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
   */
  function reduce(collection, iteratee, accumulator) {
    var func = isArray(collection) ? arrayReduce : baseReduce,
        initAccum = arguments.length < 3;
  
    return func(collection, baseIteratee(iteratee, 4), accumulator, initAccum, baseEach);
  }
  
  module.exports = reduce;
  
  
  /***/ }),
  /* 50 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var toFinite = __webpack_require__(213);
  
  /**
   * Converts `value` to an integer.
   *
   * **Note:** This method is loosely based on
   * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to convert.
   * @returns {number} Returns the converted integer.
   * @example
   *
   * _.toInteger(3.2);
   * // => 3
   *
   * _.toInteger(Number.MIN_VALUE);
   * // => 0
   *
   * _.toInteger(Infinity);
   * // => 1.7976931348623157e+308
   *
   * _.toInteger('3.2');
   * // => 3
   */
  function toInteger(value) {
    var result = toFinite(value),
        remainder = result % 1;
  
    return result === result ? (remainder ? result - remainder : result) : 0;
  }
  
  module.exports = toInteger;
  
  
  /***/ }),
  /* 51 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isArray = __webpack_require__(0),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var stringTag = '[object String]';
  
  /**
   * Checks if `value` is classified as a `String` primitive or object.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a string, else `false`.
   * @example
   *
   * _.isString('abc');
   * // => true
   *
   * _.isString(1);
   * // => false
   */
  function isString(value) {
    return typeof value == 'string' ||
      (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
  }
  
  module.exports = isString;
  
  
  /***/ }),
  /* 52 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var createFind = __webpack_require__(266),
      findIndex = __webpack_require__(186);
  
  /**
   * Iterates over elements of `collection`, returning the first element
   * `predicate` returns truthy for. The predicate is invoked with three
   * arguments: (value, index|key, collection).
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Collection
   * @param {Array|Object} collection The collection to inspect.
   * @param {Function} [predicate=_.identity] The function invoked per iteration.
   * @param {number} [fromIndex=0] The index to search from.
   * @returns {*} Returns the matched element, else `undefined`.
   * @example
   *
   * var users = [
   *   { 'user': 'barney',  'age': 36, 'active': true },
   *   { 'user': 'fred',    'age': 40, 'active': false },
   *   { 'user': 'pebbles', 'age': 1,  'active': true }
   * ];
   *
   * _.find(users, function(o) { return o.age < 40; });
   * // => object for 'barney'
   *
   * // The `_.matches` iteratee shorthand.
   * _.find(users, { 'age': 1, 'active': true });
   * // => object for 'pebbles'
   *
   * // The `_.matchesProperty` iteratee shorthand.
   * _.find(users, ['active', false]);
   * // => object for 'fred'
   *
   * // The `_.property` iteratee shorthand.
   * _.find(users, 'active');
   * // => object for 'barney'
   */
  var find = createFind(findIndex);
  
  module.exports = find;
  
  
  /***/ }),
  /* 53 */
  /***/ (function(module, exports) {
  
  /**
   * Gets the argument placeholder value for `func`.
   *
   * @private
   * @param {Function} func The function to inspect.
   * @returns {*} Returns the placeholder value.
   */
  function getHolder(func) {
    var object = func;
    return object.placeholder;
  }
  
  module.exports = getHolder;
  
  
  /***/ }),
  /* 54 */
  /***/ (function(module, exports) {
  
  var g;
  
  // This works in non-strict mode
  g = (function() {
  	return this;
  })();
  
  try {
  	// This works if eval is allowed (see CSP)
  	g = g || Function("return this")() || (1,eval)("this");
  } catch(e) {
  	// This works if the window reference is available
  	if(typeof window === "object")
  		g = window;
  }
  
  // g can still be undefined, but nothing to do about it...
  // We return undefined, instead of nothing here, so it's
  // easier to handle this case. if(!global) { ...}
  
  module.exports = g;
  
  
  /***/ }),
  /* 55 */
  /***/ (function(module, exports) {
  
  module.exports = function(module) {
  	if(!module.webpackPolyfill) {
  		module.deprecate = function() {};
  		module.paths = [];
  		// module.parent = undefined by default
  		if(!module.children) module.children = [];
  		Object.defineProperty(module, "loaded", {
  			enumerable: true,
  			get: function() {
  				return module.l;
  			}
  		});
  		Object.defineProperty(module, "id", {
  			enumerable: true,
  			get: function() {
  				return module.i;
  			}
  		});
  		module.webpackPolyfill = 1;
  	}
  	return module;
  };
  
  
  /***/ }),
  /* 56 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var DataView = __webpack_require__(152),
      Map = __webpack_require__(39),
      Promise = __webpack_require__(153),
      Set = __webpack_require__(154),
      WeakMap = __webpack_require__(90),
      baseGetTag = __webpack_require__(8),
      toSource = __webpack_require__(77);
  
  /** `Object#toString` result references. */
  var mapTag = '[object Map]',
      objectTag = '[object Object]',
      promiseTag = '[object Promise]',
      setTag = '[object Set]',
      weakMapTag = '[object WeakMap]';
  
  var dataViewTag = '[object DataView]';
  
  /** Used to detect maps, sets, and weakmaps. */
  var dataViewCtorString = toSource(DataView),
      mapCtorString = toSource(Map),
      promiseCtorString = toSource(Promise),
      setCtorString = toSource(Set),
      weakMapCtorString = toSource(WeakMap);
  
  /**
   * Gets the `toStringTag` of `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  var getTag = baseGetTag;
  
  // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
      (Map && getTag(new Map) != mapTag) ||
      (Promise && getTag(Promise.resolve()) != promiseTag) ||
      (Set && getTag(new Set) != setTag) ||
      (WeakMap && getTag(new WeakMap) != weakMapTag)) {
    getTag = function(value) {
      var result = baseGetTag(value),
          Ctor = result == objectTag ? value.constructor : undefined,
          ctorString = Ctor ? toSource(Ctor) : '';
  
      if (ctorString) {
        switch (ctorString) {
          case dataViewCtorString: return dataViewTag;
          case mapCtorString: return mapTag;
          case promiseCtorString: return promiseTag;
          case setCtorString: return setTag;
          case weakMapCtorString: return weakMapTag;
        }
      }
      return result;
    };
  }
  
  module.exports = getTag;
  
  
  /***/ }),
  /* 57 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseHas = __webpack_require__(155),
      hasPath = __webpack_require__(91);
  
  /**
   * Checks if `path` is a direct property of `object`.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @param {Array|string} path The path to check.
   * @returns {boolean} Returns `true` if `path` exists, else `false`.
   * @example
   *
   * var object = { 'a': { 'b': 2 } };
   * var other = _.create({ 'a': _.create({ 'b': 2 }) });
   *
   * _.has(object, 'a');
   * // => true
   *
   * _.has(object, 'a.b');
   * // => true
   *
   * _.has(object, ['a', 'b']);
   * // => true
   *
   * _.has(other, 'a');
   * // => false
   */
  function has(object, path) {
    return object != null && hasPath(object, path, baseHas);
  }
  
  module.exports = has;
  
  
  /***/ }),
  /* 58 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsEqualDeep = __webpack_require__(112),
      isObjectLike = __webpack_require__(7);
  
  /**
   * The base implementation of `_.isEqual` which supports partial comparisons
   * and tracks traversed objects.
   *
   * @private
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @param {boolean} bitmask The bitmask flags.
   *  1 - Unordered comparison
   *  2 - Partial comparison
   * @param {Function} [customizer] The function to customize comparisons.
   * @param {Object} [stack] Tracks traversed `value` and `other` objects.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   */
  function baseIsEqual(value, other, bitmask, customizer, stack) {
    if (value === other) {
      return true;
    }
    if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
      return value !== value && other !== other;
    }
    return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
  }
  
  module.exports = baseIsEqual;
  
  
  /***/ }),
  /* 59 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var MapCache = __webpack_require__(40),
      setCacheAdd = __webpack_require__(141),
      setCacheHas = __webpack_require__(142);
  
  /**
   *
   * Creates an array cache object to store unique values.
   *
   * @private
   * @constructor
   * @param {Array} [values] The values to cache.
   */
  function SetCache(values) {
    var index = -1,
        length = values == null ? 0 : values.length;
  
    this.__data__ = new MapCache;
    while (++index < length) {
      this.add(values[index]);
    }
  }
  
  // Add methods to `SetCache`.
  SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
  SetCache.prototype.has = setCacheHas;
  
  module.exports = SetCache;
  
  
  /***/ }),
  /* 60 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if a `cache` value for `key` exists.
   *
   * @private
   * @param {Object} cache The cache to query.
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function cacheHas(cache, key) {
    return cache.has(key);
  }
  
  module.exports = cacheHas;
  
  
  /***/ }),
  /* 61 */
  /***/ (function(module, exports) {
  
  /**
   * Appends the elements of `values` to `array`.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {Array} values The values to append.
   * @returns {Array} Returns `array`.
   */
  function arrayPush(array, values) {
    var index = -1,
        length = values.length,
        offset = array.length;
  
    while (++index < length) {
      array[offset + index] = values[index];
    }
    return array;
  }
  
  module.exports = arrayPush;
  
  
  /***/ }),
  /* 62 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayFilter = __webpack_require__(87),
      stubArray = __webpack_require__(88);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Built-in value references. */
  var propertyIsEnumerable = objectProto.propertyIsEnumerable;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeGetSymbols = Object.getOwnPropertySymbols;
  
  /**
   * Creates an array of the own enumerable symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of symbols.
   */
  var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
    if (object == null) {
      return [];
    }
    object = Object(object);
    return arrayFilter(nativeGetSymbols(object), function(symbol) {
      return propertyIsEnumerable.call(object, symbol);
    });
  };
  
  module.exports = getSymbols;
  
  
  /***/ }),
  /* 63 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isArray = __webpack_require__(0),
      isSymbol = __webpack_require__(23);
  
  /** Used to match property names within property paths. */
  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
      reIsPlainProp = /^\w*$/;
  
  /**
   * Checks if `value` is a property name and not a property path.
   *
   * @private
   * @param {*} value The value to check.
   * @param {Object} [object] The object to query keys on.
   * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
   */
  function isKey(value, object) {
    if (isArray(value)) {
      return false;
    }
    var type = typeof value;
    if (type == 'number' || type == 'symbol' || type == 'boolean' ||
        value == null || isSymbol(value)) {
      return true;
    }
    return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
      (object != null && value in Object(object));
  }
  
  module.exports = isKey;
  
  
  /***/ }),
  /* 64 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseToString = __webpack_require__(65);
  
  /**
   * Converts `value` to a string. An empty string is returned for `null`
   * and `undefined` values. The sign of `-0` is preserved.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to convert.
   * @returns {string} Returns the converted string.
   * @example
   *
   * _.toString(null);
   * // => ''
   *
   * _.toString(-0);
   * // => '-0'
   *
   * _.toString([1, 2, 3]);
   * // => '1,2,3'
   */
  function toString(value) {
    return value == null ? '' : baseToString(value);
  }
  
  module.exports = toString;
  
  
  /***/ }),
  /* 65 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14),
      arrayMap = __webpack_require__(12),
      isArray = __webpack_require__(0),
      isSymbol = __webpack_require__(23);
  
  /** Used as references for various `Number` constants. */
  var INFINITY = 1 / 0;
  
  /** Used to convert symbols to primitives and strings. */
  var symbolProto = Symbol ? Symbol.prototype : undefined,
      symbolToString = symbolProto ? symbolProto.toString : undefined;
  
  /**
   * The base implementation of `_.toString` which doesn't convert nullish
   * values to empty strings.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {string} Returns the string.
   */
  function baseToString(value) {
    // Exit early for strings to avoid a performance hit in some environments.
    if (typeof value == 'string') {
      return value;
    }
    if (isArray(value)) {
      // Recursively convert values (susceptible to call stack limits).
      return arrayMap(value, baseToString) + '';
    }
    if (isSymbol(value)) {
      return symbolToString ? symbolToString.call(value) : '';
    }
    var result = (value + '');
    return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
  }
  
  module.exports = baseToString;
  
  
  /***/ }),
  /* 66 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.defer = undefined;
  
  var _isPlainObject2 = __webpack_require__(43);
  
  var _isPlainObject3 = _interopRequireDefault(_isPlainObject2);
  
  var _isEmpty2 = __webpack_require__(16);
  
  var _isEmpty3 = _interopRequireDefault(_isEmpty2);
  
  exports.shallowEqual = shallowEqual;
  exports.isSpecialClick = isSpecialClick;
  exports.capitalize = capitalize;
  exports.assertFacetDefined = assertFacetDefined;
  exports.getDisplayName = getDisplayName;
  exports.removeEmptyKey = removeEmptyKey;
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  // From https://github.com/reactjs/react-redux/blob/master/src/utils/shallowEqual.js
  function shallowEqual(objA, objB) {
    if (objA === objB) {
      return true;
    }
  
    var keysA = Object.keys(objA);
    var keysB = Object.keys(objB);
  
    if (keysA.length !== keysB.length) {
      return false;
    }
  
    // Test for A's keys different from B.
    var hasOwn = Object.prototype.hasOwnProperty;
    for (var i = 0; i < keysA.length; i++) {
      if (!hasOwn.call(objB, keysA[i]) || objA[keysA[i]] !== objB[keysA[i]]) {
        return false;
      }
    }
  
    return true;
  }
  
  function isSpecialClick(event) {
    var isMiddleClick = event.button === 1;
    return Boolean(isMiddleClick || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey);
  }
  
  function capitalize(key) {
    return key.length === 0 ? '' : '' + key[0].toUpperCase() + key.slice(1);
  }
  
  function assertFacetDefined(searchParameters, searchResults, facet) {
    var wasRequested = searchParameters.isConjunctiveFacet(facet) || searchParameters.isDisjunctiveFacet(facet);
    var wasReceived = Boolean(searchResults.getFacetByName(facet));
    if (searchResults.nbHits > 0 && wasRequested && !wasReceived) {
      // eslint-disable-next-line no-console
      console.warn('A component requested values for facet "' + facet + '", but no facet ' + 'values were retrieved from the API. This means that you should add ' + ('the attribute "' + facet + '" to the list of attributes for faceting in ') + 'your index settings.');
    }
  }
  
  function getDisplayName(Component) {
    return Component.displayName || Component.name || 'UnknownComponent';
  }
  
  var resolved = Promise.resolve();
  var defer = exports.defer = function defer(f) {
    resolved.then(f);
  };
  
  function removeEmptyKey(obj) {
    Object.keys(obj).forEach(function (key) {
      var value = obj[key];
      if ((0, _isEmpty3.default)(value) && (0, _isPlainObject3.default)(value)) {
        delete obj[key];
      } else if ((0, _isPlainObject3.default)(value)) {
        removeEmptyKey(value);
      }
    });
    return obj;
  }
  
  /***/ }),
  /* 67 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var overArg = __webpack_require__(80);
  
  /** Built-in value references. */
  var getPrototype = overArg(Object.getPrototypeOf, Object);
  
  module.exports = getPrototype;
  
  
  /***/ }),
  /* 68 */
  /***/ (function(module, exports) {
  
  /**
   * A faster alternative to `Function#apply`, this function invokes `func`
   * with the `this` binding of `thisArg` and the arguments of `args`.
   *
   * @private
   * @param {Function} func The function to invoke.
   * @param {*} thisArg The `this` binding of `func`.
   * @param {Array} args The arguments to invoke `func` with.
   * @returns {*} Returns the result of `func`.
   */
  function apply(func, thisArg, args) {
    switch (args.length) {
      case 0: return func.call(thisArg);
      case 1: return func.call(thisArg, args[0]);
      case 2: return func.call(thisArg, args[0], args[1]);
      case 3: return func.call(thisArg, args[0], args[1], args[2]);
    }
    return func.apply(thisArg, args);
  }
  
  module.exports = apply;
  
  
  /***/ }),
  /* 69 */
  /***/ (function(module, exports) {
  
  /**
   * Copies the values of `source` to `array`.
   *
   * @private
   * @param {Array} source The array to copy values from.
   * @param {Array} [array=[]] The array to copy values to.
   * @returns {Array} Returns `array`.
   */
  function copyArray(source, array) {
    var index = -1,
        length = source.length;
  
    array || (array = Array(length));
    while (++index < length) {
      array[index] = source[index];
    }
    return array;
  }
  
  module.exports = copyArray;
  
  
  /***/ }),
  /* 70 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(6);
  
  /** Built-in value references. */
  var objectCreate = Object.create;
  
  /**
   * The base implementation of `_.create` without support for assigning
   * properties to the created object.
   *
   * @private
   * @param {Object} proto The object to inherit from.
   * @returns {Object} Returns the new object.
   */
  var baseCreate = (function() {
    function object() {}
    return function(proto) {
      if (!isObject(proto)) {
        return {};
      }
      if (objectCreate) {
        return objectCreate(proto);
      }
      object.prototype = proto;
      var result = new object;
      object.prototype = undefined;
      return result;
    };
  }());
  
  module.exports = baseCreate;
  
  
  /***/ }),
  /* 71 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var castPath = __webpack_require__(22),
      toKey = __webpack_require__(24);
  
  /**
   * The base implementation of `_.get` without support for default values.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array|string} path The path of the property to get.
   * @returns {*} Returns the resolved value.
   */
  function baseGet(object, path) {
    path = castPath(path, object);
  
    var index = 0,
        length = path.length;
  
    while (object != null && index < length) {
      object = object[toKey(path[index++])];
    }
    return (index && index == length) ? object : undefined;
  }
  
  module.exports = baseGet;
  
  
  /***/ }),
  /* 72 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGet = __webpack_require__(71);
  
  /**
   * Gets the value at `path` of `object`. If the resolved value is
   * `undefined`, the `defaultValue` is returned in its place.
   *
   * @static
   * @memberOf _
   * @since 3.7.0
   * @category Object
   * @param {Object} object The object to query.
   * @param {Array|string} path The path of the property to get.
   * @param {*} [defaultValue] The value returned for `undefined` resolved values.
   * @returns {*} Returns the resolved value.
   * @example
   *
   * var object = { 'a': [{ 'b': { 'c': 3 } }] };
   *
   * _.get(object, 'a[0].b.c');
   * // => 3
   *
   * _.get(object, ['a', '0', 'b', 'c']);
   * // => 3
   *
   * _.get(object, 'a.b.c', 'default');
   * // => 'default'
   */
  function get(object, path, defaultValue) {
    var result = object == null ? undefined : baseGet(object, path);
    return result === undefined ? defaultValue : result;
  }
  
  module.exports = get;
  
  
  /***/ }),
  /* 73 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseForOwn = __webpack_require__(48),
      createBaseEach = __webpack_require__(254);
  
  /**
   * The base implementation of `_.forEach` without support for iteratee shorthands.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array|Object} Returns `collection`.
   */
  var baseEach = createBaseEach(baseForOwn);
  
  module.exports = baseEach;
  
  
  /***/ }),
  /* 74 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIndexOf = __webpack_require__(44),
      toInteger = __webpack_require__(50);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * Gets the index at which the first occurrence of `value` is found in `array`
   * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * for equality comparisons. If `fromIndex` is negative, it's used as the
   * offset from the end of `array`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} [fromIndex=0] The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   * @example
   *
   * _.indexOf([1, 2, 1, 2], 2);
   * // => 1
   *
   * // Search from the `fromIndex`.
   * _.indexOf([1, 2, 1, 2], 2, 2);
   * // => 3
   */
  function indexOf(array, value, fromIndex) {
    var length = array == null ? 0 : array.length;
    if (!length) {
      return -1;
    }
    var index = fromIndex == null ? 0 : toInteger(fromIndex);
    if (index < 0) {
      index = nativeMax(length + index, 0);
    }
    return baseIndexOf(array, value, index);
  }
  
  module.exports = indexOf;
  
  
  /***/ }),
  /* 75 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseCreate = __webpack_require__(70),
      isObject = __webpack_require__(6);
  
  /**
   * Creates a function that produces an instance of `Ctor` regardless of
   * whether it was invoked as part of a `new` expression or by `call` or `apply`.
   *
   * @private
   * @param {Function} Ctor The constructor to wrap.
   * @returns {Function} Returns the new wrapped function.
   */
  function createCtor(Ctor) {
    return function() {
      // Use a `switch` statement to work with class constructors. See
      // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
      // for more details.
      var args = arguments;
      switch (args.length) {
        case 0: return new Ctor;
        case 1: return new Ctor(args[0]);
        case 2: return new Ctor(args[0], args[1]);
        case 3: return new Ctor(args[0], args[1], args[2]);
        case 4: return new Ctor(args[0], args[1], args[2], args[3]);
        case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
        case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
        case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
      }
      var thisBinding = baseCreate(Ctor.prototype),
          result = Ctor.apply(thisBinding, args);
  
      // Mimic the constructor's `return` behavior.
      // See https://es5.github.io/#x13.2.2 for more details.
      return isObject(result) ? result : thisBinding;
    };
  }
  
  module.exports = createCtor;
  
  
  /***/ }),
  /* 76 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */
  var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
  
  module.exports = freeGlobal;
  
  /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(54)))
  
  /***/ }),
  /* 77 */
  /***/ (function(module, exports) {
  
  /** Used for built-in method references. */
  var funcProto = Function.prototype;
  
  /** Used to resolve the decompiled source of functions. */
  var funcToString = funcProto.toString;
  
  /**
   * Converts `func` to its source code.
   *
   * @private
   * @param {Function} func The function to convert.
   * @returns {string} Returns the source code.
   */
  function toSource(func) {
    if (func != null) {
      try {
        return funcToString.call(func);
      } catch (e) {}
      try {
        return (func + '');
      } catch (e) {}
    }
    return '';
  }
  
  module.exports = toSource;
  
  
  /***/ }),
  /* 78 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var SetCache = __webpack_require__(59),
      arraySome = __webpack_require__(143),
      cacheHas = __webpack_require__(60);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;
  
  /**
   * A specialized version of `baseIsEqualDeep` for arrays with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Array} array The array to compare.
   * @param {Array} other The other array to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `array` and `other` objects.
   * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
   */
  function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
    var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
        arrLength = array.length,
        othLength = other.length;
  
    if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
      return false;
    }
    // Assume cyclic values are equal.
    var stacked = stack.get(array);
    if (stacked && stack.get(other)) {
      return stacked == other;
    }
    var index = -1,
        result = true,
        seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
  
    stack.set(array, other);
    stack.set(other, array);
  
    // Ignore non-index properties.
    while (++index < arrLength) {
      var arrValue = array[index],
          othValue = other[index];
  
      if (customizer) {
        var compared = isPartial
          ? customizer(othValue, arrValue, index, other, array, stack)
          : customizer(arrValue, othValue, index, array, other, stack);
      }
      if (compared !== undefined) {
        if (compared) {
          continue;
        }
        result = false;
        break;
      }
      // Recursively compare arrays (susceptible to call stack limits).
      if (seen) {
        if (!arraySome(other, function(othValue, othIndex) {
              if (!cacheHas(seen, othIndex) &&
                  (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                return seen.push(othIndex);
              }
            })) {
          result = false;
          break;
        }
      } else if (!(
            arrValue === othValue ||
              equalFunc(arrValue, othValue, bitmask, customizer, stack)
          )) {
        result = false;
        break;
      }
    }
    stack['delete'](array);
    stack['delete'](other);
    return result;
  }
  
  module.exports = equalArrays;
  
  
  /***/ }),
  /* 79 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isPrototype = __webpack_require__(37),
      nativeKeys = __webpack_require__(151);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function baseKeys(object) {
    if (!isPrototype(object)) {
      return nativeKeys(object);
    }
    var result = [];
    for (var key in Object(object)) {
      if (hasOwnProperty.call(object, key) && key != 'constructor') {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = baseKeys;
  
  
  /***/ }),
  /* 80 */
  /***/ (function(module, exports) {
  
  /**
   * Creates a unary function that invokes `func` with its argument transformed.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {Function} transform The argument transform.
   * @returns {Function} Returns the new function.
   */
  function overArg(func, transform) {
    return function(arg) {
      return func(transform(arg));
    };
  }
  
  module.exports = overArg;
  
  
  /***/ }),
  /* 81 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsEqual = __webpack_require__(58);
  
  /**
   * Performs a deep comparison between two values to determine if they are
   * equivalent.
   *
   * **Note:** This method supports comparing arrays, array buffers, booleans,
   * date objects, error objects, maps, numbers, `Object` objects, regexes,
   * sets, strings, symbols, and typed arrays. `Object` objects are compared
   * by their own, not inherited, enumerable properties. Functions and DOM
   * nodes are compared by strict equality, i.e. `===`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   * @example
   *
   * var object = { 'a': 1 };
   * var other = { 'a': 1 };
   *
   * _.isEqual(object, other);
   * // => true
   *
   * object === other;
   * // => false
   */
  function isEqual(value, other) {
    return baseIsEqual(value, other);
  }
  
  module.exports = isEqual;
  
  
  /***/ }),
  /* 82 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var root = __webpack_require__(3);
  
  /** Built-in value references. */
  var Uint8Array = root.Uint8Array;
  
  module.exports = Uint8Array;
  
  
  /***/ }),
  /* 83 */
  /***/ (function(module, exports) {
  
  /**
   * Converts `map` to its key-value pairs.
   *
   * @private
   * @param {Object} map The map to convert.
   * @returns {Array} Returns the key-value pairs.
   */
  function mapToArray(map) {
    var index = -1,
        result = Array(map.size);
  
    map.forEach(function(value, key) {
      result[++index] = [key, value];
    });
    return result;
  }
  
  module.exports = mapToArray;
  
  
  /***/ }),
  /* 84 */
  /***/ (function(module, exports) {
  
  /**
   * Converts `set` to an array of its values.
   *
   * @private
   * @param {Object} set The set to convert.
   * @returns {Array} Returns the values.
   */
  function setToArray(set) {
    var index = -1,
        result = Array(set.size);
  
    set.forEach(function(value) {
      result[++index] = value;
    });
    return result;
  }
  
  module.exports = setToArray;
  
  
  /***/ }),
  /* 85 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetAllKeys = __webpack_require__(86),
      getSymbols = __webpack_require__(62),
      keys = __webpack_require__(9);
  
  /**
   * Creates an array of own enumerable property names and symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function getAllKeys(object) {
    return baseGetAllKeys(object, keys, getSymbols);
  }
  
  module.exports = getAllKeys;
  
  
  /***/ }),
  /* 86 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayPush = __webpack_require__(61),
      isArray = __webpack_require__(0);
  
  /**
   * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
   * `keysFunc` and `symbolsFunc` to get the enumerable property names and
   * symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @param {Function} symbolsFunc The function to get the symbols of `object`.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function baseGetAllKeys(object, keysFunc, symbolsFunc) {
    var result = keysFunc(object);
    return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
  }
  
  module.exports = baseGetAllKeys;
  
  
  /***/ }),
  /* 87 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.filter` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {Array} Returns the new filtered array.
   */
  function arrayFilter(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length,
        resIndex = 0,
        result = [];
  
    while (++index < length) {
      var value = array[index];
      if (predicate(value, index, array)) {
        result[resIndex++] = value;
      }
    }
    return result;
  }
  
  module.exports = arrayFilter;
  
  
  /***/ }),
  /* 88 */
  /***/ (function(module, exports) {
  
  /**
   * This method returns a new empty array.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {Array} Returns the new empty array.
   * @example
   *
   * var arrays = _.times(2, _.stubArray);
   *
   * console.log(arrays);
   * // => [[], []]
   *
   * console.log(arrays[0] === arrays[1]);
   * // => false
   */
  function stubArray() {
    return [];
  }
  
  module.exports = stubArray;
  
  
  /***/ }),
  /* 89 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseTimes = __webpack_require__(146),
      isArguments = __webpack_require__(20),
      isArray = __webpack_require__(0),
      isBuffer = __webpack_require__(21),
      isIndex = __webpack_require__(32),
      isTypedArray = __webpack_require__(33);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Creates an array of the enumerable property names of the array-like `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @param {boolean} inherited Specify returning inherited property names.
   * @returns {Array} Returns the array of property names.
   */
  function arrayLikeKeys(value, inherited) {
    var isArr = isArray(value),
        isArg = !isArr && isArguments(value),
        isBuff = !isArr && !isArg && isBuffer(value),
        isType = !isArr && !isArg && !isBuff && isTypedArray(value),
        skipIndexes = isArr || isArg || isBuff || isType,
        result = skipIndexes ? baseTimes(value.length, String) : [],
        length = result.length;
  
    for (var key in value) {
      if ((inherited || hasOwnProperty.call(value, key)) &&
          !(skipIndexes && (
             // Safari 9 has enumerable `arguments.length` in strict mode.
             key == 'length' ||
             // Node.js 0.10 has enumerable non-index properties on buffers.
             (isBuff && (key == 'offset' || key == 'parent')) ||
             // PhantomJS 2 has enumerable non-index properties on typed arrays.
             (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
             // Skip index properties.
             isIndex(key, length)
          ))) {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = arrayLikeKeys;
  
  
  /***/ }),
  /* 90 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10),
      root = __webpack_require__(3);
  
  /* Built-in method references that are verified to be native. */
  var WeakMap = getNative(root, 'WeakMap');
  
  module.exports = WeakMap;
  
  
  /***/ }),
  /* 91 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var castPath = __webpack_require__(22),
      isArguments = __webpack_require__(20),
      isArray = __webpack_require__(0),
      isIndex = __webpack_require__(32),
      isLength = __webpack_require__(41),
      toKey = __webpack_require__(24);
  
  /**
   * Checks if `path` exists on `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array|string} path The path to check.
   * @param {Function} hasFunc The function to check properties.
   * @returns {boolean} Returns `true` if `path` exists, else `false`.
   */
  function hasPath(object, path, hasFunc) {
    path = castPath(path, object);
  
    var index = -1,
        length = path.length,
        result = false;
  
    while (++index < length) {
      var key = toKey(path[index]);
      if (!(result = object != null && hasFunc(object, key))) {
        break;
      }
      object = object[key];
    }
    if (result || ++index != length) {
      return result;
    }
    length = object == null ? 0 : object.length;
    return !!length && isLength(length) && isIndex(key, length) &&
      (isArray(object) || isArguments(object));
  }
  
  module.exports = hasPath;
  
  
  /***/ }),
  /* 92 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIndexOf = __webpack_require__(44);
  
  /**
   * A specialized version of `_.includes` for arrays without support for
   * specifying an index to search from.
   *
   * @private
   * @param {Array} [array] The array to inspect.
   * @param {*} target The value to search for.
   * @returns {boolean} Returns `true` if `target` is found, else `false`.
   */
  function arrayIncludes(array, value) {
    var length = array == null ? 0 : array.length;
    return !!length && baseIndexOf(array, value, 0) > -1;
  }
  
  module.exports = arrayIncludes;
  
  
  /***/ }),
  /* 93 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseSetToString = __webpack_require__(227),
      shortOut = __webpack_require__(169);
  
  /**
   * Sets the `toString` method of `func` to return `string`.
   *
   * @private
   * @param {Function} func The function to modify.
   * @param {Function} string The `toString` result.
   * @returns {Function} Returns `func`.
   */
  var setToString = shortOut(baseSetToString);
  
  module.exports = setToString;
  
  
  /***/ }),
  /* 94 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isArrayLike = __webpack_require__(11),
      isObjectLike = __webpack_require__(7);
  
  /**
   * This method is like `_.isArrayLike` except that it also checks if `value`
   * is an object.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array-like object,
   *  else `false`.
   * @example
   *
   * _.isArrayLikeObject([1, 2, 3]);
   * // => true
   *
   * _.isArrayLikeObject(document.body.children);
   * // => true
   *
   * _.isArrayLikeObject('abc');
   * // => false
   *
   * _.isArrayLikeObject(_.noop);
   * // => false
   */
  function isArrayLikeObject(value) {
    return isObjectLike(value) && isArrayLike(value);
  }
  
  module.exports = isArrayLikeObject;
  
  
  /***/ }),
  /* 95 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.forEach` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns `array`.
   */
  function arrayEach(array, iteratee) {
    var index = -1,
        length = array == null ? 0 : array.length;
  
    while (++index < length) {
      if (iteratee(array[index], index, array) === false) {
        break;
      }
    }
    return array;
  }
  
  module.exports = arrayEach;
  
  
  /***/ }),
  /* 96 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseAssignValue = __webpack_require__(46),
      eq = __webpack_require__(18);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Assigns `value` to `key` of `object` if the existing value is not equivalent
   * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * for equality comparisons.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {string} key The key of the property to assign.
   * @param {*} value The value to assign.
   */
  function assignValue(object, key, value) {
    var objValue = object[key];
    if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
        (value === undefined && !(key in object))) {
      baseAssignValue(object, key, value);
    }
  }
  
  module.exports = assignValue;
  
  
  /***/ }),
  /* 97 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetAllKeys = __webpack_require__(86),
      getSymbolsIn = __webpack_require__(171),
      keysIn = __webpack_require__(47);
  
  /**
   * Creates an array of own and inherited enumerable property names and
   * symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function getAllKeysIn(object) {
    return baseGetAllKeys(object, keysIn, getSymbolsIn);
  }
  
  module.exports = getAllKeysIn;
  
  
  /***/ }),
  /* 98 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Uint8Array = __webpack_require__(82);
  
  /**
   * Creates a clone of `arrayBuffer`.
   *
   * @private
   * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
   * @returns {ArrayBuffer} Returns the cloned array buffer.
   */
  function cloneArrayBuffer(arrayBuffer) {
    var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
    new Uint8Array(result).set(new Uint8Array(arrayBuffer));
    return result;
  }
  
  module.exports = cloneArrayBuffer;
  
  
  /***/ }),
  /* 99 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.reduce` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} [accumulator] The initial value.
   * @param {boolean} [initAccum] Specify using the first element of `array` as
   *  the initial value.
   * @returns {*} Returns the accumulated value.
   */
  function arrayReduce(array, iteratee, accumulator, initAccum) {
    var index = -1,
        length = array == null ? 0 : array.length;
  
    if (initAccum && length) {
      accumulator = array[++index];
    }
    while (++index < length) {
      accumulator = iteratee(accumulator, array[index], index, array);
    }
    return accumulator;
  }
  
  module.exports = arrayReduce;
  
  
  /***/ }),
  /* 100 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var keys = __webpack_require__(9);
  var intersection = __webpack_require__(249);
  var forOwn = __webpack_require__(252);
  var forEach = __webpack_require__(35);
  var filter = __webpack_require__(101);
  var map = __webpack_require__(17);
  var reduce = __webpack_require__(49);
  var omit = __webpack_require__(45);
  var indexOf = __webpack_require__(74);
  var isNaN = __webpack_require__(214);
  var isArray = __webpack_require__(0);
  var isEmpty = __webpack_require__(16);
  var isEqual = __webpack_require__(81);
  var isUndefined = __webpack_require__(185);
  var isString = __webpack_require__(51);
  var isFunction = __webpack_require__(19);
  var find = __webpack_require__(52);
  var trim = __webpack_require__(187);
  
  var defaults = __webpack_require__(102);
  var merge = __webpack_require__(103);
  
  var valToNumber = __webpack_require__(279);
  
  var filterState = __webpack_require__(280);
  
  var RefinementList = __webpack_require__(281);
  
  /**
   * like _.find but using _.isEqual to be able to use it
   * to find arrays.
   * @private
   * @param {any[]} array array to search into
   * @param {any} searchedValue the value we're looking for
   * @return {any} the searched value or undefined
   */
  function findArray(array, searchedValue) {
    return find(array, function(currentValue) {
      return isEqual(currentValue, searchedValue);
    });
  }
  
  /**
   * The facet list is the structure used to store the list of values used to
   * filter a single attribute.
   * @typedef {string[]} SearchParameters.FacetList
   */
  
  /**
   * Structure to store numeric filters with the operator as the key. The supported operators
   * are `=`, `>`, `<`, `>=`, `<=` and `!=`.
   * @typedef {Object.<string, Array.<number|number[]>>} SearchParameters.OperatorList
   */
  
  /**
   * SearchParameters is the data structure that contains all the information
   * usable for making a search to Algolia API. It doesn't do the search itself,
   * nor does it contains logic about the parameters.
   * It is an immutable object, therefore it has been created in a way that each
   * changes does not change the object itself but returns a copy with the
   * modification.
   * This object should probably not be instantiated outside of the helper. It will
   * be provided when needed. This object is documented for reference as you'll
   * get it from events generated by the {@link AlgoliaSearchHelper}.
   * If need be, instantiate the Helper from the factory function {@link SearchParameters.make}
   * @constructor
   * @classdesc contains all the parameters of a search
   * @param {object|SearchParameters} newParameters existing parameters or partial object
   * for the properties of a new SearchParameters
   * @see SearchParameters.make
   * @example <caption>SearchParameters of the first query in
   *   <a href="http://demos.algolia.com/instant-search-demo/">the instant search demo</a></caption>
  {
     "query": "",
     "disjunctiveFacets": [
        "customerReviewCount",
        "category",
        "salePrice_range",
        "manufacturer"
    ],
     "maxValuesPerFacet": 30,
     "page": 0,
     "hitsPerPage": 10,
     "facets": [
        "type",
        "shipping"
    ]
  }
   */
  function SearchParameters(newParameters) {
    var params = newParameters ? SearchParameters._parseNumbers(newParameters) : {};
  
    /**
     * Targeted index. This parameter is mandatory.
     * @member {string}
     */
    this.index = params.index || '';
  
    // Query
    /**
     * Query string of the instant search. The empty string is a valid query.
     * @member {string}
     * @see https://www.algolia.com/doc/rest#param-query
     */
    this.query = params.query || '';
  
    // Facets
    /**
     * This attribute contains the list of all the conjunctive facets
     * used. This list will be added to requested facets in the
     * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
     * @member {string[]}
     */
    this.facets = params.facets || [];
    /**
     * This attribute contains the list of all the disjunctive facets
     * used. This list will be added to requested facets in the
     * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
     * @member {string[]}
     */
    this.disjunctiveFacets = params.disjunctiveFacets || [];
    /**
     * This attribute contains the list of all the hierarchical facets
     * used. This list will be added to requested facets in the
     * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia.
     * Hierarchical facets are a sub type of disjunctive facets that
     * let you filter faceted attributes hierarchically.
     * @member {string[]|object[]}
     */
    this.hierarchicalFacets = params.hierarchicalFacets || [];
  
    // Refinements
    /**
     * This attribute contains all the filters that need to be
     * applied on the conjunctive facets. Each facet must be properly
     * defined in the `facets` attribute.
     *
     * The key is the name of the facet, and the `FacetList` contains all
     * filters selected for the associated facet name.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `facetFilters` attribute.
     * @member {Object.<string, SearchParameters.FacetList>}
     */
    this.facetsRefinements = params.facetsRefinements || {};
    /**
     * This attribute contains all the filters that need to be
     * excluded from the conjunctive facets. Each facet must be properly
     * defined in the `facets` attribute.
     *
     * The key is the name of the facet, and the `FacetList` contains all
     * filters excluded for the associated facet name.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `facetFilters` attribute.
     * @member {Object.<string, SearchParameters.FacetList>}
     */
    this.facetsExcludes = params.facetsExcludes || {};
    /**
     * This attribute contains all the filters that need to be
     * applied on the disjunctive facets. Each facet must be properly
     * defined in the `disjunctiveFacets` attribute.
     *
     * The key is the name of the facet, and the `FacetList` contains all
     * filters selected for the associated facet name.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `facetFilters` attribute.
     * @member {Object.<string, SearchParameters.FacetList>}
     */
    this.disjunctiveFacetsRefinements = params.disjunctiveFacetsRefinements || {};
    /**
     * This attribute contains all the filters that need to be
     * applied on the numeric attributes.
     *
     * The key is the name of the attribute, and the value is the
     * filters to apply to this attribute.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `numericFilters` attribute.
     * @member {Object.<string, SearchParameters.OperatorList>}
     */
    this.numericRefinements = params.numericRefinements || {};
    /**
     * This attribute contains all the tags used to refine the query.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `tagFilters` attribute.
     * @member {string[]}
     */
    this.tagRefinements = params.tagRefinements || [];
    /**
     * This attribute contains all the filters that need to be
     * applied on the hierarchical facets. Each facet must be properly
     * defined in the `hierarchicalFacets` attribute.
     *
     * The key is the name of the facet, and the `FacetList` contains all
     * filters selected for the associated facet name. The FacetList values
     * are structured as a string that contain the values for each level
     * separated by the configured separator.
     *
     * When querying algolia, the values stored in this attribute will
     * be translated into the `facetFilters` attribute.
     * @member {Object.<string, SearchParameters.FacetList>}
     */
    this.hierarchicalFacetsRefinements = params.hierarchicalFacetsRefinements || {};
  
    /**
     * Contains the numeric filters in the raw format of the Algolia API. Setting
     * this parameter is not compatible with the usage of numeric filters methods.
     * @see https://www.algolia.com/doc/javascript#numericFilters
     * @member {string}
     */
    this.numericFilters = params.numericFilters;
  
    /**
     * Contains the tag filters in the raw format of the Algolia API. Setting this
     * parameter is not compatible with the of the add/remove/toggle methods of the
     * tag api.
     * @see https://www.algolia.com/doc/rest#param-tagFilters
     * @member {string}
     */
    this.tagFilters = params.tagFilters;
  
    /**
     * Contains the optional tag filters in the raw format of the Algolia API.
     * @see https://www.algolia.com/doc/rest#param-tagFilters
     * @member {string}
     */
    this.optionalTagFilters = params.optionalTagFilters;
  
    /**
     * Contains the optional facet filters in the raw format of the Algolia API.
     * @see https://www.algolia.com/doc/rest#param-tagFilters
     * @member {string}
     */
    this.optionalFacetFilters = params.optionalFacetFilters;
  
  
    // Misc. parameters
    /**
     * Number of hits to be returned by the search API
     * @member {number}
     * @see https://www.algolia.com/doc/rest#param-hitsPerPage
     */
    this.hitsPerPage = params.hitsPerPage;
    /**
     * Number of values for each faceted attribute
     * @member {number}
     * @see https://www.algolia.com/doc/rest#param-maxValuesPerFacet
     */
    this.maxValuesPerFacet = params.maxValuesPerFacet;
    /**
     * The current page number
     * @member {number}
     * @see https://www.algolia.com/doc/rest#param-page
     */
    this.page = params.page || 0;
    /**
     * How the query should be treated by the search engine.
     * Possible values: prefixAll, prefixLast, prefixNone
     * @see https://www.algolia.com/doc/rest#param-queryType
     * @member {string}
     */
    this.queryType = params.queryType;
    /**
     * How the typo tolerance behave in the search engine.
     * Possible values: true, false, min, strict
     * @see https://www.algolia.com/doc/rest#param-typoTolerance
     * @member {string}
     */
    this.typoTolerance = params.typoTolerance;
  
    /**
     * Number of characters to wait before doing one character replacement.
     * @see https://www.algolia.com/doc/rest#param-minWordSizefor1Typo
     * @member {number}
     */
    this.minWordSizefor1Typo = params.minWordSizefor1Typo;
    /**
     * Number of characters to wait before doing a second character replacement.
     * @see https://www.algolia.com/doc/rest#param-minWordSizefor2Typos
     * @member {number}
     */
    this.minWordSizefor2Typos = params.minWordSizefor2Typos;
    /**
     * Configure the precision of the proximity ranking criterion
     * @see https://www.algolia.com/doc/rest#param-minProximity
     */
    this.minProximity = params.minProximity;
    /**
     * Should the engine allow typos on numerics.
     * @see https://www.algolia.com/doc/rest#param-allowTyposOnNumericTokens
     * @member {boolean}
     */
    this.allowTyposOnNumericTokens = params.allowTyposOnNumericTokens;
    /**
     * Should the plurals be ignored
     * @see https://www.algolia.com/doc/rest#param-ignorePlurals
     * @member {boolean}
     */
    this.ignorePlurals = params.ignorePlurals;
    /**
     * Restrict which attribute is searched.
     * @see https://www.algolia.com/doc/rest#param-restrictSearchableAttributes
     * @member {string}
     */
    this.restrictSearchableAttributes = params.restrictSearchableAttributes;
    /**
     * Enable the advanced syntax.
     * @see https://www.algolia.com/doc/rest#param-advancedSyntax
     * @member {boolean}
     */
    this.advancedSyntax = params.advancedSyntax;
    /**
     * Enable the analytics
     * @see https://www.algolia.com/doc/rest#param-analytics
     * @member {boolean}
     */
    this.analytics = params.analytics;
    /**
     * Tag of the query in the analytics.
     * @see https://www.algolia.com/doc/rest#param-analyticsTags
     * @member {string}
     */
    this.analyticsTags = params.analyticsTags;
    /**
     * Enable the synonyms
     * @see https://www.algolia.com/doc/rest#param-synonyms
     * @member {boolean}
     */
    this.synonyms = params.synonyms;
    /**
     * Should the engine replace the synonyms in the highlighted results.
     * @see https://www.algolia.com/doc/rest#param-replaceSynonymsInHighlight
     * @member {boolean}
     */
    this.replaceSynonymsInHighlight = params.replaceSynonymsInHighlight;
    /**
     * Add some optional words to those defined in the dashboard
     * @see https://www.algolia.com/doc/rest#param-optionalWords
     * @member {string}
     */
    this.optionalWords = params.optionalWords;
    /**
     * Possible values are "lastWords" "firstWords" "allOptional" "none" (default)
     * @see https://www.algolia.com/doc/rest#param-removeWordsIfNoResults
     * @member {string}
     */
    this.removeWordsIfNoResults = params.removeWordsIfNoResults;
    /**
     * List of attributes to retrieve
     * @see https://www.algolia.com/doc/rest#param-attributesToRetrieve
     * @member {string}
     */
    this.attributesToRetrieve = params.attributesToRetrieve;
    /**
     * List of attributes to highlight
     * @see https://www.algolia.com/doc/rest#param-attributesToHighlight
     * @member {string}
     */
    this.attributesToHighlight = params.attributesToHighlight;
    /**
     * Code to be embedded on the left part of the highlighted results
     * @see https://www.algolia.com/doc/rest#param-highlightPreTag
     * @member {string}
     */
    this.highlightPreTag = params.highlightPreTag;
    /**
     * Code to be embedded on the right part of the highlighted results
     * @see https://www.algolia.com/doc/rest#param-highlightPostTag
     * @member {string}
     */
    this.highlightPostTag = params.highlightPostTag;
    /**
     * List of attributes to snippet
     * @see https://www.algolia.com/doc/rest#param-attributesToSnippet
     * @member {string}
     */
    this.attributesToSnippet = params.attributesToSnippet;
    /**
     * Enable the ranking informations in the response, set to 1 to activate
     * @see https://www.algolia.com/doc/rest#param-getRankingInfo
     * @member {number}
     */
    this.getRankingInfo = params.getRankingInfo;
    /**
     * Remove duplicates based on the index setting attributeForDistinct
     * @see https://www.algolia.com/doc/rest#param-distinct
     * @member {boolean|number}
     */
    this.distinct = params.distinct;
    /**
     * Center of the geo search.
     * @see https://www.algolia.com/doc/rest#param-aroundLatLng
     * @member {string}
     */
    this.aroundLatLng = params.aroundLatLng;
    /**
     * Center of the search, retrieve from the user IP.
     * @see https://www.algolia.com/doc/rest#param-aroundLatLngViaIP
     * @member {boolean}
     */
    this.aroundLatLngViaIP = params.aroundLatLngViaIP;
    /**
     * Radius of the geo search.
     * @see https://www.algolia.com/doc/rest#param-aroundRadius
     * @member {number}
     */
    this.aroundRadius = params.aroundRadius;
    /**
     * Precision of the geo search.
     * @see https://www.algolia.com/doc/rest#param-aroundPrecision
     * @member {number}
     */
    this.minimumAroundRadius = params.minimumAroundRadius;
    /**
     * Precision of the geo search.
     * @see https://www.algolia.com/doc/rest#param-minimumAroundRadius
     * @member {number}
     */
    this.aroundPrecision = params.aroundPrecision;
    /**
     * Geo search inside a box.
     * @see https://www.algolia.com/doc/rest#param-insideBoundingBox
     * @member {string}
     */
    this.insideBoundingBox = params.insideBoundingBox;
    /**
     * Geo search inside a polygon.
     * @see https://www.algolia.com/doc/rest#param-insidePolygon
     * @member {string}
     */
    this.insidePolygon = params.insidePolygon;
    /**
     * Allows to specify an ellipsis character for the snippet when we truncate the text
     * (added before and after if truncated).
     * The default value is an empty string and we recommend to set it to "…"
     * @see https://www.algolia.com/doc/rest#param-insidePolygon
     * @member {string}
     */
    this.snippetEllipsisText = params.snippetEllipsisText;
    /**
     * Allows to specify some attributes name on which exact won't be applied.
     * Attributes are separated with a comma (for example "name,address" ), you can also use a
     * JSON string array encoding (for example encodeURIComponent('["name","address"]') ).
     * By default the list is empty.
     * @see https://www.algolia.com/doc/rest#param-disableExactOnAttributes
     * @member {string|string[]}
     */
    this.disableExactOnAttributes = params.disableExactOnAttributes;
    /**
     * Applies 'exact' on single word queries if the word contains at least 3 characters
     * and is not a stop word.
     * Can take two values: true or false.
     * By default, its set to false.
     * @see https://www.algolia.com/doc/rest#param-enableExactOnSingleWordQuery
     * @member {boolean}
     */
    this.enableExactOnSingleWordQuery = params.enableExactOnSingleWordQuery;
  
    // Undocumented parameters, still needed otherwise we fail
    this.offset = params.offset;
    this.length = params.length;
  
    var self = this;
    forOwn(params, function checkForUnknownParameter(paramValue, paramName) {
      if (SearchParameters.PARAMETERS.indexOf(paramName) === -1) {
        self[paramName] = paramValue;
      }
    });
  }
  
  /**
   * List all the properties in SearchParameters and therefore all the known Algolia properties
   * This doesn't contain any beta/hidden features.
   * @private
   */
  SearchParameters.PARAMETERS = keys(new SearchParameters());
  
  /**
   * @private
   * @param {object} partialState full or part of a state
   * @return {object} a new object with the number keys as number
   */
  SearchParameters._parseNumbers = function(partialState) {
    // Do not reparse numbers in SearchParameters, they ought to be parsed already
    if (partialState instanceof SearchParameters) return partialState;
  
    var numbers = {};
  
    var numberKeys = [
      'aroundPrecision',
      'aroundRadius',
      'getRankingInfo',
      'minWordSizefor2Typos',
      'minWordSizefor1Typo',
      'page',
      'maxValuesPerFacet',
      'distinct',
      'minimumAroundRadius',
      'hitsPerPage',
      'minProximity'
    ];
  
    forEach(numberKeys, function(k) {
      var value = partialState[k];
      if (isString(value)) {
        var parsedValue = parseFloat(value);
        numbers[k] = isNaN(parsedValue) ? value : parsedValue;
      }
    });
  
    if (partialState.numericRefinements) {
      var numericRefinements = {};
      forEach(partialState.numericRefinements, function(operators, attribute) {
        numericRefinements[attribute] = {};
        forEach(operators, function(values, operator) {
          var parsedValues = map(values, function(v) {
            if (isArray(v)) {
              return map(v, function(vPrime) {
                if (isString(vPrime)) {
                  return parseFloat(vPrime);
                }
                return vPrime;
              });
            } else if (isString(v)) {
              return parseFloat(v);
            }
            return v;
          });
          numericRefinements[attribute][operator] = parsedValues;
        });
      });
      numbers.numericRefinements = numericRefinements;
    }
  
    return merge({}, partialState, numbers);
  };
  
  /**
   * Factory for SearchParameters
   * @param {object|SearchParameters} newParameters existing parameters or partial
   * object for the properties of a new SearchParameters
   * @return {SearchParameters} frozen instance of SearchParameters
   */
  SearchParameters.make = function makeSearchParameters(newParameters) {
    var instance = new SearchParameters(newParameters);
  
    forEach(newParameters.hierarchicalFacets, function(facet) {
      if (facet.rootPath) {
        var currentRefinement = instance.getHierarchicalRefinement(facet.name);
  
        if (currentRefinement.length > 0 && currentRefinement[0].indexOf(facet.rootPath) !== 0) {
          instance = instance.clearRefinements(facet.name);
        }
  
        // get it again in case it has been cleared
        currentRefinement = instance.getHierarchicalRefinement(facet.name);
        if (currentRefinement.length === 0) {
          instance = instance.toggleHierarchicalFacetRefinement(facet.name, facet.rootPath);
        }
      }
    });
  
    return instance;
  };
  
  /**
   * Validates the new parameters based on the previous state
   * @param {SearchParameters} currentState the current state
   * @param {object|SearchParameters} parameters the new parameters to set
   * @return {Error|null} Error if the modification is invalid, null otherwise
   */
  SearchParameters.validate = function(currentState, parameters) {
    var params = parameters || {};
  
    if (currentState.tagFilters && params.tagRefinements && params.tagRefinements.length > 0) {
      return new Error(
        '[Tags] Cannot switch from the managed tag API to the advanced API. It is probably ' +
        'an error, if it is really what you want, you should first clear the tags with clearTags method.');
    }
  
    if (currentState.tagRefinements.length > 0 && params.tagFilters) {
      return new Error(
        '[Tags] Cannot switch from the advanced tag API to the managed API. It is probably ' +
        'an error, if it is not, you should first clear the tags with clearTags method.');
    }
  
    if (currentState.numericFilters && params.numericRefinements && !isEmpty(params.numericRefinements)) {
      return new Error(
        "[Numeric filters] Can't switch from the advanced to the managed API. It" +
        ' is probably an error, if this is really what you want, you have to first' +
        ' clear the numeric filters.');
    }
  
    if (!isEmpty(currentState.numericRefinements) && params.numericFilters) {
      return new Error(
        "[Numeric filters] Can't switch from the managed API to the advanced. It" +
        ' is probably an error, if this is really what you want, you have to first' +
        ' clear the numeric filters.');
    }
  
    return null;
  };
  
  SearchParameters.prototype = {
    constructor: SearchParameters,
  
    /**
     * Remove all refinements (disjunctive + conjunctive + excludes + numeric filters)
     * @method
     * @param {undefined|string|SearchParameters.clearCallback} [attribute] optional string or function
     * - If not given, means to clear all the filters.
     * - If `string`, means to clear all refinements for the `attribute` named filter.
     * - If `function`, means to clear all the refinements that return truthy values.
     * @return {SearchParameters}
     */
    clearRefinements: function clearRefinements(attribute) {
      var clear = RefinementList.clearRefinement;
      return this.setQueryParameters({
        numericRefinements: this._clearNumericRefinements(attribute),
        facetsRefinements: clear(this.facetsRefinements, attribute, 'conjunctiveFacet'),
        facetsExcludes: clear(this.facetsExcludes, attribute, 'exclude'),
        disjunctiveFacetsRefinements: clear(this.disjunctiveFacetsRefinements, attribute, 'disjunctiveFacet'),
        hierarchicalFacetsRefinements: clear(this.hierarchicalFacetsRefinements, attribute, 'hierarchicalFacet')
      });
    },
    /**
     * Remove all the refined tags from the SearchParameters
     * @method
     * @return {SearchParameters}
     */
    clearTags: function clearTags() {
      if (this.tagFilters === undefined && this.tagRefinements.length === 0) return this;
  
      return this.setQueryParameters({
        tagFilters: undefined,
        tagRefinements: []
      });
    },
    /**
     * Set the index.
     * @method
     * @param {string} index the index name
     * @return {SearchParameters}
     */
    setIndex: function setIndex(index) {
      if (index === this.index) return this;
  
      return this.setQueryParameters({
        index: index
      });
    },
    /**
     * Query setter
     * @method
     * @param {string} newQuery value for the new query
     * @return {SearchParameters}
     */
    setQuery: function setQuery(newQuery) {
      if (newQuery === this.query) return this;
  
      return this.setQueryParameters({
        query: newQuery
      });
    },
    /**
     * Page setter
     * @method
     * @param {number} newPage new page number
     * @return {SearchParameters}
     */
    setPage: function setPage(newPage) {
      if (newPage === this.page) return this;
  
      return this.setQueryParameters({
        page: newPage
      });
    },
    /**
     * Facets setter
     * The facets are the simple facets, used for conjunctive (and) faceting.
     * @method
     * @param {string[]} facets all the attributes of the algolia records used for conjunctive faceting
     * @return {SearchParameters}
     */
    setFacets: function setFacets(facets) {
      return this.setQueryParameters({
        facets: facets
      });
    },
    /**
     * Disjunctive facets setter
     * Change the list of disjunctive (or) facets the helper chan handle.
     * @method
     * @param {string[]} facets all the attributes of the algolia records used for disjunctive faceting
     * @return {SearchParameters}
     */
    setDisjunctiveFacets: function setDisjunctiveFacets(facets) {
      return this.setQueryParameters({
        disjunctiveFacets: facets
      });
    },
    /**
     * HitsPerPage setter
     * Hits per page represents the number of hits retrieved for this query
     * @method
     * @param {number} n number of hits retrieved per page of results
     * @return {SearchParameters}
     */
    setHitsPerPage: function setHitsPerPage(n) {
      if (this.hitsPerPage === n) return this;
  
      return this.setQueryParameters({
        hitsPerPage: n
      });
    },
    /**
     * typoTolerance setter
     * Set the value of typoTolerance
     * @method
     * @param {string} typoTolerance new value of typoTolerance ("true", "false", "min" or "strict")
     * @return {SearchParameters}
     */
    setTypoTolerance: function setTypoTolerance(typoTolerance) {
      if (this.typoTolerance === typoTolerance) return this;
  
      return this.setQueryParameters({
        typoTolerance: typoTolerance
      });
    },
    /**
     * Add a numeric filter for a given attribute
     * When value is an array, they are combined with OR
     * When value is a single value, it will combined with AND
     * @method
     * @param {string} attribute attribute to set the filter on
     * @param {string} operator operator of the filter (possible values: =, >, >=, <, <=, !=)
     * @param {number | number[]} value value of the filter
     * @return {SearchParameters}
     * @example
     * // for price = 50 or 40
     * searchparameter.addNumericRefinement('price', '=', [50, 40]);
     * @example
     * // for size = 38 and 40
     * searchparameter.addNumericRefinement('size', '=', 38);
     * searchparameter.addNumericRefinement('size', '=', 40);
     */
    addNumericRefinement: function(attribute, operator, v) {
      var value = valToNumber(v);
  
      if (this.isNumericRefined(attribute, operator, value)) return this;
  
      var mod = merge({}, this.numericRefinements);
  
      mod[attribute] = merge({}, mod[attribute]);
  
      if (mod[attribute][operator]) {
        // Array copy
        mod[attribute][operator] = mod[attribute][operator].slice();
        // Add the element. Concat can't be used here because value can be an array.
        mod[attribute][operator].push(value);
      } else {
        mod[attribute][operator] = [value];
      }
  
      return this.setQueryParameters({
        numericRefinements: mod
      });
    },
    /**
     * Get the list of conjunctive refinements for a single facet
     * @param {string} facetName name of the attribute used for faceting
     * @return {string[]} list of refinements
     */
    getConjunctiveRefinements: function(facetName) {
      if (!this.isConjunctiveFacet(facetName)) {
        throw new Error(facetName + ' is not defined in the facets attribute of the helper configuration');
      }
      return this.facetsRefinements[facetName] || [];
    },
    /**
     * Get the list of disjunctive refinements for a single facet
     * @param {string} facetName name of the attribute used for faceting
     * @return {string[]} list of refinements
     */
    getDisjunctiveRefinements: function(facetName) {
      if (!this.isDisjunctiveFacet(facetName)) {
        throw new Error(
          facetName + ' is not defined in the disjunctiveFacets attribute of the helper configuration'
        );
      }
      return this.disjunctiveFacetsRefinements[facetName] || [];
    },
    /**
     * Get the list of hierarchical refinements for a single facet
     * @param {string} facetName name of the attribute used for faceting
     * @return {string[]} list of refinements
     */
    getHierarchicalRefinement: function(facetName) {
      // we send an array but we currently do not support multiple
      // hierarchicalRefinements for a hierarchicalFacet
      return this.hierarchicalFacetsRefinements[facetName] || [];
    },
    /**
     * Get the list of exclude refinements for a single facet
     * @param {string} facetName name of the attribute used for faceting
     * @return {string[]} list of refinements
     */
    getExcludeRefinements: function(facetName) {
      if (!this.isConjunctiveFacet(facetName)) {
        throw new Error(facetName + ' is not defined in the facets attribute of the helper configuration');
      }
      return this.facetsExcludes[facetName] || [];
    },
  
    /**
     * Remove all the numeric filter for a given (attribute, operator)
     * @method
     * @param {string} attribute attribute to set the filter on
     * @param {string} [operator] operator of the filter (possible values: =, >, >=, <, <=, !=)
     * @param {number} [number] the value to be removed
     * @return {SearchParameters}
     */
    removeNumericRefinement: function(attribute, operator, paramValue) {
      if (paramValue !== undefined) {
        var paramValueAsNumber = valToNumber(paramValue);
        if (!this.isNumericRefined(attribute, operator, paramValueAsNumber)) return this;
        return this.setQueryParameters({
          numericRefinements: this._clearNumericRefinements(function(value, key) {
            return key === attribute && value.op === operator && isEqual(value.val, paramValueAsNumber);
          })
        });
      } else if (operator !== undefined) {
        if (!this.isNumericRefined(attribute, operator)) return this;
        return this.setQueryParameters({
          numericRefinements: this._clearNumericRefinements(function(value, key) {
            return key === attribute && value.op === operator;
          })
        });
      }
  
      if (!this.isNumericRefined(attribute)) return this;
      return this.setQueryParameters({
        numericRefinements: this._clearNumericRefinements(function(value, key) {
          return key === attribute;
        })
      });
    },
    /**
     * Get the list of numeric refinements for a single facet
     * @param {string} facetName name of the attribute used for faceting
     * @return {SearchParameters.OperatorList[]} list of refinements
     */
    getNumericRefinements: function(facetName) {
      return this.numericRefinements[facetName] || {};
    },
    /**
     * Return the current refinement for the (attribute, operator)
     * @param {string} attribute of the record
     * @param {string} operator applied
     * @return {number} value of the refinement
     */
    getNumericRefinement: function(attribute, operator) {
      return this.numericRefinements[attribute] && this.numericRefinements[attribute][operator];
    },
    /**
     * Clear numeric filters.
     * @method
     * @private
     * @param {string|SearchParameters.clearCallback} [attribute] optional string or function
     * - If not given, means to clear all the filters.
     * - If `string`, means to clear all refinements for the `attribute` named filter.
     * - If `function`, means to clear all the refinements that return truthy values.
     * @return {Object.<string, OperatorList>}
     */
    _clearNumericRefinements: function _clearNumericRefinements(attribute) {
      if (isUndefined(attribute)) {
        return {};
      } else if (isString(attribute)) {
        return omit(this.numericRefinements, attribute);
      } else if (isFunction(attribute)) {
        return reduce(this.numericRefinements, function(memo, operators, key) {
          var operatorList = {};
  
          forEach(operators, function(values, operator) {
            var outValues = [];
            forEach(values, function(value) {
              var predicateResult = attribute({val: value, op: operator}, key, 'numeric');
              if (!predicateResult) outValues.push(value);
            });
            if (!isEmpty(outValues)) operatorList[operator] = outValues;
          });
  
          if (!isEmpty(operatorList)) memo[key] = operatorList;
  
          return memo;
        }, {});
      }
    },
    /**
     * Add a facet to the facets attribute of the helper configuration, if it
     * isn't already present.
     * @method
     * @param {string} facet facet name to add
     * @return {SearchParameters}
     */
    addFacet: function addFacet(facet) {
      if (this.isConjunctiveFacet(facet)) {
        return this;
      }
  
      return this.setQueryParameters({
        facets: this.facets.concat([facet])
      });
    },
    /**
     * Add a disjunctive facet to the disjunctiveFacets attribute of the helper
     * configuration, if it isn't already present.
     * @method
     * @param {string} facet disjunctive facet name to add
     * @return {SearchParameters}
     */
    addDisjunctiveFacet: function addDisjunctiveFacet(facet) {
      if (this.isDisjunctiveFacet(facet)) {
        return this;
      }
  
      return this.setQueryParameters({
        disjunctiveFacets: this.disjunctiveFacets.concat([facet])
      });
    },
    /**
     * Add a hierarchical facet to the hierarchicalFacets attribute of the helper
     * configuration.
     * @method
     * @param {object} hierarchicalFacet hierarchical facet to add
     * @return {SearchParameters}
     * @throws will throw an error if a hierarchical facet with the same name was already declared
     */
    addHierarchicalFacet: function addHierarchicalFacet(hierarchicalFacet) {
      if (this.isHierarchicalFacet(hierarchicalFacet.name)) {
        throw new Error(
          'Cannot declare two hierarchical facets with the same name: `' + hierarchicalFacet.name + '`');
      }
  
      return this.setQueryParameters({
        hierarchicalFacets: this.hierarchicalFacets.concat([hierarchicalFacet])
      });
    },
    /**
     * Add a refinement on a "normal" facet
     * @method
     * @param {string} facet attribute to apply the faceting on
     * @param {string} value value of the attribute (will be converted to string)
     * @return {SearchParameters}
     */
    addFacetRefinement: function addFacetRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      if (RefinementList.isRefined(this.facetsRefinements, facet, value)) return this;
  
      return this.setQueryParameters({
        facetsRefinements: RefinementList.addRefinement(this.facetsRefinements, facet, value)
      });
    },
    /**
     * Exclude a value from a "normal" facet
     * @method
     * @param {string} facet attribute to apply the exclusion on
     * @param {string} value value of the attribute (will be converted to string)
     * @return {SearchParameters}
     */
    addExcludeRefinement: function addExcludeRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      if (RefinementList.isRefined(this.facetsExcludes, facet, value)) return this;
  
      return this.setQueryParameters({
        facetsExcludes: RefinementList.addRefinement(this.facetsExcludes, facet, value)
      });
    },
    /**
     * Adds a refinement on a disjunctive facet.
     * @method
     * @param {string} facet attribute to apply the faceting on
     * @param {string} value value of the attribute (will be converted to string)
     * @return {SearchParameters}
     */
    addDisjunctiveFacetRefinement: function addDisjunctiveFacetRefinement(facet, value) {
      if (!this.isDisjunctiveFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration');
      }
  
      if (RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)) return this;
  
      return this.setQueryParameters({
        disjunctiveFacetsRefinements: RefinementList.addRefinement(
          this.disjunctiveFacetsRefinements, facet, value)
      });
    },
    /**
     * addTagRefinement adds a tag to the list used to filter the results
     * @param {string} tag tag to be added
     * @return {SearchParameters}
     */
    addTagRefinement: function addTagRefinement(tag) {
      if (this.isTagRefined(tag)) return this;
  
      var modification = {
        tagRefinements: this.tagRefinements.concat(tag)
      };
  
      return this.setQueryParameters(modification);
    },
    /**
     * Remove a facet from the facets attribute of the helper configuration, if it
     * is present.
     * @method
     * @param {string} facet facet name to remove
     * @return {SearchParameters}
     */
    removeFacet: function removeFacet(facet) {
      if (!this.isConjunctiveFacet(facet)) {
        return this;
      }
  
      return this.clearRefinements(facet).setQueryParameters({
        facets: filter(this.facets, function(f) {
          return f !== facet;
        })
      });
    },
    /**
     * Remove a disjunctive facet from the disjunctiveFacets attribute of the
     * helper configuration, if it is present.
     * @method
     * @param {string} facet disjunctive facet name to remove
     * @return {SearchParameters}
     */
    removeDisjunctiveFacet: function removeDisjunctiveFacet(facet) {
      if (!this.isDisjunctiveFacet(facet)) {
        return this;
      }
  
      return this.clearRefinements(facet).setQueryParameters({
        disjunctiveFacets: filter(this.disjunctiveFacets, function(f) {
          return f !== facet;
        })
      });
    },
    /**
     * Remove a hierarchical facet from the hierarchicalFacets attribute of the
     * helper configuration, if it is present.
     * @method
     * @param {string} facet hierarchical facet name to remove
     * @return {SearchParameters}
     */
    removeHierarchicalFacet: function removeHierarchicalFacet(facet) {
      if (!this.isHierarchicalFacet(facet)) {
        return this;
      }
  
      return this.clearRefinements(facet).setQueryParameters({
        hierarchicalFacets: filter(this.hierarchicalFacets, function(f) {
          return f.name !== facet;
        })
      });
    },
    /**
     * Remove a refinement set on facet. If a value is provided, it will clear the
     * refinement for the given value, otherwise it will clear all the refinement
     * values for the faceted attribute.
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {string} [value] value used to filter
     * @return {SearchParameters}
     */
    removeFacetRefinement: function removeFacetRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      if (!RefinementList.isRefined(this.facetsRefinements, facet, value)) return this;
  
      return this.setQueryParameters({
        facetsRefinements: RefinementList.removeRefinement(this.facetsRefinements, facet, value)
      });
    },
    /**
     * Remove a negative refinement on a facet
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {string} value value used to filter
     * @return {SearchParameters}
     */
    removeExcludeRefinement: function removeExcludeRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      if (!RefinementList.isRefined(this.facetsExcludes, facet, value)) return this;
  
      return this.setQueryParameters({
        facetsExcludes: RefinementList.removeRefinement(this.facetsExcludes, facet, value)
      });
    },
    /**
     * Remove a refinement on a disjunctive facet
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {string} value value used to filter
     * @return {SearchParameters}
     */
    removeDisjunctiveFacetRefinement: function removeDisjunctiveFacetRefinement(facet, value) {
      if (!this.isDisjunctiveFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration');
      }
      if (!RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)) return this;
  
      return this.setQueryParameters({
        disjunctiveFacetsRefinements: RefinementList.removeRefinement(
          this.disjunctiveFacetsRefinements, facet, value)
      });
    },
    /**
     * Remove a tag from the list of tag refinements
     * @method
     * @param {string} tag the tag to remove
     * @return {SearchParameters}
     */
    removeTagRefinement: function removeTagRefinement(tag) {
      if (!this.isTagRefined(tag)) return this;
  
      var modification = {
        tagRefinements: filter(this.tagRefinements, function(t) { return t !== tag; })
      };
  
      return this.setQueryParameters(modification);
    },
    /**
     * Generic toggle refinement method to use with facet, disjunctive facets
     * and hierarchical facets
     * @param  {string} facet the facet to refine
     * @param  {string} value the associated value
     * @return {SearchParameters}
     * @throws will throw an error if the facet is not declared in the settings of the helper
     * @deprecated since version 2.19.0, see {@link SearchParameters#toggleFacetRefinement}
     */
    toggleRefinement: function toggleRefinement(facet, value) {
      return this.toggleFacetRefinement(facet, value);
    },
    /**
     * Generic toggle refinement method to use with facet, disjunctive facets
     * and hierarchical facets
     * @param  {string} facet the facet to refine
     * @param  {string} value the associated value
     * @return {SearchParameters}
     * @throws will throw an error if the facet is not declared in the settings of the helper
     */
    toggleFacetRefinement: function toggleFacetRefinement(facet, value) {
      if (this.isHierarchicalFacet(facet)) {
        return this.toggleHierarchicalFacetRefinement(facet, value);
      } else if (this.isConjunctiveFacet(facet)) {
        return this.toggleConjunctiveFacetRefinement(facet, value);
      } else if (this.isDisjunctiveFacet(facet)) {
        return this.toggleDisjunctiveFacetRefinement(facet, value);
      }
  
      throw new Error('Cannot refine the undeclared facet ' + facet +
        '; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets');
    },
    /**
     * Switch the refinement applied over a facet/value
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {SearchParameters}
     */
    toggleConjunctiveFacetRefinement: function toggleConjunctiveFacetRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
  
      return this.setQueryParameters({
        facetsRefinements: RefinementList.toggleRefinement(this.facetsRefinements, facet, value)
      });
    },
    /**
     * Switch the refinement applied over a facet/value
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {SearchParameters}
     */
    toggleExcludeFacetRefinement: function toggleExcludeFacetRefinement(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
  
      return this.setQueryParameters({
        facetsExcludes: RefinementList.toggleRefinement(this.facetsExcludes, facet, value)
      });
    },
    /**
     * Switch the refinement applied over a facet/value
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {SearchParameters}
     */
    toggleDisjunctiveFacetRefinement: function toggleDisjunctiveFacetRefinement(facet, value) {
      if (!this.isDisjunctiveFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration');
      }
  
      return this.setQueryParameters({
        disjunctiveFacetsRefinements: RefinementList.toggleRefinement(
          this.disjunctiveFacetsRefinements, facet, value)
      });
    },
    /**
     * Switch the refinement applied over a facet/value
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {SearchParameters}
     */
    toggleHierarchicalFacetRefinement: function toggleHierarchicalFacetRefinement(facet, value) {
      if (!this.isHierarchicalFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the hierarchicalFacets attribute of the helper configuration');
      }
  
      var separator = this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(facet));
  
      var mod = {};
  
      var upOneOrMultipleLevel = this.hierarchicalFacetsRefinements[facet] !== undefined &&
        this.hierarchicalFacetsRefinements[facet].length > 0 && (
        // remove current refinement:
        // refinement was 'beer > IPA', call is toggleRefine('beer > IPA'), refinement should be `beer`
        this.hierarchicalFacetsRefinements[facet][0] === value ||
        // remove a parent refinement of the current refinement:
        //  - refinement was 'beer > IPA > Flying dog'
        //  - call is toggleRefine('beer > IPA')
        //  - refinement should be `beer`
        this.hierarchicalFacetsRefinements[facet][0].indexOf(value + separator) === 0
      );
  
      if (upOneOrMultipleLevel) {
        if (value.indexOf(separator) === -1) {
          // go back to root level
          mod[facet] = [];
        } else {
          mod[facet] = [value.slice(0, value.lastIndexOf(separator))];
        }
      } else {
        mod[facet] = [value];
      }
  
      return this.setQueryParameters({
        hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
      });
    },
  
    /**
     * Adds a refinement on a hierarchical facet.
     * @param {string} facet the facet name
     * @param {string} path the hierarchical facet path
     * @return {SearchParameter} the new state
     * @throws Error if the facet is not defined or if the facet is refined
     */
    addHierarchicalFacetRefinement: function(facet, path) {
      if (this.isHierarchicalFacetRefined(facet)) {
        throw new Error(facet + ' is already refined.');
      }
      var mod = {};
      mod[facet] = [path];
      return this.setQueryParameters({
        hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
      });
    },
  
    /**
     * Removes the refinement set on a hierarchical facet.
     * @param {string} facet the facet name
     * @return {SearchParameter} the new state
     * @throws Error if the facet is not defined or if the facet is not refined
     */
    removeHierarchicalFacetRefinement: function(facet) {
      if (!this.isHierarchicalFacetRefined(facet)) {
        throw new Error(facet + ' is not refined.');
      }
      var mod = {};
      mod[facet] = [];
      return this.setQueryParameters({
        hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements)
      });
    },
    /**
     * Switch the tag refinement
     * @method
     * @param {string} tag the tag to remove or add
     * @return {SearchParameters}
     */
    toggleTagRefinement: function toggleTagRefinement(tag) {
      if (this.isTagRefined(tag)) {
        return this.removeTagRefinement(tag);
      }
  
      return this.addTagRefinement(tag);
    },
    /**
     * Test if the facet name is from one of the disjunctive facets
     * @method
     * @param {string} facet facet name to test
     * @return {boolean}
     */
    isDisjunctiveFacet: function(facet) {
      return indexOf(this.disjunctiveFacets, facet) > -1;
    },
    /**
     * Test if the facet name is from one of the hierarchical facets
     * @method
     * @param {string} facetName facet name to test
     * @return {boolean}
     */
    isHierarchicalFacet: function(facetName) {
      return this.getHierarchicalFacetByName(facetName) !== undefined;
    },
    /**
     * Test if the facet name is from one of the conjunctive/normal facets
     * @method
     * @param {string} facet facet name to test
     * @return {boolean}
     */
    isConjunctiveFacet: function(facet) {
      return indexOf(this.facets, facet) > -1;
    },
    /**
     * Returns true if the facet is refined, either for a specific value or in
     * general.
     * @method
     * @param {string} facet name of the attribute for used for faceting
     * @param {string} value, optional value. If passed will test that this value
     * is filtering the given facet.
     * @return {boolean} returns true if refined
     */
    isFacetRefined: function isFacetRefined(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      return RefinementList.isRefined(this.facetsRefinements, facet, value);
    },
    /**
     * Returns true if the facet contains exclusions or if a specific value is
     * excluded.
     *
     * @method
     * @param {string} facet name of the attribute for used for faceting
     * @param {string} [value] optional value. If passed will test that this value
     * is filtering the given facet.
     * @return {boolean} returns true if refined
     */
    isExcludeRefined: function isExcludeRefined(facet, value) {
      if (!this.isConjunctiveFacet(facet)) {
        throw new Error(facet + ' is not defined in the facets attribute of the helper configuration');
      }
      return RefinementList.isRefined(this.facetsExcludes, facet, value);
    },
    /**
     * Returns true if the facet contains a refinement, or if a value passed is a
     * refinement for the facet.
     * @method
     * @param {string} facet name of the attribute for used for faceting
     * @param {string} value optional, will test if the value is used for refinement
     * if there is one, otherwise will test if the facet contains any refinement
     * @return {boolean}
     */
    isDisjunctiveFacetRefined: function isDisjunctiveFacetRefined(facet, value) {
      if (!this.isDisjunctiveFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration');
      }
      return RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value);
    },
    /**
     * Returns true if the facet contains a refinement, or if a value passed is a
     * refinement for the facet.
     * @method
     * @param {string} facet name of the attribute for used for faceting
     * @param {string} value optional, will test if the value is used for refinement
     * if there is one, otherwise will test if the facet contains any refinement
     * @return {boolean}
     */
    isHierarchicalFacetRefined: function isHierarchicalFacetRefined(facet, value) {
      if (!this.isHierarchicalFacet(facet)) {
        throw new Error(
          facet + ' is not defined in the hierarchicalFacets attribute of the helper configuration');
      }
  
      var refinements = this.getHierarchicalRefinement(facet);
  
      if (!value) {
        return refinements.length > 0;
      }
  
      return indexOf(refinements, value) !== -1;
    },
    /**
     * Test if the triple (attribute, operator, value) is already refined.
     * If only the attribute and the operator are provided, it tests if the
     * contains any refinement value.
     * @method
     * @param {string} attribute attribute for which the refinement is applied
     * @param {string} [operator] operator of the refinement
     * @param {string} [value] value of the refinement
     * @return {boolean} true if it is refined
     */
    isNumericRefined: function isNumericRefined(attribute, operator, value) {
      if (isUndefined(value) && isUndefined(operator)) {
        return !!this.numericRefinements[attribute];
      }
  
      var isOperatorDefined = this.numericRefinements[attribute] &&
        !isUndefined(this.numericRefinements[attribute][operator]);
  
      if (isUndefined(value) || !isOperatorDefined) {
        return isOperatorDefined;
      }
  
      var parsedValue = valToNumber(value);
      var isAttributeValueDefined = !isUndefined(
        findArray(this.numericRefinements[attribute][operator], parsedValue)
      );
  
      return isOperatorDefined && isAttributeValueDefined;
    },
    /**
     * Returns true if the tag refined, false otherwise
     * @method
     * @param {string} tag the tag to check
     * @return {boolean}
     */
    isTagRefined: function isTagRefined(tag) {
      return indexOf(this.tagRefinements, tag) !== -1;
    },
    /**
     * Returns the list of all disjunctive facets refined
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {string[]}
     */
    getRefinedDisjunctiveFacets: function getRefinedDisjunctiveFacets() {
      // attributes used for numeric filter can also be disjunctive
      var disjunctiveNumericRefinedFacets = intersection(
        keys(this.numericRefinements),
        this.disjunctiveFacets
      );
  
      return keys(this.disjunctiveFacetsRefinements)
        .concat(disjunctiveNumericRefinedFacets)
        .concat(this.getRefinedHierarchicalFacets());
    },
    /**
     * Returns the list of all disjunctive facets refined
     * @method
     * @param {string} facet name of the attribute used for faceting
     * @param {value} value value used for filtering
     * @return {string[]}
     */
    getRefinedHierarchicalFacets: function getRefinedHierarchicalFacets() {
      return intersection(
        // enforce the order between the two arrays,
        // so that refinement name index === hierarchical facet index
        map(this.hierarchicalFacets, 'name'),
        keys(this.hierarchicalFacetsRefinements)
      );
    },
    /**
     * Returned the list of all disjunctive facets not refined
     * @method
     * @return {string[]}
     */
    getUnrefinedDisjunctiveFacets: function() {
      var refinedFacets = this.getRefinedDisjunctiveFacets();
  
      return filter(this.disjunctiveFacets, function(f) {
        return indexOf(refinedFacets, f) === -1;
      });
    },
  
    managedParameters: [
      'index',
      'facets', 'disjunctiveFacets', 'facetsRefinements',
      'facetsExcludes', 'disjunctiveFacetsRefinements',
      'numericRefinements', 'tagRefinements', 'hierarchicalFacets', 'hierarchicalFacetsRefinements'
    ],
    getQueryParams: function getQueryParams() {
      var managedParameters = this.managedParameters;
  
      var queryParams = {};
  
      forOwn(this, function(paramValue, paramName) {
        if (indexOf(managedParameters, paramName) === -1 && paramValue !== undefined) {
          queryParams[paramName] = paramValue;
        }
      });
  
      return queryParams;
    },
    /**
     * Let the user retrieve any parameter value from the SearchParameters
     * @param {string} paramName name of the parameter
     * @return {any} the value of the parameter
     */
    getQueryParameter: function getQueryParameter(paramName) {
      if (!this.hasOwnProperty(paramName)) {
        throw new Error(
          "Parameter '" + paramName + "' is not an attribute of SearchParameters " +
          '(http://algolia.github.io/algoliasearch-helper-js/docs/SearchParameters.html)');
      }
  
      return this[paramName];
    },
    /**
     * Let the user set a specific value for a given parameter. Will return the
     * same instance if the parameter is invalid or if the value is the same as the
     * previous one.
     * @method
     * @param {string} parameter the parameter name
     * @param {any} value the value to be set, must be compliant with the definition
     * of the attribute on the object
     * @return {SearchParameters} the updated state
     */
    setQueryParameter: function setParameter(parameter, value) {
      if (this[parameter] === value) return this;
  
      var modification = {};
  
      modification[parameter] = value;
  
      return this.setQueryParameters(modification);
    },
    /**
     * Let the user set any of the parameters with a plain object.
     * @method
     * @param {object} params all the keys and the values to be updated
     * @return {SearchParameters} a new updated instance
     */
    setQueryParameters: function setQueryParameters(params) {
      if (!params) return this;
  
      var error = SearchParameters.validate(this, params);
  
      if (error) {
        throw error;
      }
  
      var parsedParams = SearchParameters._parseNumbers(params);
  
      return this.mutateMe(function mergeWith(newInstance) {
        var ks = keys(params);
  
        forEach(ks, function(k) {
          newInstance[k] = parsedParams[k];
        });
  
        return newInstance;
      });
    },
  
    /**
     * Returns an object with only the selected attributes.
     * @param {string[]} filters filters to retrieve only a subset of the state. It
     * accepts strings that can be either attributes of the SearchParameters (e.g. hitsPerPage)
     * or attributes of the index with the notation 'attribute:nameOfMyAttribute'
     * @return {object}
     */
    filter: function(filters) {
      return filterState(this, filters);
    },
    /**
     * Helper function to make it easier to build new instances from a mutating
     * function
     * @private
     * @param {function} fn newMutableState -> previousState -> () function that will
     * change the value of the newMutable to the desired state
     * @return {SearchParameters} a new instance with the specified modifications applied
     */
    mutateMe: function mutateMe(fn) {
      var newState = new this.constructor(this);
  
      fn(newState, this);
      return newState;
    },
  
    /**
     * Helper function to get the hierarchicalFacet separator or the default one (`>`)
     * @param  {object} hierarchicalFacet
     * @return {string} returns the hierarchicalFacet.separator or `>` as default
     */
    _getHierarchicalFacetSortBy: function(hierarchicalFacet) {
      return hierarchicalFacet.sortBy || ['isRefined:desc', 'name:asc'];
    },
  
    /**
     * Helper function to get the hierarchicalFacet separator or the default one (`>`)
     * @private
     * @param  {object} hierarchicalFacet
     * @return {string} returns the hierarchicalFacet.separator or `>` as default
     */
    _getHierarchicalFacetSeparator: function(hierarchicalFacet) {
      return hierarchicalFacet.separator || ' > ';
    },
  
    /**
     * Helper function to get the hierarchicalFacet prefix path or null
     * @private
     * @param  {object} hierarchicalFacet
     * @return {string} returns the hierarchicalFacet.rootPath or null as default
     */
    _getHierarchicalRootPath: function(hierarchicalFacet) {
      return hierarchicalFacet.rootPath || null;
    },
  
    /**
     * Helper function to check if we show the parent level of the hierarchicalFacet
     * @private
     * @param  {object} hierarchicalFacet
     * @return {string} returns the hierarchicalFacet.showParentLevel or true as default
     */
    _getHierarchicalShowParentLevel: function(hierarchicalFacet) {
      if (typeof hierarchicalFacet.showParentLevel === 'boolean') {
        return hierarchicalFacet.showParentLevel;
      }
      return true;
    },
  
    /**
     * Helper function to get the hierarchicalFacet by it's name
     * @param  {string} hierarchicalFacetName
     * @return {object} a hierarchicalFacet
     */
    getHierarchicalFacetByName: function(hierarchicalFacetName) {
      return find(
        this.hierarchicalFacets,
        {name: hierarchicalFacetName}
      );
    },
  
    /**
     * Get the current breadcrumb for a hierarchical facet, as an array
     * @param  {string} facetName Hierarchical facet name
     * @return {array.<string>} the path as an array of string
     */
    getHierarchicalFacetBreadcrumb: function(facetName) {
      if (!this.isHierarchicalFacet(facetName)) {
        throw new Error(
          'Cannot get the breadcrumb of an unknown hierarchical facet: `' + facetName + '`');
      }
  
      var refinement = this.getHierarchicalRefinement(facetName)[0];
      if (!refinement) return [];
  
      var separator = this._getHierarchicalFacetSeparator(
        this.getHierarchicalFacetByName(facetName)
      );
      var path = refinement.split(separator);
      return map(path, trim);
    }
  };
  
  /**
   * Callback used for clearRefinement method
   * @callback SearchParameters.clearCallback
   * @param {OperatorList|FacetList} value the value of the filter
   * @param {string} key the current attribute name
   * @param {string} type `numeric`, `disjunctiveFacet`, `conjunctiveFacet`, `hierarchicalFacet` or `exclude`
   * depending on the type of facet
   * @return {boolean} `true` if the element should be removed. `false` otherwise.
   */
  module.exports = SearchParameters;
  
  
  /***/ }),
  /* 101 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayFilter = __webpack_require__(87),
      baseFilter = __webpack_require__(255),
      baseIteratee = __webpack_require__(13),
      isArray = __webpack_require__(0);
  
  /**
   * Iterates over elements of `collection`, returning an array of all elements
   * `predicate` returns truthy for. The predicate is invoked with three
   * arguments: (value, index|key, collection).
   *
   * **Note:** Unlike `_.remove`, this method returns a new array.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Collection
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} [predicate=_.identity] The function invoked per iteration.
   * @returns {Array} Returns the new filtered array.
   * @see _.reject
   * @example
   *
   * var users = [
   *   { 'user': 'barney', 'age': 36, 'active': true },
   *   { 'user': 'fred',   'age': 40, 'active': false }
   * ];
   *
   * _.filter(users, function(o) { return !o.active; });
   * // => objects for ['fred']
   *
   * // The `_.matches` iteratee shorthand.
   * _.filter(users, { 'age': 36, 'active': true });
   * // => objects for ['barney']
   *
   * // The `_.matchesProperty` iteratee shorthand.
   * _.filter(users, ['active', false]);
   * // => objects for ['fred']
   *
   * // The `_.property` iteratee shorthand.
   * _.filter(users, 'active');
   * // => objects for ['barney']
   */
  function filter(collection, predicate) {
    var func = isArray(collection) ? arrayFilter : baseFilter;
    return func(collection, baseIteratee(predicate, 3));
  }
  
  module.exports = filter;
  
  
  /***/ }),
  /* 102 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var apply = __webpack_require__(68),
      assignInWith = __webpack_require__(274),
      baseRest = __webpack_require__(25),
      customDefaultsAssignIn = __webpack_require__(275);
  
  /**
   * Assigns own and inherited enumerable string keyed properties of source
   * objects to the destination object for all destination properties that
   * resolve to `undefined`. Source objects are applied from left to right.
   * Once a property is set, additional values of the same property are ignored.
   *
   * **Note:** This method mutates `object`.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The destination object.
   * @param {...Object} [sources] The source objects.
   * @returns {Object} Returns `object`.
   * @see _.defaultsDeep
   * @example
   *
   * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
   * // => { 'a': 1, 'b': 2 }
   */
  var defaults = baseRest(function(args) {
    args.push(undefined, customDefaultsAssignIn);
    return apply(assignInWith, undefined, args);
  });
  
  module.exports = defaults;
  
  
  /***/ }),
  /* 103 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseMerge = __webpack_require__(276),
      createAssigner = __webpack_require__(188);
  
  /**
   * This method is like `_.assign` except that it recursively merges own and
   * inherited enumerable string keyed properties of source objects into the
   * destination object. Source properties that resolve to `undefined` are
   * skipped if a destination value exists. Array and plain object properties
   * are merged recursively. Other objects and value types are overridden by
   * assignment. Source objects are applied from left to right. Subsequent
   * sources overwrite property assignments of previous sources.
   *
   * **Note:** This method mutates `object`.
   *
   * @static
   * @memberOf _
   * @since 0.5.0
   * @category Object
   * @param {Object} object The destination object.
   * @param {...Object} [sources] The source objects.
   * @returns {Object} Returns `object`.
   * @example
   *
   * var object = {
   *   'a': [{ 'b': 2 }, { 'd': 4 }]
   * };
   *
   * var other = {
   *   'a': [{ 'c': 3 }, { 'e': 5 }]
   * };
   *
   * _.merge(object, other);
   * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
   */
  var merge = createAssigner(function(object, source, srcIndex) {
    baseMerge(object, source, srcIndex);
  });
  
  module.exports = merge;
  
  
  /***/ }),
  /* 104 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseOrderBy = __webpack_require__(288),
      isArray = __webpack_require__(0);
  
  /**
   * This method is like `_.sortBy` except that it allows specifying the sort
   * orders of the iteratees to sort by. If `orders` is unspecified, all values
   * are sorted in ascending order. Otherwise, specify an order of "desc" for
   * descending or "asc" for ascending sort order of corresponding values.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Collection
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
   *  The iteratees to sort by.
   * @param {string[]} [orders] The sort orders of `iteratees`.
   * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
   * @returns {Array} Returns the new sorted array.
   * @example
   *
   * var users = [
   *   { 'user': 'fred',   'age': 48 },
   *   { 'user': 'barney', 'age': 34 },
   *   { 'user': 'fred',   'age': 40 },
   *   { 'user': 'barney', 'age': 36 }
   * ];
   *
   * // Sort by `user` in ascending order and by `age` in descending order.
   * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
   * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
   */
  function orderBy(collection, iteratees, orders, guard) {
    if (collection == null) {
      return [];
    }
    if (!isArray(iteratees)) {
      iteratees = iteratees == null ? [] : [iteratees];
    }
    orders = guard ? undefined : orders;
    if (!isArray(orders)) {
      orders = orders == null ? [] : [orders];
    }
    return baseOrderBy(collection, iteratees, orders);
  }
  
  module.exports = orderBy;
  
  
  /***/ }),
  /* 105 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseSetData = __webpack_require__(191),
      createBind = __webpack_require__(293),
      createCurry = __webpack_require__(294),
      createHybrid = __webpack_require__(193),
      createPartial = __webpack_require__(306),
      getData = __webpack_require__(197),
      mergeData = __webpack_require__(307),
      setData = __webpack_require__(199),
      setWrapToString = __webpack_require__(200),
      toInteger = __webpack_require__(50);
  
  /** Error message constants. */
  var FUNC_ERROR_TEXT = 'Expected a function';
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_FLAG = 8,
      WRAP_CURRY_RIGHT_FLAG = 16,
      WRAP_PARTIAL_FLAG = 32,
      WRAP_PARTIAL_RIGHT_FLAG = 64;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * Creates a function that either curries or invokes `func` with optional
   * `this` binding and partially applied arguments.
   *
   * @private
   * @param {Function|string} func The function or method name to wrap.
   * @param {number} bitmask The bitmask flags.
   *    1 - `_.bind`
   *    2 - `_.bindKey`
   *    4 - `_.curry` or `_.curryRight` of a bound function
   *    8 - `_.curry`
   *   16 - `_.curryRight`
   *   32 - `_.partial`
   *   64 - `_.partialRight`
   *  128 - `_.rearg`
   *  256 - `_.ary`
   *  512 - `_.flip`
   * @param {*} [thisArg] The `this` binding of `func`.
   * @param {Array} [partials] The arguments to be partially applied.
   * @param {Array} [holders] The `partials` placeholder indexes.
   * @param {Array} [argPos] The argument positions of the new function.
   * @param {number} [ary] The arity cap of `func`.
   * @param {number} [arity] The arity of `func`.
   * @returns {Function} Returns the new wrapped function.
   */
  function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
    var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
    if (!isBindKey && typeof func != 'function') {
      throw new TypeError(FUNC_ERROR_TEXT);
    }
    var length = partials ? partials.length : 0;
    if (!length) {
      bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
      partials = holders = undefined;
    }
    ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
    arity = arity === undefined ? arity : toInteger(arity);
    length -= holders ? holders.length : 0;
  
    if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
      var partialsRight = partials,
          holdersRight = holders;
  
      partials = holders = undefined;
    }
    var data = isBindKey ? undefined : getData(func);
  
    var newData = [
      func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
      argPos, ary, arity
    ];
  
    if (data) {
      mergeData(newData, data);
    }
    func = newData[0];
    bitmask = newData[1];
    thisArg = newData[2];
    partials = newData[3];
    holders = newData[4];
    arity = newData[9] = newData[9] === undefined
      ? (isBindKey ? 0 : func.length)
      : nativeMax(newData[9] - length, 0);
  
    if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
      bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
    }
    if (!bitmask || bitmask == WRAP_BIND_FLAG) {
      var result = createBind(func, bitmask, thisArg);
    } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
      result = createCurry(func, bitmask, arity);
    } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
      result = createPartial(func, bitmask, thisArg, partials);
    } else {
      result = createHybrid.apply(undefined, newData);
    }
    var setter = data ? baseSetData : setData;
    return setWrapToString(setter(result, newData), func, bitmask);
  }
  
  module.exports = createWrap;
  
  
  /***/ }),
  /* 106 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseCreate = __webpack_require__(70),
      baseLodash = __webpack_require__(107);
  
  /** Used as references for the maximum length and index of an array. */
  var MAX_ARRAY_LENGTH = 4294967295;
  
  /**
   * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
   *
   * @private
   * @constructor
   * @param {*} value The value to wrap.
   */
  function LazyWrapper(value) {
    this.__wrapped__ = value;
    this.__actions__ = [];
    this.__dir__ = 1;
    this.__filtered__ = false;
    this.__iteratees__ = [];
    this.__takeCount__ = MAX_ARRAY_LENGTH;
    this.__views__ = [];
  }
  
  // Ensure `LazyWrapper` is an instance of `baseLodash`.
  LazyWrapper.prototype = baseCreate(baseLodash.prototype);
  LazyWrapper.prototype.constructor = LazyWrapper;
  
  module.exports = LazyWrapper;
  
  
  /***/ }),
  /* 107 */
  /***/ (function(module, exports) {
  
  /**
   * The function whose prototype chain sequence wrappers inherit from.
   *
   * @private
   */
  function baseLodash() {
    // No operation performed.
  }
  
  module.exports = baseLodash;
  
  
  /***/ }),
  /* 108 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var has = Object.prototype.hasOwnProperty;
  
  var hexTable = (function () {
      var array = [];
      for (var i = 0; i < 256; ++i) {
          array.push('%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase());
      }
  
      return array;
  }());
  
  exports.arrayToObject = function (source, options) {
      var obj = options && options.plainObjects ? Object.create(null) : {};
      for (var i = 0; i < source.length; ++i) {
          if (typeof source[i] !== 'undefined') {
              obj[i] = source[i];
          }
      }
  
      return obj;
  };
  
  exports.merge = function (target, source, options) {
      if (!source) {
          return target;
      }
  
      if (typeof source !== 'object') {
          if (Array.isArray(target)) {
              target.push(source);
          } else if (typeof target === 'object') {
              target[source] = true;
          } else {
              return [target, source];
          }
  
          return target;
      }
  
      if (typeof target !== 'object') {
          return [target].concat(source);
      }
  
      var mergeTarget = target;
      if (Array.isArray(target) && !Array.isArray(source)) {
          mergeTarget = exports.arrayToObject(target, options);
      }
  
      if (Array.isArray(target) && Array.isArray(source)) {
          source.forEach(function (item, i) {
              if (has.call(target, i)) {
                  if (target[i] && typeof target[i] === 'object') {
                      target[i] = exports.merge(target[i], item, options);
                  } else {
                      target.push(item);
                  }
              } else {
                  target[i] = item;
              }
          });
          return target;
      }
  
      return Object.keys(source).reduce(function (acc, key) {
          var value = source[key];
  
          if (Object.prototype.hasOwnProperty.call(acc, key)) {
              acc[key] = exports.merge(acc[key], value, options);
          } else {
              acc[key] = value;
          }
          return acc;
      }, mergeTarget);
  };
  
  exports.decode = function (str) {
      try {
          return decodeURIComponent(str.replace(/\+/g, ' '));
      } catch (e) {
          return str;
      }
  };
  
  exports.encode = function (str) {
      // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
      // It has been adapted here for stricter adherence to RFC 3986
      if (str.length === 0) {
          return str;
      }
  
      var string = typeof str === 'string' ? str : String(str);
  
      var out = '';
      for (var i = 0; i < string.length; ++i) {
          var c = string.charCodeAt(i);
  
          if (
              c === 0x2D || // -
              c === 0x2E || // .
              c === 0x5F || // _
              c === 0x7E || // ~
              (c >= 0x30 && c <= 0x39) || // 0-9
              (c >= 0x41 && c <= 0x5A) || // a-z
              (c >= 0x61 && c <= 0x7A) // A-Z
          ) {
              out += string.charAt(i);
              continue;
          }
  
          if (c < 0x80) {
              out = out + hexTable[c];
              continue;
          }
  
          if (c < 0x800) {
              out = out + (hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]);
              continue;
          }
  
          if (c < 0xD800 || c >= 0xE000) {
              out = out + (hexTable[0xE0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)]);
              continue;
          }
  
          i += 1;
          c = 0x10000 + (((c & 0x3FF) << 10) | (string.charCodeAt(i) & 0x3FF));
          out += hexTable[0xF0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3F)] + hexTable[0x80 | ((c >> 6) & 0x3F)] + hexTable[0x80 | (c & 0x3F)];
      }
  
      return out;
  };
  
  exports.compact = function (obj, references) {
      if (typeof obj !== 'object' || obj === null) {
          return obj;
      }
  
      var refs = references || [];
      var lookup = refs.indexOf(obj);
      if (lookup !== -1) {
          return refs[lookup];
      }
  
      refs.push(obj);
  
      if (Array.isArray(obj)) {
          var compacted = [];
  
          for (var i = 0; i < obj.length; ++i) {
              if (obj[i] && typeof obj[i] === 'object') {
                  compacted.push(exports.compact(obj[i], refs));
              } else if (typeof obj[i] !== 'undefined') {
                  compacted.push(obj[i]);
              }
          }
  
          return compacted;
      }
  
      var keys = Object.keys(obj);
      keys.forEach(function (key) {
          obj[key] = exports.compact(obj[key], refs);
      });
  
      return obj;
  };
  
  exports.isRegExp = function (obj) {
      return Object.prototype.toString.call(obj) === '[object RegExp]';
  };
  
  exports.isBuffer = function (obj) {
      if (obj === null || typeof obj === 'undefined') {
          return false;
      }
  
      return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
  };
  
  
  /***/ }),
  /* 109 */
  /***/ (function(module, exports) {
  
  // shim for using process in browser
  var process = module.exports = {};
  
  // cached from whatever global is present so that test runners that stub it
  // don't break things.  But we need to wrap it in a try catch in case it is
  // wrapped in strict mode code which doesn't define any globals.  It's inside a
  // function because try/catches deoptimize in certain engines.
  
  var cachedSetTimeout;
  var cachedClearTimeout;
  
  function defaultSetTimout() {
      throw new Error('setTimeout has not been defined');
  }
  function defaultClearTimeout () {
      throw new Error('clearTimeout has not been defined');
  }
  (function () {
      try {
          if (typeof setTimeout === 'function') {
              cachedSetTimeout = setTimeout;
          } else {
              cachedSetTimeout = defaultSetTimout;
          }
      } catch (e) {
          cachedSetTimeout = defaultSetTimout;
      }
      try {
          if (typeof clearTimeout === 'function') {
              cachedClearTimeout = clearTimeout;
          } else {
              cachedClearTimeout = defaultClearTimeout;
          }
      } catch (e) {
          cachedClearTimeout = defaultClearTimeout;
      }
  } ())
  function runTimeout(fun) {
      if (cachedSetTimeout === setTimeout) {
          //normal enviroments in sane situations
          return setTimeout(fun, 0);
      }
      // if setTimeout wasn't available but was latter defined
      if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
          cachedSetTimeout = setTimeout;
          return setTimeout(fun, 0);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedSetTimeout(fun, 0);
      } catch(e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
              return cachedSetTimeout.call(null, fun, 0);
          } catch(e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
              return cachedSetTimeout.call(this, fun, 0);
          }
      }
  
  
  }
  function runClearTimeout(marker) {
      if (cachedClearTimeout === clearTimeout) {
          //normal enviroments in sane situations
          return clearTimeout(marker);
      }
      // if clearTimeout wasn't available but was latter defined
      if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
          cachedClearTimeout = clearTimeout;
          return clearTimeout(marker);
      }
      try {
          // when when somebody has screwed with setTimeout but no I.E. maddness
          return cachedClearTimeout(marker);
      } catch (e){
          try {
              // When we are in I.E. but the script has been evaled so I.E. doesn't  trust the global object when called normally
              return cachedClearTimeout.call(null, marker);
          } catch (e){
              // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
              // Some versions of I.E. have different rules for clearTimeout vs setTimeout
              return cachedClearTimeout.call(this, marker);
          }
      }
  
  
  
  }
  var queue = [];
  var draining = false;
  var currentQueue;
  var queueIndex = -1;
  
  function cleanUpNextTick() {
      if (!draining || !currentQueue) {
          return;
      }
      draining = false;
      if (currentQueue.length) {
          queue = currentQueue.concat(queue);
      } else {
          queueIndex = -1;
      }
      if (queue.length) {
          drainQueue();
      }
  }
  
  function drainQueue() {
      if (draining) {
          return;
      }
      var timeout = runTimeout(cleanUpNextTick);
      draining = true;
  
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          while (++queueIndex < len) {
              if (currentQueue) {
                  currentQueue[queueIndex].run();
              }
          }
          queueIndex = -1;
          len = queue.length;
      }
      currentQueue = null;
      draining = false;
      runClearTimeout(timeout);
  }
  
  process.nextTick = function (fun) {
      var args = new Array(arguments.length - 1);
      if (arguments.length > 1) {
          for (var i = 1; i < arguments.length; i++) {
              args[i - 1] = arguments[i];
          }
      }
      queue.push(new Item(fun, args));
      if (queue.length === 1 && !draining) {
          runTimeout(drainQueue);
      }
  };
  
  // v8 likes predictible objects
  function Item(fun, array) {
      this.fun = fun;
      this.array = array;
  }
  Item.prototype.run = function () {
      this.fun.apply(null, this.array);
  };
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  process.versions = {};
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  process.prependListener = noop;
  process.prependOnceListener = noop;
  
  process.listeners = function (name) { return [] }
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  };
  
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  process.umask = function() { return 0; };
  
  
  /***/ }),
  /* 110 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var basePick = __webpack_require__(325),
      flatRest = __webpack_require__(176);
  
  /**
   * Creates an object composed of the picked `object` properties.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The source object.
   * @param {...(string|string[])} [paths] The property paths to pick.
   * @returns {Object} Returns the new object.
   * @example
   *
   * var object = { 'a': 1, 'b': '2', 'c': 3 };
   *
   * _.pick(object, ['a', 'c']);
   * // => { 'a': 1, 'c': 3 }
   */
  var pick = flatRest(function(object, paths) {
    return object == null ? {} : basePick(object, paths);
  });
  
  module.exports = pick;
  
  
  /***/ }),
  /* 111 */,
  /* 112 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Stack = __webpack_require__(38),
      equalArrays = __webpack_require__(78),
      equalByTag = __webpack_require__(144),
      equalObjects = __webpack_require__(145),
      getTag = __webpack_require__(56),
      isArray = __webpack_require__(0),
      isBuffer = __webpack_require__(21),
      isTypedArray = __webpack_require__(33);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      objectTag = '[object Object]';
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * A specialized version of `baseIsEqual` for arrays and objects which performs
   * deep comparisons and tracks traversed objects enabling objects with circular
   * references to be compared.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} [stack] Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
    var objIsArr = isArray(object),
        othIsArr = isArray(other),
        objTag = objIsArr ? arrayTag : getTag(object),
        othTag = othIsArr ? arrayTag : getTag(other);
  
    objTag = objTag == argsTag ? objectTag : objTag;
    othTag = othTag == argsTag ? objectTag : othTag;
  
    var objIsObj = objTag == objectTag,
        othIsObj = othTag == objectTag,
        isSameTag = objTag == othTag;
  
    if (isSameTag && isBuffer(object)) {
      if (!isBuffer(other)) {
        return false;
      }
      objIsArr = true;
      objIsObj = false;
    }
    if (isSameTag && !objIsObj) {
      stack || (stack = new Stack);
      return (objIsArr || isTypedArray(object))
        ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
        : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
    }
    if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
      var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
          othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
  
      if (objIsWrapped || othIsWrapped) {
        var objUnwrapped = objIsWrapped ? object.value() : object,
            othUnwrapped = othIsWrapped ? other.value() : other;
  
        stack || (stack = new Stack);
        return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
      }
    }
    if (!isSameTag) {
      return false;
    }
    stack || (stack = new Stack);
    return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
  }
  
  module.exports = baseIsEqualDeep;
  
  
  /***/ }),
  /* 113 */
  /***/ (function(module, exports) {
  
  /**
   * Removes all key-value entries from the list cache.
   *
   * @private
   * @name clear
   * @memberOf ListCache
   */
  function listCacheClear() {
    this.__data__ = [];
    this.size = 0;
  }
  
  module.exports = listCacheClear;
  
  
  /***/ }),
  /* 114 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assocIndexOf = __webpack_require__(29);
  
  /** Used for built-in method references. */
  var arrayProto = Array.prototype;
  
  /** Built-in value references. */
  var splice = arrayProto.splice;
  
  /**
   * Removes `key` and its value from the list cache.
   *
   * @private
   * @name delete
   * @memberOf ListCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function listCacheDelete(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      return false;
    }
    var lastIndex = data.length - 1;
    if (index == lastIndex) {
      data.pop();
    } else {
      splice.call(data, index, 1);
    }
    --this.size;
    return true;
  }
  
  module.exports = listCacheDelete;
  
  
  /***/ }),
  /* 115 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assocIndexOf = __webpack_require__(29);
  
  /**
   * Gets the list cache value for `key`.
   *
   * @private
   * @name get
   * @memberOf ListCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function listCacheGet(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    return index < 0 ? undefined : data[index][1];
  }
  
  module.exports = listCacheGet;
  
  
  /***/ }),
  /* 116 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assocIndexOf = __webpack_require__(29);
  
  /**
   * Checks if a list cache value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf ListCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function listCacheHas(key) {
    return assocIndexOf(this.__data__, key) > -1;
  }
  
  module.exports = listCacheHas;
  
  
  /***/ }),
  /* 117 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assocIndexOf = __webpack_require__(29);
  
  /**
   * Sets the list cache `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf ListCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the list cache instance.
   */
  function listCacheSet(key, value) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      ++this.size;
      data.push([key, value]);
    } else {
      data[index][1] = value;
    }
    return this;
  }
  
  module.exports = listCacheSet;
  
  
  /***/ }),
  /* 118 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ListCache = __webpack_require__(28);
  
  /**
   * Removes all key-value entries from the stack.
   *
   * @private
   * @name clear
   * @memberOf Stack
   */
  function stackClear() {
    this.__data__ = new ListCache;
    this.size = 0;
  }
  
  module.exports = stackClear;
  
  
  /***/ }),
  /* 119 */
  /***/ (function(module, exports) {
  
  /**
   * Removes `key` and its value from the stack.
   *
   * @private
   * @name delete
   * @memberOf Stack
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function stackDelete(key) {
    var data = this.__data__,
        result = data['delete'](key);
  
    this.size = data.size;
    return result;
  }
  
  module.exports = stackDelete;
  
  
  /***/ }),
  /* 120 */
  /***/ (function(module, exports) {
  
  /**
   * Gets the stack value for `key`.
   *
   * @private
   * @name get
   * @memberOf Stack
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function stackGet(key) {
    return this.__data__.get(key);
  }
  
  module.exports = stackGet;
  
  
  /***/ }),
  /* 121 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if a stack value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Stack
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function stackHas(key) {
    return this.__data__.has(key);
  }
  
  module.exports = stackHas;
  
  
  /***/ }),
  /* 122 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var ListCache = __webpack_require__(28),
      Map = __webpack_require__(39),
      MapCache = __webpack_require__(40);
  
  /** Used as the size to enable large array optimizations. */
  var LARGE_ARRAY_SIZE = 200;
  
  /**
   * Sets the stack `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Stack
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the stack cache instance.
   */
  function stackSet(key, value) {
    var data = this.__data__;
    if (data instanceof ListCache) {
      var pairs = data.__data__;
      if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
        pairs.push([key, value]);
        this.size = ++data.size;
        return this;
      }
      data = this.__data__ = new MapCache(pairs);
    }
    data.set(key, value);
    this.size = data.size;
    return this;
  }
  
  module.exports = stackSet;
  
  
  /***/ }),
  /* 123 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isFunction = __webpack_require__(19),
      isMasked = __webpack_require__(126),
      isObject = __webpack_require__(6),
      toSource = __webpack_require__(77);
  
  /**
   * Used to match `RegExp`
   * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
   */
  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
  
  /** Used to detect host constructors (Safari). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  
  /** Used for built-in method references. */
  var funcProto = Function.prototype,
      objectProto = Object.prototype;
  
  /** Used to resolve the decompiled source of functions. */
  var funcToString = funcProto.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /** Used to detect if a method is native. */
  var reIsNative = RegExp('^' +
    funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  /**
   * The base implementation of `_.isNative` without bad shim checks.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a native function,
   *  else `false`.
   */
  function baseIsNative(value) {
    if (!isObject(value) || isMasked(value)) {
      return false;
    }
    var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
    return pattern.test(toSource(value));
  }
  
  module.exports = baseIsNative;
  
  
  /***/ }),
  /* 124 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the
   * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
   * of values.
   */
  var nativeObjectToString = objectProto.toString;
  
  /** Built-in value references. */
  var symToStringTag = Symbol ? Symbol.toStringTag : undefined;
  
  /**
   * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the raw `toStringTag`.
   */
  function getRawTag(value) {
    var isOwn = hasOwnProperty.call(value, symToStringTag),
        tag = value[symToStringTag];
  
    try {
      value[symToStringTag] = undefined;
      var unmasked = true;
    } catch (e) {}
  
    var result = nativeObjectToString.call(value);
    if (unmasked) {
      if (isOwn) {
        value[symToStringTag] = tag;
      } else {
        delete value[symToStringTag];
      }
    }
    return result;
  }
  
  module.exports = getRawTag;
  
  
  /***/ }),
  /* 125 */
  /***/ (function(module, exports) {
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /**
   * Used to resolve the
   * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
   * of values.
   */
  var nativeObjectToString = objectProto.toString;
  
  /**
   * Converts `value` to a string using `Object.prototype.toString`.
   *
   * @private
   * @param {*} value The value to convert.
   * @returns {string} Returns the converted string.
   */
  function objectToString(value) {
    return nativeObjectToString.call(value);
  }
  
  module.exports = objectToString;
  
  
  /***/ }),
  /* 126 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var coreJsData = __webpack_require__(127);
  
  /** Used to detect methods masquerading as native. */
  var maskSrcKey = (function() {
    var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
    return uid ? ('Symbol(src)_1.' + uid) : '';
  }());
  
  /**
   * Checks if `func` has its source masked.
   *
   * @private
   * @param {Function} func The function to check.
   * @returns {boolean} Returns `true` if `func` is masked, else `false`.
   */
  function isMasked(func) {
    return !!maskSrcKey && (maskSrcKey in func);
  }
  
  module.exports = isMasked;
  
  
  /***/ }),
  /* 127 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var root = __webpack_require__(3);
  
  /** Used to detect overreaching core-js shims. */
  var coreJsData = root['__core-js_shared__'];
  
  module.exports = coreJsData;
  
  
  /***/ }),
  /* 128 */
  /***/ (function(module, exports) {
  
  /**
   * Gets the value at `key` of `object`.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {string} key The key of the property to get.
   * @returns {*} Returns the property value.
   */
  function getValue(object, key) {
    return object == null ? undefined : object[key];
  }
  
  module.exports = getValue;
  
  
  /***/ }),
  /* 129 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Hash = __webpack_require__(130),
      ListCache = __webpack_require__(28),
      Map = __webpack_require__(39);
  
  /**
   * Removes all key-value entries from the map.
   *
   * @private
   * @name clear
   * @memberOf MapCache
   */
  function mapCacheClear() {
    this.size = 0;
    this.__data__ = {
      'hash': new Hash,
      'map': new (Map || ListCache),
      'string': new Hash
    };
  }
  
  module.exports = mapCacheClear;
  
  
  /***/ }),
  /* 130 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var hashClear = __webpack_require__(131),
      hashDelete = __webpack_require__(132),
      hashGet = __webpack_require__(133),
      hashHas = __webpack_require__(134),
      hashSet = __webpack_require__(135);
  
  /**
   * Creates a hash object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Hash(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  // Add methods to `Hash`.
  Hash.prototype.clear = hashClear;
  Hash.prototype['delete'] = hashDelete;
  Hash.prototype.get = hashGet;
  Hash.prototype.has = hashHas;
  Hash.prototype.set = hashSet;
  
  module.exports = Hash;
  
  
  /***/ }),
  /* 131 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var nativeCreate = __webpack_require__(30);
  
  /**
   * Removes all key-value entries from the hash.
   *
   * @private
   * @name clear
   * @memberOf Hash
   */
  function hashClear() {
    this.__data__ = nativeCreate ? nativeCreate(null) : {};
    this.size = 0;
  }
  
  module.exports = hashClear;
  
  
  /***/ }),
  /* 132 */
  /***/ (function(module, exports) {
  
  /**
   * Removes `key` and its value from the hash.
   *
   * @private
   * @name delete
   * @memberOf Hash
   * @param {Object} hash The hash to modify.
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function hashDelete(key) {
    var result = this.has(key) && delete this.__data__[key];
    this.size -= result ? 1 : 0;
    return result;
  }
  
  module.exports = hashDelete;
  
  
  /***/ }),
  /* 133 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var nativeCreate = __webpack_require__(30);
  
  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Gets the hash value for `key`.
   *
   * @private
   * @name get
   * @memberOf Hash
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function hashGet(key) {
    var data = this.__data__;
    if (nativeCreate) {
      var result = data[key];
      return result === HASH_UNDEFINED ? undefined : result;
    }
    return hasOwnProperty.call(data, key) ? data[key] : undefined;
  }
  
  module.exports = hashGet;
  
  
  /***/ }),
  /* 134 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var nativeCreate = __webpack_require__(30);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Checks if a hash value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Hash
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function hashHas(key) {
    var data = this.__data__;
    return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
  }
  
  module.exports = hashHas;
  
  
  /***/ }),
  /* 135 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var nativeCreate = __webpack_require__(30);
  
  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
  
  /**
   * Sets the hash `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Hash
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the hash instance.
   */
  function hashSet(key, value) {
    var data = this.__data__;
    this.size += this.has(key) ? 0 : 1;
    data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
    return this;
  }
  
  module.exports = hashSet;
  
  
  /***/ }),
  /* 136 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getMapData = __webpack_require__(31);
  
  /**
   * Removes `key` and its value from the map.
   *
   * @private
   * @name delete
   * @memberOf MapCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function mapCacheDelete(key) {
    var result = getMapData(this, key)['delete'](key);
    this.size -= result ? 1 : 0;
    return result;
  }
  
  module.exports = mapCacheDelete;
  
  
  /***/ }),
  /* 137 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is suitable for use as unique object key.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
   */
  function isKeyable(value) {
    var type = typeof value;
    return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
      ? (value !== '__proto__')
      : (value === null);
  }
  
  module.exports = isKeyable;
  
  
  /***/ }),
  /* 138 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getMapData = __webpack_require__(31);
  
  /**
   * Gets the map value for `key`.
   *
   * @private
   * @name get
   * @memberOf MapCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function mapCacheGet(key) {
    return getMapData(this, key).get(key);
  }
  
  module.exports = mapCacheGet;
  
  
  /***/ }),
  /* 139 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getMapData = __webpack_require__(31);
  
  /**
   * Checks if a map value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf MapCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function mapCacheHas(key) {
    return getMapData(this, key).has(key);
  }
  
  module.exports = mapCacheHas;
  
  
  /***/ }),
  /* 140 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getMapData = __webpack_require__(31);
  
  /**
   * Sets the map `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf MapCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the map cache instance.
   */
  function mapCacheSet(key, value) {
    var data = getMapData(this, key),
        size = data.size;
  
    data.set(key, value);
    this.size += data.size == size ? 0 : 1;
    return this;
  }
  
  module.exports = mapCacheSet;
  
  
  /***/ }),
  /* 141 */
  /***/ (function(module, exports) {
  
  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
  
  /**
   * Adds `value` to the array cache.
   *
   * @private
   * @name add
   * @memberOf SetCache
   * @alias push
   * @param {*} value The value to cache.
   * @returns {Object} Returns the cache instance.
   */
  function setCacheAdd(value) {
    this.__data__.set(value, HASH_UNDEFINED);
    return this;
  }
  
  module.exports = setCacheAdd;
  
  
  /***/ }),
  /* 142 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is in the array cache.
   *
   * @private
   * @name has
   * @memberOf SetCache
   * @param {*} value The value to search for.
   * @returns {number} Returns `true` if `value` is found, else `false`.
   */
  function setCacheHas(value) {
    return this.__data__.has(value);
  }
  
  module.exports = setCacheHas;
  
  
  /***/ }),
  /* 143 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.some` for arrays without support for iteratee
   * shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {boolean} Returns `true` if any element passes the predicate check,
   *  else `false`.
   */
  function arraySome(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length;
  
    while (++index < length) {
      if (predicate(array[index], index, array)) {
        return true;
      }
    }
    return false;
  }
  
  module.exports = arraySome;
  
  
  /***/ }),
  /* 144 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14),
      Uint8Array = __webpack_require__(82),
      eq = __webpack_require__(18),
      equalArrays = __webpack_require__(78),
      mapToArray = __webpack_require__(83),
      setToArray = __webpack_require__(84);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;
  
  /** `Object#toString` result references. */
  var boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]';
  
  /** Used to convert symbols to primitives and strings. */
  var symbolProto = Symbol ? Symbol.prototype : undefined,
      symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
  
  /**
   * A specialized version of `baseIsEqualDeep` for comparing objects of
   * the same `toStringTag`.
   *
   * **Note:** This function only supports comparing values with tags of
   * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {string} tag The `toStringTag` of the objects to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
    switch (tag) {
      case dataViewTag:
        if ((object.byteLength != other.byteLength) ||
            (object.byteOffset != other.byteOffset)) {
          return false;
        }
        object = object.buffer;
        other = other.buffer;
  
      case arrayBufferTag:
        if ((object.byteLength != other.byteLength) ||
            !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
          return false;
        }
        return true;
  
      case boolTag:
      case dateTag:
      case numberTag:
        // Coerce booleans to `1` or `0` and dates to milliseconds.
        // Invalid dates are coerced to `NaN`.
        return eq(+object, +other);
  
      case errorTag:
        return object.name == other.name && object.message == other.message;
  
      case regexpTag:
      case stringTag:
        // Coerce regexes to strings and treat strings, primitives and objects,
        // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
        // for more details.
        return object == (other + '');
  
      case mapTag:
        var convert = mapToArray;
  
      case setTag:
        var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
        convert || (convert = setToArray);
  
        if (object.size != other.size && !isPartial) {
          return false;
        }
        // Assume cyclic values are equal.
        var stacked = stack.get(object);
        if (stacked) {
          return stacked == other;
        }
        bitmask |= COMPARE_UNORDERED_FLAG;
  
        // Recursively compare objects (susceptible to call stack limits).
        stack.set(object, other);
        var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
        stack['delete'](object);
        return result;
  
      case symbolTag:
        if (symbolValueOf) {
          return symbolValueOf.call(object) == symbolValueOf.call(other);
        }
    }
    return false;
  }
  
  module.exports = equalByTag;
  
  
  /***/ }),
  /* 145 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getAllKeys = __webpack_require__(85);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1;
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * A specialized version of `baseIsEqualDeep` for objects with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
    var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
        objProps = getAllKeys(object),
        objLength = objProps.length,
        othProps = getAllKeys(other),
        othLength = othProps.length;
  
    if (objLength != othLength && !isPartial) {
      return false;
    }
    var index = objLength;
    while (index--) {
      var key = objProps[index];
      if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
        return false;
      }
    }
    // Assume cyclic values are equal.
    var stacked = stack.get(object);
    if (stacked && stack.get(other)) {
      return stacked == other;
    }
    var result = true;
    stack.set(object, other);
    stack.set(other, object);
  
    var skipCtor = isPartial;
    while (++index < objLength) {
      key = objProps[index];
      var objValue = object[key],
          othValue = other[key];
  
      if (customizer) {
        var compared = isPartial
          ? customizer(othValue, objValue, key, other, object, stack)
          : customizer(objValue, othValue, key, object, other, stack);
      }
      // Recursively compare objects (susceptible to call stack limits).
      if (!(compared === undefined
            ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
            : compared
          )) {
        result = false;
        break;
      }
      skipCtor || (skipCtor = key == 'constructor');
    }
    if (result && !skipCtor) {
      var objCtor = object.constructor,
          othCtor = other.constructor;
  
      // Non `Object` object instances with different constructors are not equal.
      if (objCtor != othCtor &&
          ('constructor' in object && 'constructor' in other) &&
          !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
            typeof othCtor == 'function' && othCtor instanceof othCtor)) {
        result = false;
      }
    }
    stack['delete'](object);
    stack['delete'](other);
    return result;
  }
  
  module.exports = equalObjects;
  
  
  /***/ }),
  /* 146 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.times` without support for iteratee shorthands
   * or max array length checks.
   *
   * @private
   * @param {number} n The number of times to invoke `iteratee`.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the array of results.
   */
  function baseTimes(n, iteratee) {
    var index = -1,
        result = Array(n);
  
    while (++index < n) {
      result[index] = iteratee(index);
    }
    return result;
  }
  
  module.exports = baseTimes;
  
  
  /***/ }),
  /* 147 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]';
  
  /**
   * The base implementation of `_.isArguments`.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   */
  function baseIsArguments(value) {
    return isObjectLike(value) && baseGetTag(value) == argsTag;
  }
  
  module.exports = baseIsArguments;
  
  
  /***/ }),
  /* 148 */
  /***/ (function(module, exports) {
  
  /**
   * This method returns `false`.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {boolean} Returns `false`.
   * @example
   *
   * _.times(2, _.stubFalse);
   * // => [false, false]
   */
  function stubFalse() {
    return false;
  }
  
  module.exports = stubFalse;
  
  
  /***/ }),
  /* 149 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isLength = __webpack_require__(41),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      weakMapTag = '[object WeakMap]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /** Used to identify `toStringTag` values of typed arrays. */
  var typedArrayTags = {};
  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
  typedArrayTags[uint32Tag] = true;
  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
  typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
  typedArrayTags[mapTag] = typedArrayTags[numberTag] =
  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
  typedArrayTags[setTag] = typedArrayTags[stringTag] =
  typedArrayTags[weakMapTag] = false;
  
  /**
   * The base implementation of `_.isTypedArray` without Node.js optimizations.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
   */
  function baseIsTypedArray(value) {
    return isObjectLike(value) &&
      isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
  }
  
  module.exports = baseIsTypedArray;
  
  
  /***/ }),
  /* 150 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(module) {var freeGlobal = __webpack_require__(76);
  
  /** Detect free variable `exports`. */
  var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
  
  /** Detect free variable `module`. */
  var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
  
  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;
  
  /** Detect free variable `process` from Node.js. */
  var freeProcess = moduleExports && freeGlobal.process;
  
  /** Used to access faster Node.js helpers. */
  var nodeUtil = (function() {
    try {
      return freeProcess && freeProcess.binding && freeProcess.binding('util');
    } catch (e) {}
  }());
  
  module.exports = nodeUtil;
  
  /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(55)(module)))
  
  /***/ }),
  /* 151 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var overArg = __webpack_require__(80);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeKeys = overArg(Object.keys, Object);
  
  module.exports = nativeKeys;
  
  
  /***/ }),
  /* 152 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10),
      root = __webpack_require__(3);
  
  /* Built-in method references that are verified to be native. */
  var DataView = getNative(root, 'DataView');
  
  module.exports = DataView;
  
  
  /***/ }),
  /* 153 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10),
      root = __webpack_require__(3);
  
  /* Built-in method references that are verified to be native. */
  var Promise = getNative(root, 'Promise');
  
  module.exports = Promise;
  
  
  /***/ }),
  /* 154 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10),
      root = __webpack_require__(3);
  
  /* Built-in method references that are verified to be native. */
  var Set = getNative(root, 'Set');
  
  module.exports = Set;
  
  
  /***/ }),
  /* 155 */
  /***/ (function(module, exports) {
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * The base implementation of `_.has` without support for deep paths.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {Array|string} key The key to check.
   * @returns {boolean} Returns `true` if `key` exists, else `false`.
   */
  function baseHas(object, key) {
    return object != null && hasOwnProperty.call(object, key);
  }
  
  module.exports = baseHas;
  
  
  /***/ }),
  /* 156 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var memoizeCapped = __webpack_require__(157);
  
  /** Used to match property names within property paths. */
  var reLeadingDot = /^\./,
      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
  
  /** Used to match backslashes in property paths. */
  var reEscapeChar = /\\(\\)?/g;
  
  /**
   * Converts `string` to a property path array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the property path array.
   */
  var stringToPath = memoizeCapped(function(string) {
    var result = [];
    if (reLeadingDot.test(string)) {
      result.push('');
    }
    string.replace(rePropName, function(match, number, quote, string) {
      result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
    });
    return result;
  });
  
  module.exports = stringToPath;
  
  
  /***/ }),
  /* 157 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var memoize = __webpack_require__(158);
  
  /** Used as the maximum memoize cache size. */
  var MAX_MEMOIZE_SIZE = 500;
  
  /**
   * A specialized version of `_.memoize` which clears the memoized function's
   * cache when it exceeds `MAX_MEMOIZE_SIZE`.
   *
   * @private
   * @param {Function} func The function to have its output memoized.
   * @returns {Function} Returns the new memoized function.
   */
  function memoizeCapped(func) {
    var result = memoize(func, function(key) {
      if (cache.size === MAX_MEMOIZE_SIZE) {
        cache.clear();
      }
      return key;
    });
  
    var cache = result.cache;
    return result;
  }
  
  module.exports = memoizeCapped;
  
  
  /***/ }),
  /* 158 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var MapCache = __webpack_require__(40);
  
  /** Error message constants. */
  var FUNC_ERROR_TEXT = 'Expected a function';
  
  /**
   * Creates a function that memoizes the result of `func`. If `resolver` is
   * provided, it determines the cache key for storing the result based on the
   * arguments provided to the memoized function. By default, the first argument
   * provided to the memoized function is used as the map cache key. The `func`
   * is invoked with the `this` binding of the memoized function.
   *
   * **Note:** The cache is exposed as the `cache` property on the memoized
   * function. Its creation may be customized by replacing the `_.memoize.Cache`
   * constructor with one whose instances implement the
   * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
   * method interface of `clear`, `delete`, `get`, `has`, and `set`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Function
   * @param {Function} func The function to have its output memoized.
   * @param {Function} [resolver] The function to resolve the cache key.
   * @returns {Function} Returns the new memoized function.
   * @example
   *
   * var object = { 'a': 1, 'b': 2 };
   * var other = { 'c': 3, 'd': 4 };
   *
   * var values = _.memoize(_.values);
   * values(object);
   * // => [1, 2]
   *
   * values(other);
   * // => [3, 4]
   *
   * object.a = 2;
   * values(object);
   * // => [1, 2]
   *
   * // Modify the result cache.
   * values.cache.set(object, ['a', 'b']);
   * values(object);
   * // => ['a', 'b']
   *
   * // Replace `_.memoize.Cache`.
   * _.memoize.Cache = WeakMap;
   */
  function memoize(func, resolver) {
    if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
      throw new TypeError(FUNC_ERROR_TEXT);
    }
    var memoized = function() {
      var args = arguments,
          key = resolver ? resolver.apply(this, args) : args[0],
          cache = memoized.cache;
  
      if (cache.has(key)) {
        return cache.get(key);
      }
      var result = func.apply(this, args);
      memoized.cache = cache.set(key, result) || cache;
      return result;
    };
    memoized.cache = new (memoize.Cache || MapCache);
    return memoized;
  }
  
  // Expose `MapCache`.
  memoize.Cache = MapCache;
  
  module.exports = memoize;
  
  
  /***/ }),
  /* 159 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  /**
   * Copyright 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   */
  
  
  
  var emptyFunction = __webpack_require__(160);
  var invariant = __webpack_require__(161);
  var ReactPropTypesSecret = __webpack_require__(162);
  
  module.exports = function() {
    function shim(props, propName, componentName, location, propFullName, secret) {
      if (secret === ReactPropTypesSecret) {
        // It is still safe when called from React.
        return;
      }
      invariant(
        false,
        'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
        'Use PropTypes.checkPropTypes() to call them. ' +
        'Read more at http://fb.me/use-check-prop-types'
      );
    };
    shim.isRequired = shim;
    function getShim() {
      return shim;
    };
    // Important!
    // Keep this list in sync with production version in `./factoryWithTypeCheckers.js`.
    var ReactPropTypes = {
      array: shim,
      bool: shim,
      func: shim,
      number: shim,
      object: shim,
      string: shim,
      symbol: shim,
  
      any: shim,
      arrayOf: getShim,
      element: shim,
      instanceOf: getShim,
      node: shim,
      objectOf: getShim,
      oneOf: getShim,
      oneOfType: getShim,
      shape: getShim
    };
  
    ReactPropTypes.checkPropTypes = emptyFunction;
    ReactPropTypes.PropTypes = ReactPropTypes;
  
    return ReactPropTypes;
  };
  
  
  /***/ }),
  /* 160 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  /**
   * Copyright (c) 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   *
   * 
   */
  
  function makeEmptyFunction(arg) {
    return function () {
      return arg;
    };
  }
  
  /**
   * This function accepts and discards inputs; it has no side effects. This is
   * primarily useful idiomatically for overridable function endpoints which
   * always need to be callable, since JS lacks a null-call idiom ala Cocoa.
   */
  var emptyFunction = function emptyFunction() {};
  
  emptyFunction.thatReturns = makeEmptyFunction;
  emptyFunction.thatReturnsFalse = makeEmptyFunction(false);
  emptyFunction.thatReturnsTrue = makeEmptyFunction(true);
  emptyFunction.thatReturnsNull = makeEmptyFunction(null);
  emptyFunction.thatReturnsThis = function () {
    return this;
  };
  emptyFunction.thatReturnsArgument = function (arg) {
    return arg;
  };
  
  module.exports = emptyFunction;
  
  /***/ }),
  /* 161 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  /**
   * Copyright (c) 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   *
   */
  
  
  
  /**
   * Use invariant() to assert state which your program assumes to be true.
   *
   * Provide sprintf-style format (only %s is supported) and arguments
   * to provide information about what broke and what you were
   * expecting.
   *
   * The invariant message will be stripped in production, but the invariant
   * will remain to ensure logic does not differ in production.
   */
  
  var validateFormat = function validateFormat(format) {};
  
  if (false) {
    validateFormat = function validateFormat(format) {
      if (format === undefined) {
        throw new Error('invariant requires an error message argument');
      }
    };
  }
  
  function invariant(condition, format, a, b, c, d, e, f) {
    validateFormat(format);
  
    if (!condition) {
      var error;
      if (format === undefined) {
        error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.');
      } else {
        var args = [a, b, c, d, e, f];
        var argIndex = 0;
        error = new Error(format.replace(/%s/g, function () {
          return args[argIndex++];
        }));
        error.name = 'Invariant Violation';
      }
  
      error.framesToPop = 1; // we don't care about invariant's own frame
      throw error;
    }
  }
  
  module.exports = invariant;
  
  /***/ }),
  /* 162 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  /**
   * Copyright 2013-present, Facebook, Inc.
   * All rights reserved.
   *
   * This source code is licensed under the BSD-style license found in the
   * LICENSE file in the root directory of this source tree. An additional grant
   * of patent rights can be found in the PATENTS file in the same directory.
   */
  
  
  
  var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
  
  module.exports = ReactPropTypesSecret;
  
  
  /***/ }),
  /* 163 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.findIndex` and `_.findLastIndex` without
   * support for iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {Function} predicate The function invoked per iteration.
   * @param {number} fromIndex The index to search from.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseFindIndex(array, predicate, fromIndex, fromRight) {
    var length = array.length,
        index = fromIndex + (fromRight ? 1 : -1);
  
    while ((fromRight ? index-- : ++index < length)) {
      if (predicate(array[index], index, array)) {
        return index;
      }
    }
    return -1;
  }
  
  module.exports = baseFindIndex;
  
  
  /***/ }),
  /* 164 */
  /***/ (function(module, exports) {
  
  /**
   * This function is like `arrayIncludes` except that it accepts a comparator.
   *
   * @private
   * @param {Array} [array] The array to inspect.
   * @param {*} target The value to search for.
   * @param {Function} comparator The comparator invoked per element.
   * @returns {boolean} Returns `true` if `target` is found, else `false`.
   */
  function arrayIncludesWith(array, value, comparator) {
    var index = -1,
        length = array == null ? 0 : array.length;
  
    while (++index < length) {
      if (comparator(value, array[index])) {
        return true;
      }
    }
    return false;
  }
  
  module.exports = arrayIncludesWith;
  
  
  /***/ }),
  /* 165 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayPush = __webpack_require__(61),
      isFlattenable = __webpack_require__(226);
  
  /**
   * The base implementation of `_.flatten` with support for restricting flattening.
   *
   * @private
   * @param {Array} array The array to flatten.
   * @param {number} depth The maximum recursion depth.
   * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
   * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
   * @param {Array} [result=[]] The initial result value.
   * @returns {Array} Returns the new flattened array.
   */
  function baseFlatten(array, depth, predicate, isStrict, result) {
    var index = -1,
        length = array.length;
  
    predicate || (predicate = isFlattenable);
    result || (result = []);
  
    while (++index < length) {
      var value = array[index];
      if (depth > 0 && predicate(value)) {
        if (depth > 1) {
          // Recursively flatten arrays (susceptible to call stack limits).
          baseFlatten(value, depth - 1, predicate, isStrict, result);
        } else {
          arrayPush(result, value);
        }
      } else if (!isStrict) {
        result[result.length] = value;
      }
    }
    return result;
  }
  
  module.exports = baseFlatten;
  
  
  /***/ }),
  /* 166 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var apply = __webpack_require__(68);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * A specialized version of `baseRest` which transforms the rest array.
   *
   * @private
   * @param {Function} func The function to apply a rest parameter to.
   * @param {number} [start=func.length-1] The start position of the rest parameter.
   * @param {Function} transform The rest array transform.
   * @returns {Function} Returns the new function.
   */
  function overRest(func, start, transform) {
    start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
    return function() {
      var args = arguments,
          index = -1,
          length = nativeMax(args.length - start, 0),
          array = Array(length);
  
      while (++index < length) {
        array[index] = args[start + index];
      }
      index = -1;
      var otherArgs = Array(start + 1);
      while (++index < start) {
        otherArgs[index] = args[index];
      }
      otherArgs[start] = transform(array);
      return apply(func, this, otherArgs);
    };
  }
  
  module.exports = overRest;
  
  
  /***/ }),
  /* 167 */
  /***/ (function(module, exports) {
  
  /**
   * Creates a function that returns `value`.
   *
   * @static
   * @memberOf _
   * @since 2.4.0
   * @category Util
   * @param {*} value The value to return from the new function.
   * @returns {Function} Returns the new constant function.
   * @example
   *
   * var objects = _.times(2, _.constant({ 'a': 1 }));
   *
   * console.log(objects);
   * // => [{ 'a': 1 }, { 'a': 1 }]
   *
   * console.log(objects[0] === objects[1]);
   * // => true
   */
  function constant(value) {
    return function() {
      return value;
    };
  }
  
  module.exports = constant;
  
  
  /***/ }),
  /* 168 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getNative = __webpack_require__(10);
  
  var defineProperty = (function() {
    try {
      var func = getNative(Object, 'defineProperty');
      func({}, '', {});
      return func;
    } catch (e) {}
  }());
  
  module.exports = defineProperty;
  
  
  /***/ }),
  /* 169 */
  /***/ (function(module, exports) {
  
  /** Used to detect hot functions by number of calls within a span of milliseconds. */
  var HOT_COUNT = 800,
      HOT_SPAN = 16;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeNow = Date.now;
  
  /**
   * Creates a function that'll short out and invoke `identity` instead
   * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
   * milliseconds.
   *
   * @private
   * @param {Function} func The function to restrict.
   * @returns {Function} Returns the new shortable function.
   */
  function shortOut(func) {
    var count = 0,
        lastCalled = 0;
  
    return function() {
      var stamp = nativeNow(),
          remaining = HOT_SPAN - (stamp - lastCalled);
  
      lastCalled = stamp;
      if (remaining > 0) {
        if (++count >= HOT_COUNT) {
          return arguments[0];
        }
      } else {
        count = 0;
      }
      return func.apply(undefined, arguments);
    };
  }
  
  module.exports = shortOut;
  
  
  /***/ }),
  /* 170 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(module) {var root = __webpack_require__(3);
  
  /** Detect free variable `exports`. */
  var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
  
  /** Detect free variable `module`. */
  var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
  
  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;
  
  /** Built-in value references. */
  var Buffer = moduleExports ? root.Buffer : undefined,
      allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined;
  
  /**
   * Creates a clone of  `buffer`.
   *
   * @private
   * @param {Buffer} buffer The buffer to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Buffer} Returns the cloned buffer.
   */
  function cloneBuffer(buffer, isDeep) {
    if (isDeep) {
      return buffer.slice();
    }
    var length = buffer.length,
        result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
  
    buffer.copy(result);
    return result;
  }
  
  module.exports = cloneBuffer;
  
  /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(55)(module)))
  
  /***/ }),
  /* 171 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayPush = __webpack_require__(61),
      getPrototype = __webpack_require__(67),
      getSymbols = __webpack_require__(62),
      stubArray = __webpack_require__(88);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeGetSymbols = Object.getOwnPropertySymbols;
  
  /**
   * Creates an array of the own and inherited enumerable symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of symbols.
   */
  var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
    var result = [];
    while (object) {
      arrayPush(result, getSymbols(object));
      object = getPrototype(object);
    }
    return result;
  };
  
  module.exports = getSymbolsIn;
  
  
  /***/ }),
  /* 172 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var cloneArrayBuffer = __webpack_require__(98);
  
  /**
   * Creates a clone of `typedArray`.
   *
   * @private
   * @param {Object} typedArray The typed array to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned typed array.
   */
  function cloneTypedArray(typedArray, isDeep) {
    var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
    return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
  }
  
  module.exports = cloneTypedArray;
  
  
  /***/ }),
  /* 173 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseCreate = __webpack_require__(70),
      getPrototype = __webpack_require__(67),
      isPrototype = __webpack_require__(37);
  
  /**
   * Initializes an object clone.
   *
   * @private
   * @param {Object} object The object to clone.
   * @returns {Object} Returns the initialized clone.
   */
  function initCloneObject(object) {
    return (typeof object.constructor == 'function' && !isPrototype(object))
      ? baseCreate(getPrototype(object))
      : {};
  }
  
  module.exports = initCloneObject;
  
  
  /***/ }),
  /* 174 */
  /***/ (function(module, exports) {
  
  /**
   * Gets the last element of `array`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {Array} array The array to query.
   * @returns {*} Returns the last element of `array`.
   * @example
   *
   * _.last([1, 2, 3]);
   * // => 3
   */
  function last(array) {
    var length = array == null ? 0 : array.length;
    return length ? array[length - 1] : undefined;
  }
  
  module.exports = last;
  
  
  /***/ }),
  /* 175 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.slice` without an iteratee call guard.
   *
   * @private
   * @param {Array} array The array to slice.
   * @param {number} [start=0] The start position.
   * @param {number} [end=array.length] The end position.
   * @returns {Array} Returns the slice of `array`.
   */
  function baseSlice(array, start, end) {
    var index = -1,
        length = array.length;
  
    if (start < 0) {
      start = -start > length ? 0 : (length + start);
    }
    end = end > length ? length : end;
    if (end < 0) {
      end += length;
    }
    length = start > end ? 0 : ((end - start) >>> 0);
    start >>>= 0;
  
    var result = Array(length);
    while (++index < length) {
      result[index] = array[index + start];
    }
    return result;
  }
  
  module.exports = baseSlice;
  
  
  /***/ }),
  /* 176 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var flatten = __webpack_require__(177),
      overRest = __webpack_require__(166),
      setToString = __webpack_require__(93);
  
  /**
   * A specialized version of `baseRest` which flattens the rest array.
   *
   * @private
   * @param {Function} func The function to apply a rest parameter to.
   * @returns {Function} Returns the new function.
   */
  function flatRest(func) {
    return setToString(overRest(func, undefined, flatten), func + '');
  }
  
  module.exports = flatRest;
  
  
  /***/ }),
  /* 177 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseFlatten = __webpack_require__(165);
  
  /**
   * Flattens `array` a single level deep.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {Array} array The array to flatten.
   * @returns {Array} Returns the new flattened array.
   * @example
   *
   * _.flatten([1, [2, [3, [4]], 5]]);
   * // => [1, 2, [3, [4]], 5]
   */
  function flatten(array) {
    var length = array == null ? 0 : array.length;
    return length ? baseFlatten(array, 1) : [];
  }
  
  module.exports = flatten;
  
  
  /***/ }),
  /* 178 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var createBaseFor = __webpack_require__(253);
  
  /**
   * The base implementation of `baseForOwn` which iterates over `object`
   * properties returned by `keysFunc` and invokes `iteratee` for each property.
   * Iteratee functions may exit iteration early by explicitly returning `false`.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @returns {Object} Returns `object`.
   */
  var baseFor = createBaseFor();
  
  module.exports = baseFor;
  
  
  /***/ }),
  /* 179 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var identity = __webpack_require__(26);
  
  /**
   * Casts `value` to `identity` if it's not a function.
   *
   * @private
   * @param {*} value The value to inspect.
   * @returns {Function} Returns cast function.
   */
  function castFunction(value) {
    return typeof value == 'function' ? value : identity;
  }
  
  module.exports = castFunction;
  
  
  /***/ }),
  /* 180 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(6);
  
  /**
   * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` if suitable for strict
   *  equality comparisons, else `false`.
   */
  function isStrictComparable(value) {
    return value === value && !isObject(value);
  }
  
  module.exports = isStrictComparable;
  
  
  /***/ }),
  /* 181 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `matchesProperty` for source values suitable
   * for strict equality comparisons, i.e. `===`.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @param {*} srcValue The value to match.
   * @returns {Function} Returns the new spec function.
   */
  function matchesStrictComparable(key, srcValue) {
    return function(object) {
      if (object == null) {
        return false;
      }
      return object[key] === srcValue &&
        (srcValue !== undefined || (key in Object(object)));
    };
  }
  
  module.exports = matchesStrictComparable;
  
  
  /***/ }),
  /* 182 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseHasIn = __webpack_require__(260),
      hasPath = __webpack_require__(91);
  
  /**
   * Checks if `path` is a direct or inherited property of `object`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Object
   * @param {Object} object The object to query.
   * @param {Array|string} path The path to check.
   * @returns {boolean} Returns `true` if `path` exists, else `false`.
   * @example
   *
   * var object = _.create({ 'a': _.create({ 'b': 2 }) });
   *
   * _.hasIn(object, 'a');
   * // => true
   *
   * _.hasIn(object, 'a.b');
   * // => true
   *
   * _.hasIn(object, ['a', 'b']);
   * // => true
   *
   * _.hasIn(object, 'b');
   * // => false
   */
  function hasIn(object, path) {
    return object != null && hasPath(object, path, baseHasIn);
  }
  
  module.exports = hasIn;
  
  
  /***/ }),
  /* 183 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseEach = __webpack_require__(73),
      isArrayLike = __webpack_require__(11);
  
  /**
   * The base implementation of `_.map` without support for iteratee shorthands.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the new mapped array.
   */
  function baseMap(collection, iteratee) {
    var index = -1,
        result = isArrayLike(collection) ? Array(collection.length) : [];
  
    baseEach(collection, function(value, key, collection) {
      result[++index] = iteratee(value, key, collection);
    });
    return result;
  }
  
  module.exports = baseMap;
  
  
  /***/ }),
  /* 184 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGetTag = __webpack_require__(8),
      isObjectLike = __webpack_require__(7);
  
  /** `Object#toString` result references. */
  var numberTag = '[object Number]';
  
  /**
   * Checks if `value` is classified as a `Number` primitive or object.
   *
   * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
   * classified as numbers, use the `_.isFinite` method.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a number, else `false`.
   * @example
   *
   * _.isNumber(3);
   * // => true
   *
   * _.isNumber(Number.MIN_VALUE);
   * // => true
   *
   * _.isNumber(Infinity);
   * // => true
   *
   * _.isNumber('3');
   * // => false
   */
  function isNumber(value) {
    return typeof value == 'number' ||
      (isObjectLike(value) && baseGetTag(value) == numberTag);
  }
  
  module.exports = isNumber;
  
  
  /***/ }),
  /* 185 */
  /***/ (function(module, exports) {
  
  /**
   * Checks if `value` is `undefined`.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
   * @example
   *
   * _.isUndefined(void 0);
   * // => true
   *
   * _.isUndefined(null);
   * // => false
   */
  function isUndefined(value) {
    return value === undefined;
  }
  
  module.exports = isUndefined;
  
  
  /***/ }),
  /* 186 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseFindIndex = __webpack_require__(163),
      baseIteratee = __webpack_require__(13),
      toInteger = __webpack_require__(50);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * This method is like `_.find` except that it returns the index of the first
   * element `predicate` returns truthy for instead of the element itself.
   *
   * @static
   * @memberOf _
   * @since 1.1.0
   * @category Array
   * @param {Array} array The array to inspect.
   * @param {Function} [predicate=_.identity] The function invoked per iteration.
   * @param {number} [fromIndex=0] The index to search from.
   * @returns {number} Returns the index of the found element, else `-1`.
   * @example
   *
   * var users = [
   *   { 'user': 'barney',  'active': false },
   *   { 'user': 'fred',    'active': false },
   *   { 'user': 'pebbles', 'active': true }
   * ];
   *
   * _.findIndex(users, function(o) { return o.user == 'barney'; });
   * // => 0
   *
   * // The `_.matches` iteratee shorthand.
   * _.findIndex(users, { 'user': 'fred', 'active': false });
   * // => 1
   *
   * // The `_.matchesProperty` iteratee shorthand.
   * _.findIndex(users, ['active', false]);
   * // => 0
   *
   * // The `_.property` iteratee shorthand.
   * _.findIndex(users, 'active');
   * // => 2
   */
  function findIndex(array, predicate, fromIndex) {
    var length = array == null ? 0 : array.length;
    if (!length) {
      return -1;
    }
    var index = fromIndex == null ? 0 : toInteger(fromIndex);
    if (index < 0) {
      index = nativeMax(length + index, 0);
    }
    return baseFindIndex(array, baseIteratee(predicate, 3), index);
  }
  
  module.exports = findIndex;
  
  
  /***/ }),
  /* 187 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseToString = __webpack_require__(65),
      castSlice = __webpack_require__(267),
      charsEndIndex = __webpack_require__(268),
      charsStartIndex = __webpack_require__(269),
      stringToArray = __webpack_require__(270),
      toString = __webpack_require__(64);
  
  /** Used to match leading and trailing whitespace. */
  var reTrim = /^\s+|\s+$/g;
  
  /**
   * Removes leading and trailing whitespace or specified characters from `string`.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category String
   * @param {string} [string=''] The string to trim.
   * @param {string} [chars=whitespace] The characters to trim.
   * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
   * @returns {string} Returns the trimmed string.
   * @example
   *
   * _.trim('  abc  ');
   * // => 'abc'
   *
   * _.trim('-_-abc-_-', '_-');
   * // => 'abc'
   *
   * _.map(['  foo  ', '  bar  '], _.trim);
   * // => ['foo', 'bar']
   */
  function trim(string, chars, guard) {
    string = toString(string);
    if (string && (guard || chars === undefined)) {
      return string.replace(reTrim, '');
    }
    if (!string || !(chars = baseToString(chars))) {
      return string;
    }
    var strSymbols = stringToArray(string),
        chrSymbols = stringToArray(chars),
        start = charsStartIndex(strSymbols, chrSymbols),
        end = charsEndIndex(strSymbols, chrSymbols) + 1;
  
    return castSlice(strSymbols, start, end).join('');
  }
  
  module.exports = trim;
  
  
  /***/ }),
  /* 188 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseRest = __webpack_require__(25),
      isIterateeCall = __webpack_require__(215);
  
  /**
   * Creates a function like `_.assign`.
   *
   * @private
   * @param {Function} assigner The function to assign values.
   * @returns {Function} Returns the new assigner function.
   */
  function createAssigner(assigner) {
    return baseRest(function(object, sources) {
      var index = -1,
          length = sources.length,
          customizer = length > 1 ? sources[length - 1] : undefined,
          guard = length > 2 ? sources[2] : undefined;
  
      customizer = (assigner.length > 3 && typeof customizer == 'function')
        ? (length--, customizer)
        : undefined;
  
      if (guard && isIterateeCall(sources[0], sources[1], guard)) {
        customizer = length < 3 ? undefined : customizer;
        length = 1;
      }
      object = Object(object);
      while (++index < length) {
        var source = sources[index];
        if (source) {
          assigner(object, source, index, customizer);
        }
      }
      return object;
    });
  }
  
  module.exports = createAssigner;
  
  
  /***/ }),
  /* 189 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseAssignValue = __webpack_require__(46),
      eq = __webpack_require__(18);
  
  /**
   * This function is like `assignValue` except that it doesn't assign
   * `undefined` values.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {string} key The key of the property to assign.
   * @param {*} value The value to assign.
   */
  function assignMergeValue(object, key, value) {
    if ((value !== undefined && !eq(object[key], value)) ||
        (value === undefined && !(key in object))) {
      baseAssignValue(object, key, value);
    }
  }
  
  module.exports = assignMergeValue;
  
  
  /***/ }),
  /* 190 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var forEach = __webpack_require__(35);
  var compact = __webpack_require__(282);
  var indexOf = __webpack_require__(74);
  var findIndex = __webpack_require__(186);
  var get = __webpack_require__(72);
  
  var sumBy = __webpack_require__(283);
  var find = __webpack_require__(52);
  var includes = __webpack_require__(285);
  var map = __webpack_require__(17);
  var orderBy = __webpack_require__(104);
  
  var defaults = __webpack_require__(102);
  var merge = __webpack_require__(103);
  
  var isArray = __webpack_require__(0);
  var isFunction = __webpack_require__(19);
  
  var partial = __webpack_require__(292);
  var partialRight = __webpack_require__(308);
  
  var formatSort = __webpack_require__(201);
  
  var generateHierarchicalTree = __webpack_require__(311);
  
  /**
   * @typedef SearchResults.Facet
   * @type {object}
   * @property {string} name name of the attribute in the record
   * @property {object} data the faceting data: value, number of entries
   * @property {object} stats undefined unless facet_stats is retrieved from algolia
   */
  
  /**
   * @typedef SearchResults.HierarchicalFacet
   * @type {object}
   * @property {string} name name of the current value given the hierarchical level, trimmed.
   * If root node, you get the facet name
   * @property {number} count number of objects matching this hierarchical value
   * @property {string} path the current hierarchical value full path
   * @property {boolean} isRefined `true` if the current value was refined, `false` otherwise
   * @property {HierarchicalFacet[]} data sub values for the current level
   */
  
  /**
   * @typedef SearchResults.FacetValue
   * @type {object}
   * @property {string} value the facet value itself
   * @property {number} count times this facet appears in the results
   * @property {boolean} isRefined is the facet currently selected
   * @property {boolean} isExcluded is the facet currently excluded (only for conjunctive facets)
   */
  
  /**
   * @typedef Refinement
   * @type {object}
   * @property {string} type the type of filter used:
   * `numeric`, `facet`, `exclude`, `disjunctive`, `hierarchical`
   * @property {string} attributeName name of the attribute used for filtering
   * @property {string} name the value of the filter
   * @property {number} numericValue the value as a number. Only for numeric filters.
   * @property {string} operator the operator used. Only for numeric filters.
   * @property {number} count the number of computed hits for this filter. Only on facets.
   * @property {boolean} exhaustive if the count is exhaustive
   */
  
  function getIndices(obj) {
    var indices = {};
  
    forEach(obj, function(val, idx) { indices[val] = idx; });
  
    return indices;
  }
  
  function assignFacetStats(dest, facetStats, key) {
    if (facetStats && facetStats[key]) {
      dest.stats = facetStats[key];
    }
  }
  
  function findMatchingHierarchicalFacetFromAttributeName(hierarchicalFacets, hierarchicalAttributeName) {
    return find(
      hierarchicalFacets,
      function facetKeyMatchesAttribute(hierarchicalFacet) {
        return includes(hierarchicalFacet.attributes, hierarchicalAttributeName);
      }
    );
  }
  
  /*eslint-disable */
  /**
   * Constructor for SearchResults
   * @class
   * @classdesc SearchResults contains the results of a query to Algolia using the
   * {@link AlgoliaSearchHelper}.
   * @param {SearchParameters} state state that led to the response
   * @param {array.<object>} results the results from algolia client
   * @example <caption>SearchResults of the first query in
   * <a href="http://demos.algolia.com/instant-search-demo">the instant search demo</a></caption>
  {
     "hitsPerPage": 10,
     "processingTimeMS": 2,
     "facets": [
        {
           "name": "type",
           "data": {
              "HardGood": 6627,
              "BlackTie": 550,
              "Music": 665,
              "Software": 131,
              "Game": 456,
              "Movie": 1571
           },
           "exhaustive": false
        },
        {
           "exhaustive": false,
           "data": {
              "Free shipping": 5507
           },
           "name": "shipping"
        }
    ],
     "hits": [
        {
           "thumbnailImage": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_54x108_s.gif",
           "_highlightResult": {
              "shortDescription": {
                 "matchLevel": "none",
                 "value": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
                 "matchedWords": []
              },
              "category": {
                 "matchLevel": "none",
                 "value": "Computer Security Software",
                 "matchedWords": []
              },
              "manufacturer": {
                 "matchedWords": [],
                 "value": "Webroot",
                 "matchLevel": "none"
              },
              "name": {
                 "value": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
                 "matchedWords": [],
                 "matchLevel": "none"
              }
           },
           "image": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_105x210_sc.jpg",
           "shipping": "Free shipping",
           "bestSellingRank": 4,
           "shortDescription": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
           "url": "http://www.bestbuy.com/site/webroot-secureanywhere-internet-security-3-devi…d=1219060687969&skuId=1688832&cmp=RMX&ky=2d3GfEmNIzjA0vkzveHdZEBgpPCyMnLTJ",
           "name": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
           "category": "Computer Security Software",
           "salePrice_range": "1 - 50",
           "objectID": "1688832",
           "type": "Software",
           "customerReviewCount": 5980,
           "salePrice": 49.99,
           "manufacturer": "Webroot"
        },
        ....
    ],
     "nbHits": 10000,
     "disjunctiveFacets": [
        {
           "exhaustive": false,
           "data": {
              "5": 183,
              "12": 112,
              "7": 149,
              ...
           },
           "name": "customerReviewCount",
           "stats": {
              "max": 7461,
              "avg": 157.939,
              "min": 1
           }
        },
        {
           "data": {
              "Printer Ink": 142,
              "Wireless Speakers": 60,
              "Point & Shoot Cameras": 48,
              ...
           },
           "name": "category",
           "exhaustive": false
        },
        {
           "exhaustive": false,
           "data": {
              "> 5000": 2,
              "1 - 50": 6524,
              "501 - 2000": 566,
              "201 - 500": 1501,
              "101 - 200": 1360,
              "2001 - 5000": 47
           },
           "name": "salePrice_range"
        },
        {
           "data": {
              "Dynex™": 202,
              "Insignia™": 230,
              "PNY": 72,
              ...
           },
           "name": "manufacturer",
           "exhaustive": false
        }
    ],
     "query": "",
     "nbPages": 100,
     "page": 0,
     "index": "bestbuy"
  }
   **/
  /*eslint-enable */
  function SearchResults(state, results) {
    var mainSubResponse = results[0];
  
    this._rawResults = results;
  
    /**
     * query used to generate the results
     * @member {string}
     */
    this.query = mainSubResponse.query;
    /**
     * The query as parsed by the engine given all the rules.
     * @member {string}
     */
    this.parsedQuery = mainSubResponse.parsedQuery;
    /**
     * all the records that match the search parameters. Each record is
     * augmented with a new attribute `_highlightResult`
     * which is an object keyed by attribute and with the following properties:
     *  - `value` : the value of the facet highlighted (html)
     *  - `matchLevel`: full, partial or none depending on how the query terms match
     * @member {object[]}
     */
    this.hits = mainSubResponse.hits;
    /**
     * index where the results come from
     * @member {string}
     */
    this.index = mainSubResponse.index;
    /**
     * number of hits per page requested
     * @member {number}
     */
    this.hitsPerPage = mainSubResponse.hitsPerPage;
    /**
     * total number of hits of this query on the index
     * @member {number}
     */
    this.nbHits = mainSubResponse.nbHits;
    /**
     * total number of pages with respect to the number of hits per page and the total number of hits
     * @member {number}
     */
    this.nbPages = mainSubResponse.nbPages;
    /**
     * current page
     * @member {number}
     */
    this.page = mainSubResponse.page;
    /**
     * sum of the processing time of all the queries
     * @member {number}
     */
    this.processingTimeMS = sumBy(results, 'processingTimeMS');
    /**
     * The position if the position was guessed by IP.
     * @member {string}
     * @example "48.8637,2.3615",
     */
    this.aroundLatLng = mainSubResponse.aroundLatLng;
    /**
     * The radius computed by Algolia.
     * @member {string}
     * @example "126792922",
     */
    this.automaticRadius = mainSubResponse.automaticRadius;
    /**
     * String identifying the server used to serve this request.
     * @member {string}
     * @example "c7-use-2.algolia.net",
     */
    this.serverUsed = mainSubResponse.serverUsed;
    /**
     * Boolean that indicates if the computation of the counts did time out.
     * @member {boolean}
     */
    this.timeoutCounts = mainSubResponse.timeoutCounts;
    /**
     * Boolean that indicates if the computation of the hits did time out.
     * @member {boolean}
     */
    this.timeoutHits = mainSubResponse.timeoutHits;
  
    /**
     * disjunctive facets results
     * @member {SearchResults.Facet[]}
     */
    this.disjunctiveFacets = [];
    /**
     * disjunctive facets results
     * @member {SearchResults.HierarchicalFacet[]}
     */
    this.hierarchicalFacets = map(state.hierarchicalFacets, function initFutureTree() {
      return [];
    });
    /**
     * other facets results
     * @member {SearchResults.Facet[]}
     */
    this.facets = [];
  
    var disjunctiveFacets = state.getRefinedDisjunctiveFacets();
  
    var facetsIndices = getIndices(state.facets);
    var disjunctiveFacetsIndices = getIndices(state.disjunctiveFacets);
    var nextDisjunctiveResult = 1;
  
    var self = this;
    // Since we send request only for disjunctive facets that have been refined,
    // we get the facets informations from the first, general, response.
    forEach(mainSubResponse.facets, function(facetValueObject, facetKey) {
      var hierarchicalFacet = findMatchingHierarchicalFacetFromAttributeName(
        state.hierarchicalFacets,
        facetKey
      );
  
      if (hierarchicalFacet) {
        // Place the hierarchicalFacet data at the correct index depending on
        // the attributes order that was defined at the helper initialization
        var facetIndex = hierarchicalFacet.attributes.indexOf(facetKey);
        var idxAttributeName = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name});
        self.hierarchicalFacets[idxAttributeName][facetIndex] = {
          attribute: facetKey,
          data: facetValueObject,
          exhaustive: mainSubResponse.exhaustiveFacetsCount
        };
      } else {
        var isFacetDisjunctive = indexOf(state.disjunctiveFacets, facetKey) !== -1;
        var isFacetConjunctive = indexOf(state.facets, facetKey) !== -1;
        var position;
  
        if (isFacetDisjunctive) {
          position = disjunctiveFacetsIndices[facetKey];
          self.disjunctiveFacets[position] = {
            name: facetKey,
            data: facetValueObject,
            exhaustive: mainSubResponse.exhaustiveFacetsCount
          };
          assignFacetStats(self.disjunctiveFacets[position], mainSubResponse.facets_stats, facetKey);
        }
        if (isFacetConjunctive) {
          position = facetsIndices[facetKey];
          self.facets[position] = {
            name: facetKey,
            data: facetValueObject,
            exhaustive: mainSubResponse.exhaustiveFacetsCount
          };
          assignFacetStats(self.facets[position], mainSubResponse.facets_stats, facetKey);
        }
      }
    });
  
    // Make sure we do not keep holes within the hierarchical facets
    this.hierarchicalFacets = compact(this.hierarchicalFacets);
  
    // aggregate the refined disjunctive facets
    forEach(disjunctiveFacets, function(disjunctiveFacet) {
      var result = results[nextDisjunctiveResult];
      var hierarchicalFacet = state.getHierarchicalFacetByName(disjunctiveFacet);
  
      // There should be only item in facets.
      forEach(result.facets, function(facetResults, dfacet) {
        var position;
  
        if (hierarchicalFacet) {
          position = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name});
          var attributeIndex = findIndex(self.hierarchicalFacets[position], {attribute: dfacet});
  
          // previous refinements and no results so not able to find it
          if (attributeIndex === -1) {
            return;
          }
  
          self.hierarchicalFacets[position][attributeIndex].data = merge(
            {},
            self.hierarchicalFacets[position][attributeIndex].data,
            facetResults
          );
        } else {
          position = disjunctiveFacetsIndices[dfacet];
  
          var dataFromMainRequest = mainSubResponse.facets && mainSubResponse.facets[dfacet] || {};
  
          self.disjunctiveFacets[position] = {
            name: dfacet,
            data: defaults({}, facetResults, dataFromMainRequest),
            exhaustive: result.exhaustiveFacetsCount
          };
          assignFacetStats(self.disjunctiveFacets[position], result.facets_stats, dfacet);
  
          if (state.disjunctiveFacetsRefinements[dfacet]) {
            forEach(state.disjunctiveFacetsRefinements[dfacet], function(refinementValue) {
              // add the disjunctive refinements if it is no more retrieved
              if (!self.disjunctiveFacets[position].data[refinementValue] &&
                indexOf(state.disjunctiveFacetsRefinements[dfacet], refinementValue) > -1) {
                self.disjunctiveFacets[position].data[refinementValue] = 0;
              }
            });
          }
        }
      });
      nextDisjunctiveResult++;
    });
  
    // if we have some root level values for hierarchical facets, merge them
    forEach(state.getRefinedHierarchicalFacets(), function(refinedFacet) {
      var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet);
      var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
  
      var currentRefinement = state.getHierarchicalRefinement(refinedFacet);
      // if we are already at a root refinement (or no refinement at all), there is no
      // root level values request
      if (currentRefinement.length === 0 || currentRefinement[0].split(separator).length < 2) {
        return;
      }
  
      var result = results[nextDisjunctiveResult];
  
      forEach(result.facets, function(facetResults, dfacet) {
        var position = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name});
        var attributeIndex = findIndex(self.hierarchicalFacets[position], {attribute: dfacet});
  
        // previous refinements and no results so not able to find it
        if (attributeIndex === -1) {
          return;
        }
  
        // when we always get root levels, if the hits refinement is `beers > IPA` (count: 5),
        // then the disjunctive values will be `beers` (count: 100),
        // but we do not want to display
        //   | beers (100)
        //     > IPA (5)
        // We want
        //   | beers (5)
        //     > IPA (5)
        var defaultData = {};
  
        if (currentRefinement.length > 0) {
          var root = currentRefinement[0].split(separator)[0];
          defaultData[root] = self.hierarchicalFacets[position][attributeIndex].data[root];
        }
  
        self.hierarchicalFacets[position][attributeIndex].data = defaults(
          defaultData,
          facetResults,
          self.hierarchicalFacets[position][attributeIndex].data
        );
      });
  
      nextDisjunctiveResult++;
    });
  
    // add the excludes
    forEach(state.facetsExcludes, function(excludes, facetName) {
      var position = facetsIndices[facetName];
  
      self.facets[position] = {
        name: facetName,
        data: mainSubResponse.facets[facetName],
        exhaustive: mainSubResponse.exhaustiveFacetsCount
      };
      forEach(excludes, function(facetValue) {
        self.facets[position] = self.facets[position] || {name: facetName};
        self.facets[position].data = self.facets[position].data || {};
        self.facets[position].data[facetValue] = 0;
      });
    });
  
    this.hierarchicalFacets = map(this.hierarchicalFacets, generateHierarchicalTree(state));
  
    this.facets = compact(this.facets);
    this.disjunctiveFacets = compact(this.disjunctiveFacets);
  
    this._state = state;
  }
  
  /**
   * Get a facet object with its name
   * @deprecated
   * @param {string} name name of the faceted attribute
   * @return {SearchResults.Facet} the facet object
   */
  SearchResults.prototype.getFacetByName = function(name) {
    var predicate = {name: name};
  
    return find(this.facets, predicate) ||
      find(this.disjunctiveFacets, predicate) ||
      find(this.hierarchicalFacets, predicate);
  };
  
  /**
   * Get the facet values of a specified attribute from a SearchResults object.
   * @private
   * @param {SearchResults} results the search results to search in
   * @param {string} attribute name of the faceted attribute to search for
   * @return {array|object} facet values. For the hierarchical facets it is an object.
   */
  function extractNormalizedFacetValues(results, attribute) {
    var predicate = {name: attribute};
    if (results._state.isConjunctiveFacet(attribute)) {
      var facet = find(results.facets, predicate);
      if (!facet) return [];
  
      return map(facet.data, function(v, k) {
        return {
          name: k,
          count: v,
          isRefined: results._state.isFacetRefined(attribute, k),
          isExcluded: results._state.isExcludeRefined(attribute, k)
        };
      });
    } else if (results._state.isDisjunctiveFacet(attribute)) {
      var disjunctiveFacet = find(results.disjunctiveFacets, predicate);
      if (!disjunctiveFacet) return [];
  
      return map(disjunctiveFacet.data, function(v, k) {
        return {
          name: k,
          count: v,
          isRefined: results._state.isDisjunctiveFacetRefined(attribute, k)
        };
      });
    } else if (results._state.isHierarchicalFacet(attribute)) {
      return find(results.hierarchicalFacets, predicate);
    }
  }
  
  /**
   * Sort nodes of a hierarchical facet results
   * @private
   * @param {HierarchicalFacet} node node to upon which we want to apply the sort
   */
  function recSort(sortFn, node) {
    if (!node.data || node.data.length === 0) {
      return node;
    }
    var children = map(node.data, partial(recSort, sortFn));
    var sortedChildren = sortFn(children);
    var newNode = merge({}, node, {data: sortedChildren});
    return newNode;
  }
  
  SearchResults.DEFAULT_SORT = ['isRefined:desc', 'count:desc', 'name:asc'];
  
  function vanillaSortFn(order, data) {
    return data.sort(order);
  }
  
  /**
   * Get a the list of values for a given facet attribute. Those values are sorted
   * refinement first, descending count (bigger value on top), and name ascending
   * (alphabetical order). The sort formula can overridden using either string based
   * predicates or a function.
   *
   * This method will return all the values returned by the Algolia engine plus all
   * the values already refined. This means that it can happen that the
   * `maxValuesPerFacet` [configuration](https://www.algolia.com/doc/rest-api/search#param-maxValuesPerFacet)
   * might not be respected if you have facet values that are already refined.
   * @param {string} attribute attribute name
   * @param {object} opts configuration options.
   * @param {Array.<string> | function} opts.sortBy
   * When using strings, it consists of
   * the name of the [FacetValue](#SearchResults.FacetValue) or the
   * [HierarchicalFacet](#SearchResults.HierarchicalFacet) attributes with the
   * order (`asc` or `desc`). For example to order the value by count, the
   * argument would be `['count:asc']`.
   *
   * If only the attribute name is specified, the ordering defaults to the one
   * specified in the default value for this attribute.
   *
   * When not specified, the order is
   * ascending.  This parameter can also be a function which takes two facet
   * values and should return a number, 0 if equal, 1 if the first argument is
   * bigger or -1 otherwise.
   *
   * The default value for this attribute `['isRefined:desc', 'count:desc', 'name:asc']`
   * @return {FacetValue[]|HierarchicalFacet} depending on the type of facet of
   * the attribute requested (hierarchical, disjunctive or conjunctive)
   * @example
   * helper.on('results', function(content){
   *   //get values ordered only by name ascending using the string predicate
   *   content.getFacetValues('city', {sortBy: ['name:asc']);
   *   //get values  ordered only by count ascending using a function
   *   content.getFacetValues('city', {
   *     // this is equivalent to ['count:asc']
   *     sortBy: function(a, b) {
   *       if (a.count === b.count) return 0;
   *       if (a.count > b.count)   return 1;
   *       if (b.count > a.count)   return -1;
   *     }
   *   });
   * });
   */
  SearchResults.prototype.getFacetValues = function(attribute, opts) {
    var facetValues = extractNormalizedFacetValues(this, attribute);
    if (!facetValues) throw new Error(attribute + ' is not a retrieved facet.');
  
    var options = defaults({}, opts, {sortBy: SearchResults.DEFAULT_SORT});
  
    if (isArray(options.sortBy)) {
      var order = formatSort(options.sortBy, SearchResults.DEFAULT_SORT);
      if (isArray(facetValues)) {
        return orderBy(facetValues, order[0], order[1]);
      }
      // If facetValues is not an array, it's an object thus a hierarchical facet object
      return recSort(partialRight(orderBy, order[0], order[1]), facetValues);
    } else if (isFunction(options.sortBy)) {
      if (isArray(facetValues)) {
        return facetValues.sort(options.sortBy);
      }
      // If facetValues is not an array, it's an object thus a hierarchical facet object
      return recSort(partial(vanillaSortFn, options.sortBy), facetValues);
    }
    throw new Error(
      'options.sortBy is optional but if defined it must be ' +
      'either an array of string (predicates) or a sorting function'
    );
  };
  
  /**
   * Returns the facet stats if attribute is defined and the facet contains some.
   * Otherwise returns undefined.
   * @param {string} attribute name of the faceted attribute
   * @return {object} The stats of the facet
   */
  SearchResults.prototype.getFacetStats = function(attribute) {
    if (this._state.isConjunctiveFacet(attribute)) {
      return getFacetStatsIfAvailable(this.facets, attribute);
    } else if (this._state.isDisjunctiveFacet(attribute)) {
      return getFacetStatsIfAvailable(this.disjunctiveFacets, attribute);
    }
  
    throw new Error(attribute + ' is not present in `facets` or `disjunctiveFacets`');
  };
  
  function getFacetStatsIfAvailable(facetList, facetName) {
    var data = find(facetList, {name: facetName});
    return data && data.stats;
  }
  
  /**
   * Returns all refinements for all filters + tags. It also provides
   * additional information: count and exhausistivity for each filter.
   *
   * See the [refinement type](#Refinement) for an exhaustive view of the available
   * data.
   *
   * @return {Array.<Refinement>} all the refinements
   */
  SearchResults.prototype.getRefinements = function() {
    var state = this._state;
    var results = this;
    var res = [];
  
    forEach(state.facetsRefinements, function(refinements, attributeName) {
      forEach(refinements, function(name) {
        res.push(getRefinement(state, 'facet', attributeName, name, results.facets));
      });
    });
  
    forEach(state.facetsExcludes, function(refinements, attributeName) {
      forEach(refinements, function(name) {
        res.push(getRefinement(state, 'exclude', attributeName, name, results.facets));
      });
    });
  
    forEach(state.disjunctiveFacetsRefinements, function(refinements, attributeName) {
      forEach(refinements, function(name) {
        res.push(getRefinement(state, 'disjunctive', attributeName, name, results.disjunctiveFacets));
      });
    });
  
    forEach(state.hierarchicalFacetsRefinements, function(refinements, attributeName) {
      forEach(refinements, function(name) {
        res.push(getHierarchicalRefinement(state, attributeName, name, results.hierarchicalFacets));
      });
    });
  
    forEach(state.numericRefinements, function(operators, attributeName) {
      forEach(operators, function(values, operator) {
        forEach(values, function(value) {
          res.push({
            type: 'numeric',
            attributeName: attributeName,
            name: value,
            numericValue: value,
            operator: operator
          });
        });
      });
    });
  
    forEach(state.tagRefinements, function(name) {
      res.push({type: 'tag', attributeName: '_tags', name: name});
    });
  
    return res;
  };
  
  function getRefinement(state, type, attributeName, name, resultsFacets) {
    var facet = find(resultsFacets, {name: attributeName});
    var count = get(facet, 'data[' + name + ']');
    var exhaustive = get(facet, 'exhaustive');
    return {
      type: type,
      attributeName: attributeName,
      name: name,
      count: count || 0,
      exhaustive: exhaustive || false
    };
  }
  
  function getHierarchicalRefinement(state, attributeName, name, resultsFacets) {
    var facet = find(resultsFacets, {name: attributeName});
    var facetDeclaration = state.getHierarchicalFacetByName(attributeName);
    var splitted = name.split(facetDeclaration.separator);
    var configuredName = splitted[splitted.length - 1];
    for (var i = 0; facet !== undefined && i < splitted.length; ++i) {
      facet = find(facet.data, {name: splitted[i]});
    }
    var count = get(facet, 'count');
    var exhaustive = get(facet, 'exhaustive');
    return {
      type: 'hierarchical',
      attributeName: attributeName,
      name: configuredName,
      count: count || 0,
      exhaustive: exhaustive || false
    };
  }
  
  module.exports = SearchResults;
  
  
  /***/ }),
  /* 191 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var identity = __webpack_require__(26),
      metaMap = __webpack_require__(192);
  
  /**
   * The base implementation of `setData` without support for hot loop shorting.
   *
   * @private
   * @param {Function} func The function to associate metadata with.
   * @param {*} data The metadata.
   * @returns {Function} Returns `func`.
   */
  var baseSetData = !metaMap ? identity : function(func, data) {
    metaMap.set(func, data);
    return func;
  };
  
  module.exports = baseSetData;
  
  
  /***/ }),
  /* 192 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var WeakMap = __webpack_require__(90);
  
  /** Used to store function metadata. */
  var metaMap = WeakMap && new WeakMap;
  
  module.exports = metaMap;
  
  
  /***/ }),
  /* 193 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var composeArgs = __webpack_require__(194),
      composeArgsRight = __webpack_require__(195),
      countHolders = __webpack_require__(295),
      createCtor = __webpack_require__(75),
      createRecurry = __webpack_require__(196),
      getHolder = __webpack_require__(53),
      reorder = __webpack_require__(305),
      replaceHolders = __webpack_require__(36),
      root = __webpack_require__(3);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_FLAG = 8,
      WRAP_CURRY_RIGHT_FLAG = 16,
      WRAP_ARY_FLAG = 128,
      WRAP_FLIP_FLAG = 512;
  
  /**
   * Creates a function that wraps `func` to invoke it with optional `this`
   * binding of `thisArg`, partial application, and currying.
   *
   * @private
   * @param {Function|string} func The function or method name to wrap.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @param {*} [thisArg] The `this` binding of `func`.
   * @param {Array} [partials] The arguments to prepend to those provided to
   *  the new function.
   * @param {Array} [holders] The `partials` placeholder indexes.
   * @param {Array} [partialsRight] The arguments to append to those provided
   *  to the new function.
   * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
   * @param {Array} [argPos] The argument positions of the new function.
   * @param {number} [ary] The arity cap of `func`.
   * @param {number} [arity] The arity of `func`.
   * @returns {Function} Returns the new wrapped function.
   */
  function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
    var isAry = bitmask & WRAP_ARY_FLAG,
        isBind = bitmask & WRAP_BIND_FLAG,
        isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
        isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
        isFlip = bitmask & WRAP_FLIP_FLAG,
        Ctor = isBindKey ? undefined : createCtor(func);
  
    function wrapper() {
      var length = arguments.length,
          args = Array(length),
          index = length;
  
      while (index--) {
        args[index] = arguments[index];
      }
      if (isCurried) {
        var placeholder = getHolder(wrapper),
            holdersCount = countHolders(args, placeholder);
      }
      if (partials) {
        args = composeArgs(args, partials, holders, isCurried);
      }
      if (partialsRight) {
        args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
      }
      length -= holdersCount;
      if (isCurried && length < arity) {
        var newHolders = replaceHolders(args, placeholder);
        return createRecurry(
          func, bitmask, createHybrid, wrapper.placeholder, thisArg,
          args, newHolders, argPos, ary, arity - length
        );
      }
      var thisBinding = isBind ? thisArg : this,
          fn = isBindKey ? thisBinding[func] : func;
  
      length = args.length;
      if (argPos) {
        args = reorder(args, argPos);
      } else if (isFlip && length > 1) {
        args.reverse();
      }
      if (isAry && ary < length) {
        args.length = ary;
      }
      if (this && this !== root && this instanceof wrapper) {
        fn = Ctor || createCtor(fn);
      }
      return fn.apply(thisBinding, args);
    }
    return wrapper;
  }
  
  module.exports = createHybrid;
  
  
  /***/ }),
  /* 194 */
  /***/ (function(module, exports) {
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * Creates an array that is the composition of partially applied arguments,
   * placeholders, and provided arguments into a single array of arguments.
   *
   * @private
   * @param {Array} args The provided arguments.
   * @param {Array} partials The arguments to prepend to those provided.
   * @param {Array} holders The `partials` placeholder indexes.
   * @params {boolean} [isCurried] Specify composing for a curried function.
   * @returns {Array} Returns the new array of composed arguments.
   */
  function composeArgs(args, partials, holders, isCurried) {
    var argsIndex = -1,
        argsLength = args.length,
        holdersLength = holders.length,
        leftIndex = -1,
        leftLength = partials.length,
        rangeLength = nativeMax(argsLength - holdersLength, 0),
        result = Array(leftLength + rangeLength),
        isUncurried = !isCurried;
  
    while (++leftIndex < leftLength) {
      result[leftIndex] = partials[leftIndex];
    }
    while (++argsIndex < holdersLength) {
      if (isUncurried || argsIndex < argsLength) {
        result[holders[argsIndex]] = args[argsIndex];
      }
    }
    while (rangeLength--) {
      result[leftIndex++] = args[argsIndex++];
    }
    return result;
  }
  
  module.exports = composeArgs;
  
  
  /***/ }),
  /* 195 */
  /***/ (function(module, exports) {
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * This function is like `composeArgs` except that the arguments composition
   * is tailored for `_.partialRight`.
   *
   * @private
   * @param {Array} args The provided arguments.
   * @param {Array} partials The arguments to append to those provided.
   * @param {Array} holders The `partials` placeholder indexes.
   * @params {boolean} [isCurried] Specify composing for a curried function.
   * @returns {Array} Returns the new array of composed arguments.
   */
  function composeArgsRight(args, partials, holders, isCurried) {
    var argsIndex = -1,
        argsLength = args.length,
        holdersIndex = -1,
        holdersLength = holders.length,
        rightIndex = -1,
        rightLength = partials.length,
        rangeLength = nativeMax(argsLength - holdersLength, 0),
        result = Array(rangeLength + rightLength),
        isUncurried = !isCurried;
  
    while (++argsIndex < rangeLength) {
      result[argsIndex] = args[argsIndex];
    }
    var offset = argsIndex;
    while (++rightIndex < rightLength) {
      result[offset + rightIndex] = partials[rightIndex];
    }
    while (++holdersIndex < holdersLength) {
      if (isUncurried || argsIndex < argsLength) {
        result[offset + holders[holdersIndex]] = args[argsIndex++];
      }
    }
    return result;
  }
  
  module.exports = composeArgsRight;
  
  
  /***/ }),
  /* 196 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isLaziable = __webpack_require__(296),
      setData = __webpack_require__(199),
      setWrapToString = __webpack_require__(200);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_BOUND_FLAG = 4,
      WRAP_CURRY_FLAG = 8,
      WRAP_PARTIAL_FLAG = 32,
      WRAP_PARTIAL_RIGHT_FLAG = 64;
  
  /**
   * Creates a function that wraps `func` to continue currying.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @param {Function} wrapFunc The function to create the `func` wrapper.
   * @param {*} placeholder The placeholder value.
   * @param {*} [thisArg] The `this` binding of `func`.
   * @param {Array} [partials] The arguments to prepend to those provided to
   *  the new function.
   * @param {Array} [holders] The `partials` placeholder indexes.
   * @param {Array} [argPos] The argument positions of the new function.
   * @param {number} [ary] The arity cap of `func`.
   * @param {number} [arity] The arity of `func`.
   * @returns {Function} Returns the new wrapped function.
   */
  function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
    var isCurry = bitmask & WRAP_CURRY_FLAG,
        newHolders = isCurry ? holders : undefined,
        newHoldersRight = isCurry ? undefined : holders,
        newPartials = isCurry ? partials : undefined,
        newPartialsRight = isCurry ? undefined : partials;
  
    bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
    bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
  
    if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
      bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
    }
    var newData = [
      func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
      newHoldersRight, argPos, ary, arity
    ];
  
    var result = wrapFunc.apply(undefined, newData);
    if (isLaziable(func)) {
      setData(result, newData);
    }
    result.placeholder = placeholder;
    return setWrapToString(result, func, bitmask);
  }
  
  module.exports = createRecurry;
  
  
  /***/ }),
  /* 197 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var metaMap = __webpack_require__(192),
      noop = __webpack_require__(297);
  
  /**
   * Gets metadata for `func`.
   *
   * @private
   * @param {Function} func The function to query.
   * @returns {*} Returns the metadata for `func`.
   */
  var getData = !metaMap ? noop : function(func) {
    return metaMap.get(func);
  };
  
  module.exports = getData;
  
  
  /***/ }),
  /* 198 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseCreate = __webpack_require__(70),
      baseLodash = __webpack_require__(107);
  
  /**
   * The base constructor for creating `lodash` wrapper objects.
   *
   * @private
   * @param {*} value The value to wrap.
   * @param {boolean} [chainAll] Enable explicit method chain sequences.
   */
  function LodashWrapper(value, chainAll) {
    this.__wrapped__ = value;
    this.__actions__ = [];
    this.__chain__ = !!chainAll;
    this.__index__ = 0;
    this.__values__ = undefined;
  }
  
  LodashWrapper.prototype = baseCreate(baseLodash.prototype);
  LodashWrapper.prototype.constructor = LodashWrapper;
  
  module.exports = LodashWrapper;
  
  
  /***/ }),
  /* 199 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseSetData = __webpack_require__(191),
      shortOut = __webpack_require__(169);
  
  /**
   * Sets metadata for `func`.
   *
   * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
   * period of time, it will trip its breaker and transition to an identity
   * function to avoid garbage collection pauses in V8. See
   * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
   * for more details.
   *
   * @private
   * @param {Function} func The function to associate metadata with.
   * @param {*} data The metadata.
   * @returns {Function} Returns `func`.
   */
  var setData = shortOut(baseSetData);
  
  module.exports = setData;
  
  
  /***/ }),
  /* 200 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var getWrapDetails = __webpack_require__(302),
      insertWrapDetails = __webpack_require__(303),
      setToString = __webpack_require__(93),
      updateWrapDetails = __webpack_require__(304);
  
  /**
   * Sets the `toString` method of `wrapper` to mimic the source of `reference`
   * with wrapper details in a comment at the top of the source body.
   *
   * @private
   * @param {Function} wrapper The function to modify.
   * @param {Function} reference The reference function.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @returns {Function} Returns `wrapper`.
   */
  function setWrapToString(wrapper, reference, bitmask) {
    var source = (reference + '');
    return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
  }
  
  module.exports = setWrapToString;
  
  
  /***/ }),
  /* 201 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var reduce = __webpack_require__(49);
  var find = __webpack_require__(52);
  var startsWith = __webpack_require__(309);
  
  /**
   * Transform sort format from user friendly notation to lodash format
   * @param {string[]} sortBy array of predicate of the form "attribute:order"
   * @return {array.<string[]>} array containing 2 elements : attributes, orders
   */
  module.exports = function formatSort(sortBy, defaults) {
    return reduce(sortBy, function preparePredicate(out, sortInstruction) {
      var sortInstructions = sortInstruction.split(':');
      if (defaults && sortInstructions.length === 1) {
        var similarDefault = find(defaults, function(predicate) {
          return startsWith(predicate, sortInstruction[0]);
        });
        if (similarDefault) {
          sortInstructions = similarDefault.split(':');
        }
      }
      out[0].push(sortInstructions[0]);
      out[1].push(sortInstructions[1]);
      return out;
    }, [[], []]);
  };
  
  
  /***/ }),
  /* 202 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGet = __webpack_require__(71),
      baseSet = __webpack_require__(313),
      castPath = __webpack_require__(22);
  
  /**
   * The base implementation of  `_.pickBy` without support for iteratee shorthands.
   *
   * @private
   * @param {Object} object The source object.
   * @param {string[]} paths The property paths to pick.
   * @param {Function} predicate The function invoked per property.
   * @returns {Object} Returns the new object.
   */
  function basePickBy(object, paths, predicate) {
    var index = -1,
        length = paths.length,
        result = {};
  
    while (++index < length) {
      var path = paths[index],
          value = baseGet(object, path);
  
      if (predicate(value, path)) {
        baseSet(result, castPath(path, object), value);
      }
    }
    return result;
  }
  
  module.exports = basePickBy;
  
  
  /***/ }),
  /* 203 */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(global, process) {// Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = __webpack_require__(315);
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = __webpack_require__(316);
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(54), __webpack_require__(109)))
  
  /***/ }),
  /* 204 */
  /***/ (function(module, exports) {
  
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        } else {
          // At least give some kind of context to the user
          var err = new Error('Uncaught, unspecified "error" event. (' + er + ')');
          err.context = er;
          throw err;
        }
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          args = Array.prototype.slice.call(arguments, 1);
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      args = Array.prototype.slice.call(arguments, 1);
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else if (listeners) {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.prototype.listenerCount = function(type) {
    if (this._events) {
      var evlistener = this._events[type];
  
      if (isFunction(evlistener))
        return 1;
      else if (evlistener)
        return evlistener.length;
    }
    return 0;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    return emitter.listenerCount(type);
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  
  /***/ }),
  /* 205 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  /**
   * Module containing the functions to serialize and deserialize
   * {SearchParameters} in the query string format
   * @module algoliasearchHelper.url
   */
  
  var shortener = __webpack_require__(318);
  var SearchParameters = __webpack_require__(100);
  
  var qs = __webpack_require__(321);
  
  var bind = __webpack_require__(324);
  var forEach = __webpack_require__(35);
  var pick = __webpack_require__(110);
  var map = __webpack_require__(17);
  var mapKeys = __webpack_require__(326);
  var mapValues = __webpack_require__(327);
  var isString = __webpack_require__(51);
  var isPlainObject = __webpack_require__(43);
  var isArray = __webpack_require__(0);
  var invert = __webpack_require__(206);
  
  var encode = __webpack_require__(108).encode;
  
  function recursiveEncode(input) {
    if (isPlainObject(input)) {
      return mapValues(input, recursiveEncode);
    }
    if (isArray(input)) {
      return map(input, recursiveEncode);
    }
    if (isString(input)) {
      return encode(input);
    }
    return input;
  }
  
  var refinementsParameters = ['dFR', 'fR', 'nR', 'hFR', 'tR'];
  var stateKeys = shortener.ENCODED_PARAMETERS;
  function sortQueryStringValues(prefixRegexp, invertedMapping, a, b) {
    if (prefixRegexp !== null) {
      a = a.replace(prefixRegexp, '');
      b = b.replace(prefixRegexp, '');
    }
  
    a = invertedMapping[a] || a;
    b = invertedMapping[b] || b;
  
    if (stateKeys.indexOf(a) !== -1 || stateKeys.indexOf(b) !== -1) {
      if (a === 'q') return -1;
      if (b === 'q') return 1;
  
      var isARefinements = refinementsParameters.indexOf(a) !== -1;
      var isBRefinements = refinementsParameters.indexOf(b) !== -1;
      if (isARefinements && !isBRefinements) {
        return 1;
      } else if (isBRefinements && !isARefinements) {
        return -1;
      }
    }
  
    return a.localeCompare(b);
  }
  
  /**
   * Read a query string and return an object containing the state
   * @param {string} queryString the query string that will be decoded
   * @param {object} [options] accepted options :
   *   - prefix : the prefix used for the saved attributes, you have to provide the
   *     same that was used for serialization
   *   - mapping : map short attributes to another value e.g. {q: 'query'}
   * @return {object} partial search parameters object (same properties than in the
   * SearchParameters but not exhaustive)
   */
  exports.getStateFromQueryString = function(queryString, options) {
    var prefixForParameters = options && options.prefix || '';
    var mapping = options && options.mapping || {};
    var invertedMapping = invert(mapping);
  
    var partialStateWithPrefix = qs.parse(queryString);
    var prefixRegexp = new RegExp('^' + prefixForParameters);
    var partialState = mapKeys(
      partialStateWithPrefix,
      function(v, k) {
        var hasPrefix = prefixForParameters && prefixRegexp.test(k);
        var unprefixedKey = hasPrefix ? k.replace(prefixRegexp, '') : k;
        var decodedKey = shortener.decode(invertedMapping[unprefixedKey] || unprefixedKey);
        return decodedKey || unprefixedKey;
      }
    );
  
    var partialStateWithParsedNumbers = SearchParameters._parseNumbers(partialState);
  
    return pick(partialStateWithParsedNumbers, SearchParameters.PARAMETERS);
  };
  
  /**
   * Retrieve an object of all the properties that are not understandable as helper
   * parameters.
   * @param {string} queryString the query string to read
   * @param {object} [options] the options
   *   - prefixForParameters : prefix used for the helper configuration keys
   *   - mapping : map short attributes to another value e.g. {q: 'query'}
   * @return {object} the object containing the parsed configuration that doesn't
   * to the helper
   */
  exports.getUnrecognizedParametersInQueryString = function(queryString, options) {
    var prefixForParameters = options && options.prefix;
    var mapping = options && options.mapping || {};
    var invertedMapping = invert(mapping);
  
    var foreignConfig = {};
    var config = qs.parse(queryString);
    if (prefixForParameters) {
      var prefixRegexp = new RegExp('^' + prefixForParameters);
      forEach(config, function(v, key) {
        if (!prefixRegexp.test(key)) foreignConfig[key] = v;
      });
    } else {
      forEach(config, function(v, key) {
        if (!shortener.decode(invertedMapping[key] || key)) foreignConfig[key] = v;
      });
    }
  
    return foreignConfig;
  };
  
  /**
   * Generate a query string for the state passed according to the options
   * @param {SearchParameters} state state to serialize
   * @param {object} [options] May contain the following parameters :
   *  - prefix : prefix in front of the keys
   *  - mapping : map short attributes to another value e.g. {q: 'query'}
   *  - moreAttributes : more values to be added in the query string. Those values
   *    won't be prefixed.
   *  - safe : get safe urls for use in emails, chat apps or any application auto linking urls.
   *  All parameters and values will be encoded in a way that it's safe to share them.
   *  Default to false for legacy reasons ()
   * @return {string} the query string
   */
  exports.getQueryStringFromState = function(state, options) {
    var moreAttributes = options && options.moreAttributes;
    var prefixForParameters = options && options.prefix || '';
    var mapping = options && options.mapping || {};
    var safe = options && options.safe || false;
    var invertedMapping = invert(mapping);
  
    var stateForUrl = safe ? state : recursiveEncode(state);
  
    var encodedState = mapKeys(
      stateForUrl,
      function(v, k) {
        var shortK = shortener.encode(k);
        return prefixForParameters + (mapping[shortK] || shortK);
      }
    );
  
    var prefixRegexp = prefixForParameters === '' ? null : new RegExp('^' + prefixForParameters);
    var sort = bind(sortQueryStringValues, null, prefixRegexp, invertedMapping);
    if (moreAttributes) {
      var stateQs = qs.stringify(encodedState, {encode: safe, sort: sort});
      var moreQs = qs.stringify(moreAttributes, {encode: safe});
      if (!stateQs) return moreQs;
      return stateQs + '&' + moreQs;
    }
  
    return qs.stringify(encodedState, {encode: safe, sort: sort});
  };
  
  
  /***/ }),
  /* 206 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var constant = __webpack_require__(167),
      createInverter = __webpack_require__(319),
      identity = __webpack_require__(26);
  
  /**
   * Creates an object composed of the inverted keys and values of `object`.
   * If `object` contains duplicate values, subsequent values overwrite
   * property assignments of previous values.
   *
   * @static
   * @memberOf _
   * @since 0.7.0
   * @category Object
   * @param {Object} object The object to invert.
   * @returns {Object} Returns the new inverted object.
   * @example
   *
   * var object = { 'a': 1, 'b': 2, 'c': 1 };
   *
   * _.invert(object);
   * // => { '1': 'c', '2': 'b' }
   */
  var invert = createInverter(function(result, value, key) {
    result[value] = key;
  }, constant(identity));
  
  module.exports = invert;
  
  
  /***/ }),
  /* 207 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var replace = String.prototype.replace;
  var percentTwenties = /%20/g;
  
  module.exports = {
      'default': 'RFC3986',
      formatters: {
          RFC1738: function (value) {
              return replace.call(value, percentTwenties, '+');
          },
          RFC3986: function (value) {
              return value;
          }
      },
      RFC1738: 'RFC1738',
      RFC3986: 'RFC3986'
  };
  
  
  /***/ }),
  /* 208 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = '2.21.0';
  
  
  /***/ }),
  /* 209 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _indexUtils = __webpack_require__(5);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  /**
   * connectRange connector provides the logic to create connected
   * components that will give the ability for a user to refine results using
   * a numeric range.
   * @name connectRange
   * @kind connector
   * @requirements The attribute passed to the `attributeName` prop must be holding numerical values.
   * @propType {string} attributeName - Name of the attribute for faceting
   * @propType {{min: number, max: number}} [defaultRefinement] - Default searchState of the widget containing the start and the end of the range.
   * @propType {number} [min] - Minimum value. When this isn't set, the minimum value will be automatically computed by Algolia using the data in the index.
   * @propType {number} [max] - Maximum value. When this isn't set, the maximum value will be automatically computed by Algolia using the data in the index.
   * @providedPropType {function} refine - a function to select a range.
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the refinement currently applied
   */
  
  function getId(props) {
    return props.attributeName;
  }
  
  var namespace = 'range';
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), {}, function (currentRefinement) {
      var min = currentRefinement.min,
          max = currentRefinement.max;
  
      if (typeof min === 'string') {
        min = parseInt(min, 10);
      }
      if (typeof max === 'string') {
        max = parseInt(max, 10);
      }
      return { min: min, max: max };
    });
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    if (!isFinite(nextRefinement.min) || !isFinite(nextRefinement.max)) {
      throw new Error("You can't provide non finite values to the range connector");
    }
    var id = getId(props);
    var nextValue = _defineProperty({}, id, nextRefinement);
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaRange',
  
    propTypes: {
      id: _propTypes2.default.string,
      attributeName: _propTypes2.default.string.isRequired,
      defaultRefinement: _propTypes2.default.shape({
        min: _propTypes2.default.number.isRequired,
        max: _propTypes2.default.number.isRequired
      }),
      min: _propTypes2.default.number,
      max: _propTypes2.default.number
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var attributeName = props.attributeName;
      var min = props.min,
          max = props.max;
  
  
      var hasMin = typeof min !== 'undefined';
      var hasMax = typeof max !== 'undefined';
  
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      if (!hasMin || !hasMax) {
        if (!results) {
          return {
            canRefine: false
          };
        }
  
        var stats = results.getFacetByName(attributeName) ? results.getFacetStats(attributeName) : null;
        if (!stats) {
          return {
            canRefine: false
          };
        }
  
        if (!hasMin) {
          min = stats.min;
        }
        if (!hasMax) {
          max = stats.max;
        }
      }
  
      var count = results ? results.getFacetValues(attributeName).map(function (v) {
        return {
          value: v.name,
          count: v.count
        };
      }) : [];
  
      var _getCurrentRefinement = getCurrentRefinement(props, searchState, this.context),
          _getCurrentRefinement2 = _getCurrentRefinement.min,
          valueMin = _getCurrentRefinement2 === undefined ? min : _getCurrentRefinement2,
          _getCurrentRefinement3 = _getCurrentRefinement.max,
          valueMax = _getCurrentRefinement3 === undefined ? max : _getCurrentRefinement3;
  
      return {
        min: min,
        max: max,
        currentRefinement: { min: valueMin, max: valueMax },
        count: count,
        canRefine: count.length > 0
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(params, props, searchState) {
      var attributeName = props.attributeName;
  
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      params = params.addDisjunctiveFacet(attributeName);
  
      var min = currentRefinement.min,
          max = currentRefinement.max;
  
      if (typeof min !== 'undefined') {
        params = params.addNumericRefinement(attributeName, '>=', min);
      }
      if (typeof max !== 'undefined') {
        params = params.addNumericRefinement(attributeName, '<=', max);
      }
  
      return params;
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this = this;
  
      var id = getId(props);
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      var item = void 0;
      var hasMin = typeof currentRefinement.min !== 'undefined';
      var hasMax = typeof currentRefinement.max !== 'undefined';
      if (hasMin || hasMax) {
        var itemLabel = '';
        if (hasMin) {
          itemLabel += currentRefinement.min + ' <= ';
        }
        itemLabel += props.attributeName;
        if (hasMax) {
          itemLabel += ' <= ' + currentRefinement.max;
        }
        item = {
          label: itemLabel,
          currentRefinement: currentRefinement,
          attributeName: props.attributeName,
          value: function value(nextState) {
            return _cleanUp(props, nextState, _this.context);
          }
        };
      }
  
      return {
        id: id,
        index: (0, _indexUtils.getIndex)(this.context),
        items: item ? [item] : []
      };
    }
  });
  
  /***/ }),
  /* 210 */,
  /* 211 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * connectCurrentRefinements connector provides the logic to build a widget that will
   * give the user the ability to remove all or some of the filters that were
   * set.
   * @name connectCurrentRefinements
   * @kind connector
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @propType {function} [clearsQuery=false] - Pass true to also clear the search query
   * @providedPropType {function} refine - a function to remove a single filter
   * @providedPropType {array.<{label: string, attributeName: string, currentRefinement: string || object, items: array, value: function}>} items - all the filters, the `value` is to pass to the `refine` function for removing all currentrefinements, `label` is for the display. When existing several refinements for the same atribute name, then you get a nested `items` object that contains a `label` and a `value` function to use to remove a single filter. `attributeName` and `currentRefinement` are metadata containing row values.
   * @providedPropType {string} query - the search query
  */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaCurrentRefinements',
  
    propTypes: {
      transformItems: _propTypes2.default.func
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults, metadata) {
      var items = metadata.reduce(function (res, meta) {
        if (typeof meta.items !== 'undefined') {
          if (!props.clearsQuery && meta.id === 'query') {
            return res;
          } else {
            if (props.clearsQuery && meta.id === 'query' && meta.items[0].currentRefinement === '') {
              return res;
            }
            return res.concat(meta.items);
          }
        }
        return res;
      }, []);
  
      return {
        items: props.transformItems ? props.transformItems(items) : items,
        canRefine: items.length > 0
      };
    },
    refine: function refine(props, searchState, items) {
      // `value` corresponds to our internal clear function computed in each connector metadata.
      var refinementsToClear = items instanceof Array ? items.map(function (item) {
        return item.value;
      }) : [items];
      return refinementsToClear.reduce(function (res, clear) {
        return clear(res);
      }, searchState);
    }
  });
  
  /***/ }),
  /* 212 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var AlgoliaSearchHelper = __webpack_require__(248);
  
  var SearchParameters = __webpack_require__(100);
  var SearchResults = __webpack_require__(190);
  
  /**
   * The algoliasearchHelper module is the function that will let its
   * contains everything needed to use the Algoliasearch
   * Helper. It is a also a function that instanciate the helper.
   * To use the helper, you also need the Algolia JS client v3.
   * @example
   * //using the UMD build
   * var client = algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76');
   * var helper = algoliasearchHelper(client, 'bestbuy', {
   *   facets: ['shipping'],
   *   disjunctiveFacets: ['category']
   * });
   * helper.on('result', function(result) {
   *   console.log(result);
   * });
   * helper.toggleRefine('Movies & TV Shows')
   *       .toggleRefine('Free shipping')
   *       .search();
   * @example
   * // The helper is an event emitter using the node API
   * helper.on('result', updateTheResults);
   * helper.once('result', updateTheResults);
   * helper.removeListener('result', updateTheResults);
   * helper.removeAllListeners('result');
   * @module algoliasearchHelper
   * @param  {AlgoliaSearch} client an AlgoliaSearch client
   * @param  {string} index the name of the index to query
   * @param  {SearchParameters|object} opts an object defining the initial config of the search. It doesn't have to be a {SearchParameters}, just an object containing the properties you need from it.
   * @return {AlgoliaSearchHelper}
   */
  function algoliasearchHelper(client, index, opts) {
    return new AlgoliaSearchHelper(client, index, opts);
  }
  
  /**
   * The version currently used
   * @member module:algoliasearchHelper.version
   * @type {number}
   */
  algoliasearchHelper.version = __webpack_require__(208);
  
  /**
   * Constructor for the Helper.
   * @member module:algoliasearchHelper.AlgoliaSearchHelper
   * @type {AlgoliaSearchHelper}
   */
  algoliasearchHelper.AlgoliaSearchHelper = AlgoliaSearchHelper;
  
  /**
   * Constructor for the object containing all the parameters of the search.
   * @member module:algoliasearchHelper.SearchParameters
   * @type {SearchParameters}
   */
  algoliasearchHelper.SearchParameters = SearchParameters;
  
  /**
   * Constructor for the object containing the results of the search.
   * @member module:algoliasearchHelper.SearchResults
   * @type {SearchResults}
   */
  algoliasearchHelper.SearchResults = SearchResults;
  
  /**
   * URL tools to generate query string and parse them from/into
   * SearchParameters
   * @member module:algoliasearchHelper.url
   * @type {object} {@link url}
   *
   */
  algoliasearchHelper.url = __webpack_require__(205);
  
  module.exports = algoliasearchHelper;
  
  
  /***/ }),
  /* 213 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var toNumber = __webpack_require__(265);
  
  /** Used as references for various `Number` constants. */
  var INFINITY = 1 / 0,
      MAX_INTEGER = 1.7976931348623157e+308;
  
  /**
   * Converts `value` to a finite number.
   *
   * @static
   * @memberOf _
   * @since 4.12.0
   * @category Lang
   * @param {*} value The value to convert.
   * @returns {number} Returns the converted number.
   * @example
   *
   * _.toFinite(3.2);
   * // => 3.2
   *
   * _.toFinite(Number.MIN_VALUE);
   * // => 5e-324
   *
   * _.toFinite(Infinity);
   * // => 1.7976931348623157e+308
   *
   * _.toFinite('3.2');
   * // => 3.2
   */
  function toFinite(value) {
    if (!value) {
      return value === 0 ? value : 0;
    }
    value = toNumber(value);
    if (value === INFINITY || value === -INFINITY) {
      var sign = (value < 0 ? -1 : 1);
      return sign * MAX_INTEGER;
    }
    return value === value ? value : 0;
  }
  
  module.exports = toFinite;
  
  
  /***/ }),
  /* 214 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isNumber = __webpack_require__(184);
  
  /**
   * Checks if `value` is `NaN`.
   *
   * **Note:** This method is based on
   * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
   * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
   * `undefined` and other non-number values.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
   * @example
   *
   * _.isNaN(NaN);
   * // => true
   *
   * _.isNaN(new Number(NaN));
   * // => true
   *
   * isNaN(undefined);
   * // => true
   *
   * _.isNaN(undefined);
   * // => false
   */
  function isNaN(value) {
    // An `NaN` primitive is the only value that is not equal to itself.
    // Perform the `toStringTag` check first to avoid errors with some
    // ActiveX objects in IE.
    return isNumber(value) && value != +value;
  }
  
  module.exports = isNaN;
  
  
  /***/ }),
  /* 215 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var eq = __webpack_require__(18),
      isArrayLike = __webpack_require__(11),
      isIndex = __webpack_require__(32),
      isObject = __webpack_require__(6);
  
  /**
   * Checks if the given arguments are from an iteratee call.
   *
   * @private
   * @param {*} value The potential iteratee value argument.
   * @param {*} index The potential iteratee index or key argument.
   * @param {*} object The potential iteratee object argument.
   * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
   *  else `false`.
   */
  function isIterateeCall(value, index, object) {
    if (!isObject(object)) {
      return false;
    }
    var type = typeof index;
    if (type == 'number'
          ? (isArrayLike(object) && isIndex(index, object.length))
          : (type == 'string' && index in object)
        ) {
      return eq(object[index], value);
    }
    return false;
  }
  
  module.exports = isIterateeCall;
  
  
  /***/ }),
  /* 216 */,
  /* 217 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _highlight = __webpack_require__(330);
  
  var _highlight2 = _interopRequireDefault(_highlight);
  
  var _highlightTags = __webpack_require__(218);
  
  var _highlightTags2 = _interopRequireDefault(_highlightTags);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var highlight = function highlight(_ref) {
    var attributeName = _ref.attributeName,
        hit = _ref.hit,
        highlightProperty = _ref.highlightProperty;
    return (0, _highlight2.default)({
      attributeName: attributeName,
      hit: hit,
      preTag: _highlightTags2.default.highlightPreTag,
      postTag: _highlightTags2.default.highlightPostTag,
      highlightProperty: highlightProperty
    });
  };
  
  /**
   * connectHighlight connector provides the logic to create an highlighter
   * component that will retrieve, parse and render an highlighted attribute
   * from an Algolia hit.
   * @name connectHighlight
   * @kind connector
   * @category connector
   * @providedPropType {function} highlight - the function to retrieve and parse an attribute from a hit. It takes a configuration object with 3 attribute: `highlightProperty` which is the property that contains the highlight structure from the records, `attributeName` which is the name of the attribute to look for and `hit` which is the hit from Algolia. It returns an array of object `{value: string, isHighlighted: boolean}`.
   * @example
  * import React from 'react';
  * import { connectHighlight } from 'react-instantsearch/connectors';
  * import { InstantSearch, Hits } from 'react-instantsearch/dom';
  * 
  * const CustomHighlight = connectHighlight(
  *   ({ highlight, attributeName, hit, highlightProperty }) => {
  *     const parsedHit = highlight({ attributeName, hit, highlightProperty: '_highlightResult' });
  *     const highlightedHits = parsedHit.map(part => {
  *       if (part.isHighlighted) return <mark>{part.value}</mark>;
  *       return part.value;
  *     });
  *     return <div>{highlightedHits}</div>;
  *   }
  * );
  * 
  * const Hit = ({hit}) =>
  * <p>
  *   <CustomHighlight attributeName="description" hit={hit} />
  * </p>;
  * 
  * export default function App() {
  *   return (
  *     <InstantSearch
  *        appId="latency"
  *        apiKey="6be0576ff61c053d5f9a3225e2a90f76"
  *        indexName="ikea">
  *       <Hits hitComponent={Hit} />
  *     </InstantSearch>
  *   );
  * }
  */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaHighlighter',
  
    propTypes: {},
  
    getProvidedProps: function getProvidedProps() {
      return { highlight: highlight };
    }
  });
  
  /***/ }),
  /* 218 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  var timestamp = Date.now().toString();
  
  exports.default = {
    highlightPreTag: "<ais-highlight-" + timestamp + ">",
    highlightPostTag: "</ais-highlight-" + timestamp + ">"
  };
  
  /***/ }),
  /* 219 */,
  /* 220 */,
  /* 221 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _keys2 = __webpack_require__(9);
  
  var _keys3 = _interopRequireDefault(_keys2);
  
  var _difference2 = __webpack_require__(222);
  
  var _difference3 = _interopRequireDefault(_difference2);
  
  var _omit2 = __webpack_require__(45);
  
  var _omit3 = _interopRequireDefault(_omit2);
  
  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; };
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId() {
    return 'configure';
  }
  
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaConfigure',
    getProvidedProps: function getProvidedProps() {
      return {};
    },
    getSearchParameters: function getSearchParameters(searchParameters, props) {
      var items = (0, _omit3.default)(props, 'children');
      return searchParameters.setQueryParameters(items);
    },
    transitionState: function transitionState(props, prevSearchState, nextSearchState) {
      var id = getId();
      var items = (0, _omit3.default)(props, 'children');
      var nonPresentKeys = this._props ? (0, _difference3.default)((0, _keys3.default)(this._props), (0, _keys3.default)(props)) : [];
      this._props = props;
      var nextValue = _defineProperty({}, id, _extends({}, (0, _omit3.default)(nextSearchState[id], nonPresentKeys), items));
      return (0, _indexUtils.refineValue)(nextSearchState, nextValue, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      var id = getId();
      var index = (0, _indexUtils.getIndex)(this.context);
      var subState = (0, _indexUtils.hasMultipleIndex)(this.context) && searchState.indices ? searchState.indices[index] : searchState;
      var configureKeys = subState && subState[id] ? Object.keys(subState[id]) : [];
      var configureState = configureKeys.reduce(function (acc, item) {
        if (!props[item]) {
          acc[item] = subState[id][item];
        }
        return acc;
      }, {});
      var nextValue = _defineProperty({}, id, configureState);
      return (0, _indexUtils.refineValue)(searchState, nextValue, this.context);
    }
  });
  
  /***/ }),
  /* 222 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseDifference = __webpack_require__(223),
      baseFlatten = __webpack_require__(165),
      baseRest = __webpack_require__(25),
      isArrayLikeObject = __webpack_require__(94);
  
  /**
   * Creates an array of `array` values not included in the other given arrays
   * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * for equality comparisons. The order and references of result values are
   * determined by the first array.
   *
   * **Note:** Unlike `_.pullAll`, this method returns a new array.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {Array} array The array to inspect.
   * @param {...Array} [values] The values to exclude.
   * @returns {Array} Returns the new array of filtered values.
   * @see _.without, _.xor
   * @example
   *
   * _.difference([2, 1], [2, 3]);
   * // => [1]
   */
  var difference = baseRest(function(array, values) {
    return isArrayLikeObject(array)
      ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
      : [];
  });
  
  module.exports = difference;
  
  
  /***/ }),
  /* 223 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var SetCache = __webpack_require__(59),
      arrayIncludes = __webpack_require__(92),
      arrayIncludesWith = __webpack_require__(164),
      arrayMap = __webpack_require__(12),
      baseUnary = __webpack_require__(42),
      cacheHas = __webpack_require__(60);
  
  /** Used as the size to enable large array optimizations. */
  var LARGE_ARRAY_SIZE = 200;
  
  /**
   * The base implementation of methods like `_.difference` without support
   * for excluding multiple arrays or iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {Array} values The values to exclude.
   * @param {Function} [iteratee] The iteratee invoked per element.
   * @param {Function} [comparator] The comparator invoked per element.
   * @returns {Array} Returns the new array of filtered values.
   */
  function baseDifference(array, values, iteratee, comparator) {
    var index = -1,
        includes = arrayIncludes,
        isCommon = true,
        length = array.length,
        result = [],
        valuesLength = values.length;
  
    if (!length) {
      return result;
    }
    if (iteratee) {
      values = arrayMap(values, baseUnary(iteratee));
    }
    if (comparator) {
      includes = arrayIncludesWith;
      isCommon = false;
    }
    else if (values.length >= LARGE_ARRAY_SIZE) {
      includes = cacheHas;
      isCommon = false;
      values = new SetCache(values);
    }
    outer:
    while (++index < length) {
      var value = array[index],
          computed = iteratee == null ? value : iteratee(value);
  
      value = (comparator || value !== 0) ? value : 0;
      if (isCommon && computed === computed) {
        var valuesIndex = valuesLength;
        while (valuesIndex--) {
          if (values[valuesIndex] === computed) {
            continue outer;
          }
        }
        result.push(value);
      }
      else if (!includes(values, computed, comparator)) {
        result.push(value);
      }
    }
    return result;
  }
  
  module.exports = baseDifference;
  
  
  /***/ }),
  /* 224 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.isNaN` without support for number objects.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
   */
  function baseIsNaN(value) {
    return value !== value;
  }
  
  module.exports = baseIsNaN;
  
  
  /***/ }),
  /* 225 */
  /***/ (function(module, exports) {
  
  /**
   * A specialized version of `_.indexOf` which performs strict equality
   * comparisons of values, i.e. `===`.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} value The value to search for.
   * @param {number} fromIndex The index to search from.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function strictIndexOf(array, value, fromIndex) {
    var index = fromIndex - 1,
        length = array.length;
  
    while (++index < length) {
      if (array[index] === value) {
        return index;
      }
    }
    return -1;
  }
  
  module.exports = strictIndexOf;
  
  
  /***/ }),
  /* 226 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14),
      isArguments = __webpack_require__(20),
      isArray = __webpack_require__(0);
  
  /** Built-in value references. */
  var spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined;
  
  /**
   * Checks if `value` is a flattenable `arguments` object or array.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
   */
  function isFlattenable(value) {
    return isArray(value) || isArguments(value) ||
      !!(spreadableSymbol && value && value[spreadableSymbol]);
  }
  
  module.exports = isFlattenable;
  
  
  /***/ }),
  /* 227 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var constant = __webpack_require__(167),
      defineProperty = __webpack_require__(168),
      identity = __webpack_require__(26);
  
  /**
   * The base implementation of `setToString` without support for hot loop shorting.
   *
   * @private
   * @param {Function} func The function to modify.
   * @param {Function} string The `toString` result.
   * @returns {Function} Returns `func`.
   */
  var baseSetToString = !defineProperty ? identity : function(func, string) {
    return defineProperty(func, 'toString', {
      'configurable': true,
      'enumerable': false,
      'value': constant(string),
      'writable': true
    });
  };
  
  module.exports = baseSetToString;
  
  
  /***/ }),
  /* 228 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Stack = __webpack_require__(38),
      arrayEach = __webpack_require__(95),
      assignValue = __webpack_require__(96),
      baseAssign = __webpack_require__(229),
      baseAssignIn = __webpack_require__(230),
      cloneBuffer = __webpack_require__(170),
      copyArray = __webpack_require__(69),
      copySymbols = __webpack_require__(233),
      copySymbolsIn = __webpack_require__(234),
      getAllKeys = __webpack_require__(85),
      getAllKeysIn = __webpack_require__(97),
      getTag = __webpack_require__(56),
      initCloneArray = __webpack_require__(235),
      initCloneByTag = __webpack_require__(236),
      initCloneObject = __webpack_require__(173),
      isArray = __webpack_require__(0),
      isBuffer = __webpack_require__(21),
      isObject = __webpack_require__(6),
      keys = __webpack_require__(9);
  
  /** Used to compose bitmasks for cloning. */
  var CLONE_DEEP_FLAG = 1,
      CLONE_FLAT_FLAG = 2,
      CLONE_SYMBOLS_FLAG = 4;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]',
      weakMapTag = '[object WeakMap]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /** Used to identify `toStringTag` values supported by `_.clone`. */
  var cloneableTags = {};
  cloneableTags[argsTag] = cloneableTags[arrayTag] =
  cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
  cloneableTags[boolTag] = cloneableTags[dateTag] =
  cloneableTags[float32Tag] = cloneableTags[float64Tag] =
  cloneableTags[int8Tag] = cloneableTags[int16Tag] =
  cloneableTags[int32Tag] = cloneableTags[mapTag] =
  cloneableTags[numberTag] = cloneableTags[objectTag] =
  cloneableTags[regexpTag] = cloneableTags[setTag] =
  cloneableTags[stringTag] = cloneableTags[symbolTag] =
  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
  cloneableTags[errorTag] = cloneableTags[funcTag] =
  cloneableTags[weakMapTag] = false;
  
  /**
   * The base implementation of `_.clone` and `_.cloneDeep` which tracks
   * traversed objects.
   *
   * @private
   * @param {*} value The value to clone.
   * @param {boolean} bitmask The bitmask flags.
   *  1 - Deep clone
   *  2 - Flatten inherited properties
   *  4 - Clone symbols
   * @param {Function} [customizer] The function to customize cloning.
   * @param {string} [key] The key of `value`.
   * @param {Object} [object] The parent object of `value`.
   * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
   * @returns {*} Returns the cloned value.
   */
  function baseClone(value, bitmask, customizer, key, object, stack) {
    var result,
        isDeep = bitmask & CLONE_DEEP_FLAG,
        isFlat = bitmask & CLONE_FLAT_FLAG,
        isFull = bitmask & CLONE_SYMBOLS_FLAG;
  
    if (customizer) {
      result = object ? customizer(value, key, object, stack) : customizer(value);
    }
    if (result !== undefined) {
      return result;
    }
    if (!isObject(value)) {
      return value;
    }
    var isArr = isArray(value);
    if (isArr) {
      result = initCloneArray(value);
      if (!isDeep) {
        return copyArray(value, result);
      }
    } else {
      var tag = getTag(value),
          isFunc = tag == funcTag || tag == genTag;
  
      if (isBuffer(value)) {
        return cloneBuffer(value, isDeep);
      }
      if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
        result = (isFlat || isFunc) ? {} : initCloneObject(value);
        if (!isDeep) {
          return isFlat
            ? copySymbolsIn(value, baseAssignIn(result, value))
            : copySymbols(value, baseAssign(result, value));
        }
      } else {
        if (!cloneableTags[tag]) {
          return object ? value : {};
        }
        result = initCloneByTag(value, tag, baseClone, isDeep);
      }
    }
    // Check for circular references and return its corresponding clone.
    stack || (stack = new Stack);
    var stacked = stack.get(value);
    if (stacked) {
      return stacked;
    }
    stack.set(value, result);
  
    var keysFunc = isFull
      ? (isFlat ? getAllKeysIn : getAllKeys)
      : (isFlat ? keysIn : keys);
  
    var props = isArr ? undefined : keysFunc(value);
    arrayEach(props || value, function(subValue, key) {
      if (props) {
        key = subValue;
        subValue = value[key];
      }
      // Recursively populate clone (susceptible to call stack limits).
      assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
    });
    return result;
  }
  
  module.exports = baseClone;
  
  
  /***/ }),
  /* 229 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      keys = __webpack_require__(9);
  
  /**
   * The base implementation of `_.assign` without support for multiple sources
   * or `customizer` functions.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @returns {Object} Returns `object`.
   */
  function baseAssign(object, source) {
    return object && copyObject(source, keys(source), object);
  }
  
  module.exports = baseAssign;
  
  
  /***/ }),
  /* 230 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      keysIn = __webpack_require__(47);
  
  /**
   * The base implementation of `_.assignIn` without support for multiple sources
   * or `customizer` functions.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @returns {Object} Returns `object`.
   */
  function baseAssignIn(object, source) {
    return object && copyObject(source, keysIn(source), object);
  }
  
  module.exports = baseAssignIn;
  
  
  /***/ }),
  /* 231 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(6),
      isPrototype = __webpack_require__(37),
      nativeKeysIn = __webpack_require__(232);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function baseKeysIn(object) {
    if (!isObject(object)) {
      return nativeKeysIn(object);
    }
    var isProto = isPrototype(object),
        result = [];
  
    for (var key in object) {
      if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = baseKeysIn;
  
  
  /***/ }),
  /* 232 */
  /***/ (function(module, exports) {
  
  /**
   * This function is like
   * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
   * except that it includes inherited enumerable properties.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function nativeKeysIn(object) {
    var result = [];
    if (object != null) {
      for (var key in Object(object)) {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = nativeKeysIn;
  
  
  /***/ }),
  /* 233 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      getSymbols = __webpack_require__(62);
  
  /**
   * Copies own symbols of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy symbols from.
   * @param {Object} [object={}] The object to copy symbols to.
   * @returns {Object} Returns `object`.
   */
  function copySymbols(source, object) {
    return copyObject(source, getSymbols(source), object);
  }
  
  module.exports = copySymbols;
  
  
  /***/ }),
  /* 234 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      getSymbolsIn = __webpack_require__(171);
  
  /**
   * Copies own and inherited symbols of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy symbols from.
   * @param {Object} [object={}] The object to copy symbols to.
   * @returns {Object} Returns `object`.
   */
  function copySymbolsIn(source, object) {
    return copyObject(source, getSymbolsIn(source), object);
  }
  
  module.exports = copySymbolsIn;
  
  
  /***/ }),
  /* 235 */
  /***/ (function(module, exports) {
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Initializes an array clone.
   *
   * @private
   * @param {Array} array The array to clone.
   * @returns {Array} Returns the initialized clone.
   */
  function initCloneArray(array) {
    var length = array.length,
        result = array.constructor(length);
  
    // Add properties assigned by `RegExp#exec`.
    if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
      result.index = array.index;
      result.input = array.input;
    }
    return result;
  }
  
  module.exports = initCloneArray;
  
  
  /***/ }),
  /* 236 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var cloneArrayBuffer = __webpack_require__(98),
      cloneDataView = __webpack_require__(237),
      cloneMap = __webpack_require__(238),
      cloneRegExp = __webpack_require__(240),
      cloneSet = __webpack_require__(241),
      cloneSymbol = __webpack_require__(243),
      cloneTypedArray = __webpack_require__(172);
  
  /** `Object#toString` result references. */
  var boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /**
   * Initializes an object clone based on its `toStringTag`.
   *
   * **Note:** This function only supports cloning values with tags of
   * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
   *
   * @private
   * @param {Object} object The object to clone.
   * @param {string} tag The `toStringTag` of the object to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the initialized clone.
   */
  function initCloneByTag(object, tag, cloneFunc, isDeep) {
    var Ctor = object.constructor;
    switch (tag) {
      case arrayBufferTag:
        return cloneArrayBuffer(object);
  
      case boolTag:
      case dateTag:
        return new Ctor(+object);
  
      case dataViewTag:
        return cloneDataView(object, isDeep);
  
      case float32Tag: case float64Tag:
      case int8Tag: case int16Tag: case int32Tag:
      case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
        return cloneTypedArray(object, isDeep);
  
      case mapTag:
        return cloneMap(object, isDeep, cloneFunc);
  
      case numberTag:
      case stringTag:
        return new Ctor(object);
  
      case regexpTag:
        return cloneRegExp(object);
  
      case setTag:
        return cloneSet(object, isDeep, cloneFunc);
  
      case symbolTag:
        return cloneSymbol(object);
    }
  }
  
  module.exports = initCloneByTag;
  
  
  /***/ }),
  /* 237 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var cloneArrayBuffer = __webpack_require__(98);
  
  /**
   * Creates a clone of `dataView`.
   *
   * @private
   * @param {Object} dataView The data view to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned data view.
   */
  function cloneDataView(dataView, isDeep) {
    var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
    return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
  }
  
  module.exports = cloneDataView;
  
  
  /***/ }),
  /* 238 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var addMapEntry = __webpack_require__(239),
      arrayReduce = __webpack_require__(99),
      mapToArray = __webpack_require__(83);
  
  /** Used to compose bitmasks for cloning. */
  var CLONE_DEEP_FLAG = 1;
  
  /**
   * Creates a clone of `map`.
   *
   * @private
   * @param {Object} map The map to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned map.
   */
  function cloneMap(map, isDeep, cloneFunc) {
    var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
    return arrayReduce(array, addMapEntry, new map.constructor);
  }
  
  module.exports = cloneMap;
  
  
  /***/ }),
  /* 239 */
  /***/ (function(module, exports) {
  
  /**
   * Adds the key-value `pair` to `map`.
   *
   * @private
   * @param {Object} map The map to modify.
   * @param {Array} pair The key-value pair to add.
   * @returns {Object} Returns `map`.
   */
  function addMapEntry(map, pair) {
    // Don't return `map.set` because it's not chainable in IE 11.
    map.set(pair[0], pair[1]);
    return map;
  }
  
  module.exports = addMapEntry;
  
  
  /***/ }),
  /* 240 */
  /***/ (function(module, exports) {
  
  /** Used to match `RegExp` flags from their coerced string values. */
  var reFlags = /\w*$/;
  
  /**
   * Creates a clone of `regexp`.
   *
   * @private
   * @param {Object} regexp The regexp to clone.
   * @returns {Object} Returns the cloned regexp.
   */
  function cloneRegExp(regexp) {
    var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
    result.lastIndex = regexp.lastIndex;
    return result;
  }
  
  module.exports = cloneRegExp;
  
  
  /***/ }),
  /* 241 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var addSetEntry = __webpack_require__(242),
      arrayReduce = __webpack_require__(99),
      setToArray = __webpack_require__(84);
  
  /** Used to compose bitmasks for cloning. */
  var CLONE_DEEP_FLAG = 1;
  
  /**
   * Creates a clone of `set`.
   *
   * @private
   * @param {Object} set The set to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned set.
   */
  function cloneSet(set, isDeep, cloneFunc) {
    var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
    return arrayReduce(array, addSetEntry, new set.constructor);
  }
  
  module.exports = cloneSet;
  
  
  /***/ }),
  /* 242 */
  /***/ (function(module, exports) {
  
  /**
   * Adds `value` to `set`.
   *
   * @private
   * @param {Object} set The set to modify.
   * @param {*} value The value to add.
   * @returns {Object} Returns `set`.
   */
  function addSetEntry(set, value) {
    // Don't return `set.add` because it's not chainable in IE 11.
    set.add(value);
    return set;
  }
  
  module.exports = addSetEntry;
  
  
  /***/ }),
  /* 243 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Symbol = __webpack_require__(14);
  
  /** Used to convert symbols to primitives and strings. */
  var symbolProto = Symbol ? Symbol.prototype : undefined,
      symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
  
  /**
   * Creates a clone of the `symbol` object.
   *
   * @private
   * @param {Object} symbol The symbol object to clone.
   * @returns {Object} Returns the cloned symbol object.
   */
  function cloneSymbol(symbol) {
    return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
  }
  
  module.exports = cloneSymbol;
  
  
  /***/ }),
  /* 244 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var castPath = __webpack_require__(22),
      last = __webpack_require__(174),
      parent = __webpack_require__(245),
      toKey = __webpack_require__(24);
  
  /**
   * The base implementation of `_.unset`.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {Array|string} path The property path to unset.
   * @returns {boolean} Returns `true` if the property is deleted, else `false`.
   */
  function baseUnset(object, path) {
    path = castPath(path, object);
    object = parent(object, path);
    return object == null || delete object[toKey(last(path))];
  }
  
  module.exports = baseUnset;
  
  
  /***/ }),
  /* 245 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGet = __webpack_require__(71),
      baseSlice = __webpack_require__(175);
  
  /**
   * Gets the parent value at `path` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array} path The path to get the parent value of.
   * @returns {*} Returns the parent value.
   */
  function parent(object, path) {
    return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
  }
  
  module.exports = parent;
  
  
  /***/ }),
  /* 246 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isPlainObject = __webpack_require__(43);
  
  /**
   * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
   * objects.
   *
   * @private
   * @param {*} value The value to inspect.
   * @param {string} key The key of the property to inspect.
   * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
   */
  function customOmitClone(value) {
    return isPlainObject(value) ? undefined : value;
  }
  
  module.exports = customOmitClone;
  
  
  /***/ }),
  /* 247 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.getId = undefined;
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _algoliasearchHelper = __webpack_require__(212);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  var getId = exports.getId = function getId(props) {
    return props.attributes[0];
  };
  
  var namespace = 'hierarchicalMenu';
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), null, function (currentRefinement) {
      if (currentRefinement === '') {
        return null;
      }
      return currentRefinement;
    });
  }
  
  function getValue(path, props, searchState, context) {
    var id = props.id,
        attributes = props.attributes,
        separator = props.separator,
        rootPath = props.rootPath,
        showParentLevel = props.showParentLevel;
  
  
    var currentRefinement = getCurrentRefinement(props, searchState, context);
    var nextRefinement = void 0;
  
    if (currentRefinement === null) {
      nextRefinement = path;
    } else {
      var tmpSearchParameters = new _algoliasearchHelper.SearchParameters({
        hierarchicalFacets: [{
          name: id,
          attributes: attributes,
          separator: separator,
          rootPath: rootPath,
          showParentLevel: showParentLevel
        }]
      });
  
      nextRefinement = tmpSearchParameters.toggleHierarchicalFacetRefinement(id, currentRefinement).toggleHierarchicalFacetRefinement(id, path).getHierarchicalRefinement(id)[0];
    }
  
    return nextRefinement;
  }
  
  function transformValue(value, limit, props, searchState, context) {
    return value.slice(0, limit).map(function (v) {
      return {
        label: v.name,
        value: getValue(v.path, props, searchState, context),
        count: v.count,
        isRefined: v.isRefined,
        items: v.data && transformValue(v.data, limit, props, searchState, context)
      };
    });
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId(props);
    var nextValue = _defineProperty({}, id, nextRefinement || '');
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  
  var sortBy = ['name:asc'];
  
  /**
   * connectHierarchicalMenu connector provides the logic to build a widget that will
   * give the user the ability to explore a tree-like structure.
   * This is commonly used for multi-level categorization of products on e-commerce
   * websites. From a UX point of view, we suggest not displaying more than two levels deep.
   * @name connectHierarchicalMenu
   * @requirements To use this widget, your attributes must be formatted in a specific way.
   * If you want for example to have a hiearchical menu of categories, objects in your index
   * should be formatted this way:
   *
   * ```json
   * {
   *   "categories.lvl0": "products",
   *   "categories.lvl1": "products > fruits",
   *   "categories.lvl2": "products > fruits > citrus"
   * }
   * ```
   *
   * It's also possible to provide more than one path for each level:
   *
   * ```json
   * {
   *   "categories.lvl0": ["products", "goods"],
   *   "categories.lvl1": ["products > fruits", "goods > to eat"]
   * }
   * ```
   *
   * All attributes passed to the `attributes` prop must be present in "attributes for faceting"
   * on the Algolia dashboard or configured as `attributesForFaceting` via a set settings call to the Algolia API.
   *
   * @kind connector
   * @propType {string} attributes - List of attributes to use to generate the hierarchy of the menu. See the example for the convention to follow.
   * @propType {string} [defaultRefinement] - the item value selected by default
   * @propType {boolean} [showMore=false] - Flag to activate the show more button, for toggling the number of items between limitMin and limitMax.
   * @propType {number} [limitMin=10] -  The maximum number of items displayed.
   * @propType {number} [limitMax=20] -  The maximum number of items displayed when the user triggers the show more. Not considered if `showMore` is false.
   * @propType {string} [separator='>'] -  Specifies the level separator used in the data.
   * @propType {string[]} [rootPath=null] - The already selected and hidden path.
   * @propType {boolean} [showParentLevel=true] - Flag to set if the parent level should be displayed.
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @providedPropType {function} refine - a function to toggle a refinement
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the refinement currently applied
   * @providedPropType {array.<{items: object, count: number, isRefined: boolean, label: string, value: string}>} items - the list of items the HierarchicalMenu can display. items has the same shape as parent items.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaHierarchicalMenu',
  
    propTypes: {
      attributes: function attributes(props, propName, componentName) {
        var isNotString = function isNotString(val) {
          return typeof val !== 'string';
        };
        if (!Array.isArray(props[propName]) || props[propName].some(isNotString) || props[propName].length < 1) {
          return new Error('Invalid prop ' + propName + ' supplied to ' + componentName + '. Expected an Array of Strings');
        }
        return undefined;
      },
      separator: _propTypes2.default.string,
      rootPath: _propTypes2.default.string,
      showParentLevel: _propTypes2.default.bool,
      defaultRefinement: _propTypes2.default.string,
      showMore: _propTypes2.default.bool,
      limitMin: _propTypes2.default.number,
      limitMax: _propTypes2.default.number,
      transformItems: _propTypes2.default.func
    },
  
    defaultProps: {
      showMore: false,
      limitMin: 10,
      limitMax: 20,
      separator: ' > ',
      rootPath: null,
      showParentLevel: true
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
      var id = getId(props);
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      var isFacetPresent = Boolean(results) && Boolean(results.getFacetByName(id));
  
      if (!isFacetPresent) {
        return {
          items: [],
          currentRefinement: getCurrentRefinement(props, searchState, this.context),
          canRefine: false
        };
      }
  
      var limit = showMore ? limitMax : limitMin;
      var value = results.getFacetValues(id, { sortBy: sortBy });
      var items = value.data ? transformValue(value.data, limit, props, searchState, this.context) : [];
  
      return {
        items: props.transformItems ? props.transformItems(items) : items,
        currentRefinement: getCurrentRefinement(props, searchState, this.context),
        canRefine: items.length > 0
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var attributes = props.attributes,
          separator = props.separator,
          rootPath = props.rootPath,
          showParentLevel = props.showParentLevel,
          showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
  
      var id = getId(props);
      var limit = showMore ? limitMax : limitMin;
  
      searchParameters = searchParameters.addHierarchicalFacet({
        name: id,
        attributes: attributes,
        separator: separator,
        rootPath: rootPath,
        showParentLevel: showParentLevel
      }).setQueryParameters({
        maxValuesPerFacet: Math.max(searchParameters.maxValuesPerFacet || 0, limit)
      });
  
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      if (currentRefinement !== null) {
        searchParameters = searchParameters.toggleHierarchicalFacetRefinement(id, currentRefinement);
      }
  
      return searchParameters;
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this = this;
  
      var rootAttribute = props.attributes[0];
      var id = getId(props);
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
  
      return {
        id: id,
        index: (0, _indexUtils.getIndex)(this.context),
        items: !currentRefinement ? [] : [{
          label: rootAttribute + ': ' + currentRefinement,
          attributeName: rootAttribute,
          value: function value(nextState) {
            return _refine(props, nextState, '', _this.context);
          },
          currentRefinement: currentRefinement
        }]
      };
    }
  });
  
  /***/ }),
  /* 248 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var SearchParameters = __webpack_require__(100);
  var SearchResults = __webpack_require__(190);
  var DerivedHelper = __webpack_require__(314);
  var requestBuilder = __webpack_require__(317);
  
  var util = __webpack_require__(203);
  var events = __webpack_require__(204);
  
  var flatten = __webpack_require__(177);
  var forEach = __webpack_require__(35);
  var isEmpty = __webpack_require__(16);
  var map = __webpack_require__(17);
  
  var url = __webpack_require__(205);
  var version = __webpack_require__(208);
  
  /**
   * Event triggered when a parameter is set or updated
   * @event AlgoliaSearchHelper#event:change
   * @property {SearchParameters} state the current parameters with the latest changes applied
   * @property {SearchResults} lastResults the previous results received from Algolia. `null` before
   * the first request
   * @example
   * helper.on('change', function(state, lastResults) {
   *   console.log('The parameters have changed');
   * });
   */
  
  /**
   * Event triggered when a main search is sent to Algolia
   * @event AlgoliaSearchHelper#event:search
   * @property {SearchParameters} state the parameters used for this search
   * @property {SearchResults} lastResults the results from the previous search. `null` if
   * it is the first search.
   * @example
   * helper.on('search', function(state, lastResults) {
   *   console.log('Search sent');
   * });
   */
  
  /**
   * Event triggered when a search using `searchForFacetValues` is sent to Algolia
   * @event AlgoliaSearchHelper#event:searchForFacetValues
   * @property {SearchParameters} state the parameters used for this search
   * it is the first search.
   * @property {string} facet the facet searched into
   * @property {string} query the query used to search in the facets
   * @example
   * helper.on('searchForFacetValues', function(state, facet, query) {
   *   console.log('searchForFacetValues sent');
   * });
   */
  
  /**
   * Event triggered when a search using `searchOnce` is sent to Algolia
   * @event AlgoliaSearchHelper#event:searchOnce
   * @property {SearchParameters} state the parameters used for this search
   * it is the first search.
   * @example
   * helper.on('searchOnce', function(state) {
   *   console.log('searchOnce sent');
   * });
   */
  
  /**
   * Event triggered when the results are retrieved from Algolia
   * @event AlgoliaSearchHelper#event:result
   * @property {SearchResults} results the results received from Algolia
   * @property {SearchParameters} state the parameters used to query Algolia. Those might
   * be different from the one in the helper instance (for example if the network is unreliable).
   * @example
   * helper.on('result', function(results, state) {
   *   console.log('Search results received');
   * });
   */
  
  /**
   * Event triggered when Algolia sends back an error. For example, if an unknown parameter is
   * used, the error can be caught using this event.
   * @event AlgoliaSearchHelper#event:error
   * @property {Error} error the error returned by the Algolia.
   * @example
   * helper.on('error', function(error) {
   *   console.log('Houston we got a problem.');
   * });
   */
  
  /**
   * Event triggered when the queue of queries have been depleted (with any result or outdated queries)
   * @event AlgoliaSearchHelper#event:searchQueueEmpty
   * @example
   * helper.on('searchQueueEmpty', function() {
   *   console.log('No more search pending');
   *   // This is received before the result event if we're not expecting new results
   * });
   *
   * helper.search();
   */
  
  /**
   * Initialize a new AlgoliaSearchHelper
   * @class
   * @classdesc The AlgoliaSearchHelper is a class that ease the management of the
   * search. It provides an event based interface for search callbacks:
   *  - change: when the internal search state is changed.
   *    This event contains a {@link SearchParameters} object and the
   *    {@link SearchResults} of the last result if any.
   *  - search: when a search is triggered using the `search()` method.
   *  - result: when the response is retrieved from Algolia and is processed.
   *    This event contains a {@link SearchResults} object and the
   *    {@link SearchParameters} corresponding to this answer.
   *  - error: when the response is an error. This event contains the error returned by the server.
   * @param  {AlgoliaSearch} client an AlgoliaSearch client
   * @param  {string} index the index name to query
   * @param  {SearchParameters | object} options an object defining the initial
   * config of the search. It doesn't have to be a {SearchParameters},
   * just an object containing the properties you need from it.
   */
  function AlgoliaSearchHelper(client, index, options) {
    if (!client.addAlgoliaAgent) console.log('Please upgrade to the newest version of the JS Client.'); // eslint-disable-line
    else if (!doesClientAgentContainsHelper(client)) client.addAlgoliaAgent('JS Helper ' + version);
  
    this.setClient(client);
    var opts = options || {};
    opts.index = index;
    this.state = SearchParameters.make(opts);
    this.lastResults = null;
    this._queryId = 0;
    this._lastQueryIdReceived = -1;
    this.derivedHelpers = [];
    this._currentNbQueries = 0;
  }
  
  util.inherits(AlgoliaSearchHelper, events.EventEmitter);
  
  /**
   * Start the search with the parameters set in the state. When the
   * method is called, it triggers a `search` event. The results will
   * be available through the `result` event. If an error occurs, an
   * `error` will be fired instead.
   * @return {AlgoliaSearchHelper}
   * @fires search
   * @fires result
   * @fires error
   * @chainable
   */
  AlgoliaSearchHelper.prototype.search = function() {
    this._search();
    return this;
  };
  
  /**
   * Gets the search query parameters that would be sent to the Algolia Client
   * for the hits
   * @return {object} Query Parameters
   */
  AlgoliaSearchHelper.prototype.getQuery = function() {
    var state = this.state;
    return requestBuilder._getHitsSearchParams(state);
  };
  
  /**
   * Start a search using a modified version of the current state. This method does
   * not trigger the helper lifecycle and does not modify the state kept internally
   * by the helper. This second aspect means that the next search call will be the
   * same as a search call before calling searchOnce.
   * @param {object} options can contain all the parameters that can be set to SearchParameters
   * plus the index
   * @param {function} [callback] optional callback executed when the response from the
   * server is back.
   * @return {promise|undefined} if a callback is passed the method returns undefined
   * otherwise it returns a promise containing an object with two keys :
   *  - content with a SearchResults
   *  - state with the state used for the query as a SearchParameters
   * @example
   * // Changing the number of records returned per page to 1
   * // This example uses the callback API
   * var state = helper.searchOnce({hitsPerPage: 1},
   *   function(error, content, state) {
   *     // if an error occurred it will be passed in error, otherwise its value is null
   *     // content contains the results formatted as a SearchResults
   *     // state is the instance of SearchParameters used for this search
   *   });
   * @example
   * // Changing the number of records returned per page to 1
   * // This example uses the promise API
   * var state1 = helper.searchOnce({hitsPerPage: 1})
   *                 .then(promiseHandler);
   *
   * function promiseHandler(res) {
   *   // res contains
   *   // {
   *   //   content : SearchResults
   *   //   state   : SearchParameters (the one used for this specific search)
   *   // }
   * }
   */
  AlgoliaSearchHelper.prototype.searchOnce = function(options, cb) {
    var tempState = !options ? this.state : this.state.setQueryParameters(options);
    var queries = requestBuilder._getQueries(tempState.index, tempState);
    var self = this;
  
    this._currentNbQueries++;
  
    this.emit('searchOnce', tempState);
  
    if (cb) {
      return this.client.search(
        queries,
        function(err, content) {
          self._currentNbQueries--;
          if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');
          if (err) cb(err, null, tempState);
          else cb(err, new SearchResults(tempState, content.results), tempState);
        }
      );
    }
  
    return this.client.search(queries).then(function(content) {
      self._currentNbQueries--;
      if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');
      return {
        content: new SearchResults(tempState, content.results),
        state: tempState,
        _originalResponse: content
      };
    }, function(e) {
      self._currentNbQueries--;
      if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');
      throw e;
    });
  };
  
  /**
   * Structure of each result when using
   * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues)
   * @typedef FacetSearchHit
   * @type {object}
   * @property {string} value the facet value
   * @property {string} highlighted the facet value highlighted with the query string
   * @property {number} count number of occurrence of this facet value
   * @property {boolean} isRefined true if the value is already refined
   */
  
  /**
   * Structure of the data resolved by the
   * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues)
   * promise.
   * @typedef FacetSearchResult
   * @type {object}
   * @property {FacetSearchHit} facetHits the results for this search for facet values
   * @property {number} processingTimeMS time taken by the query inside the engine
   */
  
  /**
   * Search for facet values based on an query and the name of a faceted attribute. This
   * triggers a search and will return a promise. On top of using the query, it also sends
   * the parameters from the state so that the search is narrowed down to only the possible values.
   *
   * See the description of [FacetSearchResult](reference.html#FacetSearchResult)
   * @param {string} facet the name of the faceted attribute
   * @param {string} query the string query for the search
   * @param {number} maxFacetHits the maximum number values returned. Should be > 0 and <= 100
   * @return {promise<FacetSearchResult>} the results of the search
   */
  AlgoliaSearchHelper.prototype.searchForFacetValues = function(facet, query, maxFacetHits) {
    var state = this.state;
    var index = this.client.initIndex(this.state.index);
    var isDisjunctive = state.isDisjunctiveFacet(facet);
    var algoliaQuery = requestBuilder.getSearchForFacetQuery(facet, query, maxFacetHits, this.state);
  
    this._currentNbQueries++;
    var self = this;
  
    this.emit('searchForFacetValues', state, facet, query);
    return index.searchForFacetValues(algoliaQuery).then(function addIsRefined(content) {
      self._currentNbQueries--;
      if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');
      content.facetHits = forEach(content.facetHits, function(f) {
        f.isRefined = isDisjunctive ?
          state.isDisjunctiveFacetRefined(facet, f.value) :
          state.isFacetRefined(facet, f.value);
      });
  
      return content;
    }, function(e) {
      self._currentNbQueries--;
      if (self._currentNbQueries === 0) self.emit('searchQueueEmpty');
      throw e;
    });
  };
  
  /**
   * Sets the text query used for the search.
   *
   * This method resets the current page to 0.
   * @param  {string} q the user query
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.setQuery = function(q) {
    this.state = this.state.setPage(0).setQuery(q);
    this._change();
    return this;
  };
  
  /**
   * Remove all the types of refinements except tags. A string can be provided to remove
   * only the refinements of a specific attribute. For more advanced use case, you can
   * provide a function instead. This function should follow the
   * [clearCallback definition](#SearchParameters.clearCallback).
   *
   * This method resets the current page to 0.
   * @param {string} [name] optional name of the facet / attribute on which we want to remove all refinements
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   * @example
   * // Removing all the refinements
   * helper.clearRefinements().search();
   * @example
   * // Removing all the filters on a the category attribute.
   * helper.clearRefinements('category').search();
   * @example
   * // Removing only the exclude filters on the category facet.
   * helper.clearRefinements(function(value, attribute, type) {
   *   return type === 'exclude' && attribute === 'category';
   * }).search();
   */
  AlgoliaSearchHelper.prototype.clearRefinements = function(name) {
    this.state = this.state.setPage(0).clearRefinements(name);
    this._change();
    return this;
  };
  
  /**
   * Remove all the tag filters.
   *
   * This method resets the current page to 0.
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.clearTags = function() {
    this.state = this.state.setPage(0).clearTags();
    this._change();
    return this;
  };
  
  /**
   * Adds a disjunctive filter to a faceted attribute with the `value` provided. If the
   * filter is already set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value (will be converted to string)
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.addDisjunctiveFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).addDisjunctiveFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addDisjunctiveFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.addDisjunctiveRefine = function() {
    return this.addDisjunctiveFacetRefinement.apply(this, arguments);
  };
  
  /**
   * Adds a refinement on a hierarchical facet. It will throw
   * an exception if the facet is not defined or if the facet
   * is already refined.
   *
   * This method resets the current page to 0.
   * @param {string} facet the facet name
   * @param {string} path the hierarchical facet path
   * @return {AlgoliaSearchHelper}
   * @throws Error if the facet is not defined or if the facet is refined
   * @chainable
   * @fires change
   */
  AlgoliaSearchHelper.prototype.addHierarchicalFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).addHierarchicalFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * Adds a an numeric filter to an attribute with the `operator` and `value` provided. If the
   * filter is already set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param  {string} attribute the attribute on which the numeric filter applies
   * @param  {string} operator the operator of the filter
   * @param  {number} value the value of the filter
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.addNumericRefinement = function(attribute, operator, value) {
    this.state = this.state.setPage(0).addNumericRefinement(attribute, operator, value);
    this._change();
    return this;
  };
  
  /**
   * Adds a filter to a faceted attribute with the `value` provided. If the
   * filter is already set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value (will be converted to string)
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.addFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).addFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.addRefine = function() {
    return this.addFacetRefinement.apply(this, arguments);
  };
  
  
  /**
   * Adds a an exclusion filter to a faceted attribute with the `value` provided. If the
   * filter is already set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value (will be converted to string)
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.addFacetExclusion = function(facet, value) {
    this.state = this.state.setPage(0).addExcludeRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetExclusion}
   */
  AlgoliaSearchHelper.prototype.addExclude = function() {
    return this.addFacetExclusion.apply(this, arguments);
  };
  
  /**
   * Adds a tag filter with the `tag` provided. If the
   * filter is already set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param {string} tag the tag to add to the filter
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.addTag = function(tag) {
    this.state = this.state.setPage(0).addTagRefinement(tag);
    this._change();
    return this;
  };
  
  /**
   * Removes an numeric filter to an attribute with the `operator` and `value` provided. If the
   * filter is not set, it doesn't change the filters.
   *
   * Some parameters are optional, triggering different behavior:
   *  - if the value is not provided, then all the numeric value will be removed for the
   *  specified attribute/operator couple.
   *  - if the operator is not provided either, then all the numeric filter on this attribute
   *  will be removed.
   *
   * This method resets the current page to 0.
   * @param  {string} attribute the attribute on which the numeric filter applies
   * @param  {string} [operator] the operator of the filter
   * @param  {number} [value] the value of the filter
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeNumericRefinement = function(attribute, operator, value) {
    this.state = this.state.setPage(0).removeNumericRefinement(attribute, operator, value);
    this._change();
    return this;
  };
  
  /**
   * Removes a disjunctive filter to a faceted attribute with the `value` provided. If the
   * filter is not set, it doesn't change the filters.
   *
   * If the value is omitted, then this method will remove all the filters for the
   * attribute.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} [value] the associated value
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeDisjunctiveFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).removeDisjunctiveFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeDisjunctiveFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.removeDisjunctiveRefine = function() {
    return this.removeDisjunctiveFacetRefinement.apply(this, arguments);
  };
  
  /**
   * Removes the refinement set on a hierarchical facet.
   * @param {string} facet the facet name
   * @return {AlgoliaSearchHelper}
   * @throws Error if the facet is not defined or if the facet is not refined
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeHierarchicalFacetRefinement = function(facet) {
    this.state = this.state.setPage(0).removeHierarchicalFacetRefinement(facet);
    this._change();
  
    return this;
  };
  
  /**
   * Removes a filter to a faceted attribute with the `value` provided. If the
   * filter is not set, it doesn't change the filters.
   *
   * If the value is omitted, then this method will remove all the filters for the
   * attribute.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} [value] the associated value
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).removeFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.removeRefine = function() {
    return this.removeFacetRefinement.apply(this, arguments);
  };
  
  /**
   * Removes an exclusion filter to a faceted attribute with the `value` provided. If the
   * filter is not set, it doesn't change the filters.
   *
   * If the value is omitted, then this method will remove all the filters for the
   * attribute.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} [value] the associated value
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeFacetExclusion = function(facet, value) {
    this.state = this.state.setPage(0).removeExcludeRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetExclusion}
   */
  AlgoliaSearchHelper.prototype.removeExclude = function() {
    return this.removeFacetExclusion.apply(this, arguments);
  };
  
  /**
   * Removes a tag filter with the `tag` provided. If the
   * filter is not set, it doesn't change the filters.
   *
   * This method resets the current page to 0.
   * @param {string} tag tag to remove from the filter
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.removeTag = function(tag) {
    this.state = this.state.setPage(0).removeTagRefinement(tag);
    this._change();
    return this;
  };
  
  /**
   * Adds or removes an exclusion filter to a faceted attribute with the `value` provided. If
   * the value is set then it removes it, otherwise it adds the filter.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.toggleFacetExclusion = function(facet, value) {
    this.state = this.state.setPage(0).toggleExcludeFacetRefinement(facet, value);
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetExclusion}
   */
  AlgoliaSearchHelper.prototype.toggleExclude = function() {
    return this.toggleFacetExclusion.apply(this, arguments);
  };
  
  /**
   * Adds or removes a filter to a faceted attribute with the `value` provided. If
   * the value is set then it removes it, otherwise it adds the filter.
   *
   * This method can be used for conjunctive, disjunctive and hierarchical filters.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value
   * @return {AlgoliaSearchHelper}
   * @throws Error will throw an error if the facet is not declared in the settings of the helper
   * @fires change
   * @chainable
   * @deprecated since version 2.19.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.toggleRefinement = function(facet, value) {
    return this.toggleFacetRefinement(facet, value);
  };
  
  /**
   * Adds or removes a filter to a faceted attribute with the `value` provided. If
   * the value is set then it removes it, otherwise it adds the filter.
   *
   * This method can be used for conjunctive, disjunctive and hierarchical filters.
   *
   * This method resets the current page to 0.
   * @param  {string} facet the facet to refine
   * @param  {string} value the associated value
   * @return {AlgoliaSearchHelper}
   * @throws Error will throw an error if the facet is not declared in the settings of the helper
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.toggleFacetRefinement = function(facet, value) {
    this.state = this.state.setPage(0).toggleFacetRefinement(facet, value);
  
    this._change();
    return this;
  };
  
  /**
   * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement}
   */
  AlgoliaSearchHelper.prototype.toggleRefine = function() {
    return this.toggleFacetRefinement.apply(this, arguments);
  };
  
  /**
   * Adds or removes a tag filter with the `value` provided. If
   * the value is set then it removes it, otherwise it adds the filter.
   *
   * This method resets the current page to 0.
   * @param {string} tag tag to remove or add
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.toggleTag = function(tag) {
    this.state = this.state.setPage(0).toggleTagRefinement(tag);
    this._change();
    return this;
  };
  
  /**
   * Increments the page number by one.
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   * @example
   * helper.setPage(0).nextPage().getPage();
   * // returns 1
   */
  AlgoliaSearchHelper.prototype.nextPage = function() {
    return this.setPage(this.state.page + 1);
  };
  
  /**
   * Decrements the page number by one.
   * @fires change
   * @return {AlgoliaSearchHelper}
   * @chainable
   * @example
   * helper.setPage(1).previousPage().getPage();
   * // returns 0
   */
  AlgoliaSearchHelper.prototype.previousPage = function() {
    return this.setPage(this.state.page - 1);
  };
  
  /**
   * @private
   */
  function setCurrentPage(page) {
    if (page < 0) throw new Error('Page requested below 0.');
  
    this.state = this.state.setPage(page);
    this._change();
    return this;
  }
  
  /**
   * Change the current page
   * @deprecated
   * @param  {number} page The page number
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.setCurrentPage = setCurrentPage;
  
  /**
   * Updates the current page.
   * @function
   * @param  {number} page The page number
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.setPage = setCurrentPage;
  
  /**
   * Updates the name of the index that will be targeted by the query.
   *
   * This method resets the current page to 0.
   * @param {string} name the index name
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.setIndex = function(name) {
    this.state = this.state.setPage(0).setIndex(name);
    this._change();
    return this;
  };
  
  /**
   * Update a parameter of the search. This method reset the page
   *
   * The complete list of parameters is available on the
   * [Algolia website](https://www.algolia.com/doc/rest#query-an-index).
   * The most commonly used parameters have their own [shortcuts](#query-parameters-shortcuts)
   * or benefit from higher-level APIs (all the kind of filters and facets have their own API)
   *
   * This method resets the current page to 0.
   * @param {string} parameter name of the parameter to update
   * @param {any} value new value of the parameter
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   * @example
   * helper.setQueryParameter('hitsPerPage', 20).search();
   */
  AlgoliaSearchHelper.prototype.setQueryParameter = function(parameter, value) {
    var newState = this.state.setPage(0).setQueryParameter(parameter, value);
  
    if (this.state === newState) return this;
  
    this.state = newState;
    this._change();
    return this;
  };
  
  /**
   * Set the whole state (warning: will erase previous state)
   * @param {SearchParameters} newState the whole new state
   * @return {AlgoliaSearchHelper}
   * @fires change
   * @chainable
   */
  AlgoliaSearchHelper.prototype.setState = function(newState) {
    this.state = new SearchParameters(newState);
    this._change();
    return this;
  };
  
  /**
   * Get the current search state stored in the helper. This object is immutable.
   * @param {string[]} [filters] optional filters to retrieve only a subset of the state
   * @return {SearchParameters|object} if filters is specified a plain object is
   * returned containing only the requested fields, otherwise return the unfiltered
   * state
   * @example
   * // Get the complete state as stored in the helper
   * helper.getState();
   * @example
   * // Get a part of the state with all the refinements on attributes and the query
   * helper.getState(['query', 'attribute:category']);
   */
  AlgoliaSearchHelper.prototype.getState = function(filters) {
    if (filters === undefined) return this.state;
    return this.state.filter(filters);
  };
  
  /**
   * DEPRECATED Get part of the state as a query string. By default, the output keys will not
   * be prefixed and will only take the applied refinements and the query.
   * @deprecated
   * @param {object} [options] May contain the following parameters :
   *
   * **filters** : possible values are all the keys of the [SearchParameters](#searchparameters), `index` for
   * the index, all the refinements with `attribute:*` or for some specific attributes with
   * `attribute:theAttribute`
   *
   * **prefix** : prefix in front of the keys
   *
   * **moreAttributes** : more values to be added in the query string. Those values
   *    won't be prefixed.
   * @return {string} the query string
   */
  AlgoliaSearchHelper.prototype.getStateAsQueryString = function getStateAsQueryString(options) {
    var filters = options && options.filters || ['query', 'attribute:*'];
    var partialState = this.getState(filters);
  
    return url.getQueryStringFromState(partialState, options);
  };
  
  /**
   * DEPRECATED Read a query string and return an object containing the state. Use
   * url module.
   * @deprecated
   * @static
   * @param {string} queryString the query string that will be decoded
   * @param {object} options accepted options :
   *   - prefix : the prefix used for the saved attributes, you have to provide the
   *     same that was used for serialization
   * @return {object} partial search parameters object (same properties than in the
   * SearchParameters but not exhaustive)
   * @see {@link url#getStateFromQueryString}
   */
  AlgoliaSearchHelper.getConfigurationFromQueryString = url.getStateFromQueryString;
  
  /**
   * DEPRECATED Retrieve an object of all the properties that are not understandable as helper
   * parameters. Use url module.
   * @deprecated
   * @static
   * @param {string} queryString the query string to read
   * @param {object} options the options
   *   - prefixForParameters : prefix used for the helper configuration keys
   * @return {object} the object containing the parsed configuration that doesn't
   * to the helper
   */
  AlgoliaSearchHelper.getForeignConfigurationInQueryString = url.getUnrecognizedParametersInQueryString;
  
  /**
   * DEPRECATED Overrides part of the state with the properties stored in the provided query
   * string.
   * @deprecated
   * @param {string} queryString the query string containing the informations to url the state
   * @param {object} options optional parameters :
   *  - prefix : prefix used for the algolia parameters
   *  - triggerChange : if set to true the state update will trigger a change event
   */
  AlgoliaSearchHelper.prototype.setStateFromQueryString = function(queryString, options) {
    var triggerChange = options && options.triggerChange || false;
    var configuration = url.getStateFromQueryString(queryString, options);
    var updatedState = this.state.setQueryParameters(configuration);
  
    if (triggerChange) this.setState(updatedState);
    else this.overrideStateWithoutTriggeringChangeEvent(updatedState);
  };
  
  /**
   * Override the current state without triggering a change event.
   * Do not use this method unless you know what you are doing. (see the example
   * for a legit use case)
   * @param {SearchParameters} newState the whole new state
   * @return {AlgoliaSearchHelper}
   * @example
   *  helper.on('change', function(state){
   *    // In this function you might want to find a way to store the state in the url/history
   *    updateYourURL(state)
   *  })
   *  window.onpopstate = function(event){
   *    // This is naive though as you should check if the state is really defined etc.
   *    helper.overrideStateWithoutTriggeringChangeEvent(event.state).search()
   *  }
   * @chainable
   */
  AlgoliaSearchHelper.prototype.overrideStateWithoutTriggeringChangeEvent = function(newState) {
    this.state = new SearchParameters(newState);
    return this;
  };
  
  /**
   * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasRefinements}
   */
  AlgoliaSearchHelper.prototype.isRefined = function(facet, value) {
    if (this.state.isConjunctiveFacet(facet)) {
      return this.state.isFacetRefined(facet, value);
    } else if (this.state.isDisjunctiveFacet(facet)) {
      return this.state.isDisjunctiveFacetRefined(facet, value);
    }
  
    throw new Error(facet +
      ' is not properly defined in this helper configuration' +
      '(use the facets or disjunctiveFacets keys to configure it)');
  };
  
  /**
   * Check if an attribute has any numeric, conjunctive, disjunctive or hierarchical filters.
   * @param {string} attribute the name of the attribute
   * @return {boolean} true if the attribute is filtered by at least one value
   * @example
   * // hasRefinements works with numeric, conjunctive, disjunctive and hierarchical filters
   * helper.hasRefinements('price'); // false
   * helper.addNumericRefinement('price', '>', 100);
   * helper.hasRefinements('price'); // true
   *
   * helper.hasRefinements('color'); // false
   * helper.addFacetRefinement('color', 'blue');
   * helper.hasRefinements('color'); // true
   *
   * helper.hasRefinements('material'); // false
   * helper.addDisjunctiveFacetRefinement('material', 'plastic');
   * helper.hasRefinements('material'); // true
   *
   * helper.hasRefinements('categories'); // false
   * helper.toggleFacetRefinement('categories', 'kitchen > knife');
   * helper.hasRefinements('categories'); // true
   *
   */
  AlgoliaSearchHelper.prototype.hasRefinements = function(attribute) {
    if (!isEmpty(this.state.getNumericRefinements(attribute))) {
      return true;
    } else if (this.state.isConjunctiveFacet(attribute)) {
      return this.state.isFacetRefined(attribute);
    } else if (this.state.isDisjunctiveFacet(attribute)) {
      return this.state.isDisjunctiveFacetRefined(attribute);
    } else if (this.state.isHierarchicalFacet(attribute)) {
      return this.state.isHierarchicalFacetRefined(attribute);
    }
  
    // there's currently no way to know that the user did call `addNumericRefinement` at some point
    // thus we cannot distinguish if there once was a numeric refinement that was cleared
    // so we will return false in every other situations to be consistent
    // while what we should do here is throw because we did not find the attribute in any type
    // of refinement
    return false;
  };
  
  /**
   * Check if a value is excluded for a specific faceted attribute. If the value
   * is omitted then the function checks if there is any excluding refinements.
   *
   * @param  {string}  facet name of the attribute for used for faceting
   * @param  {string}  [value] optional value. If passed will test that this value
     * is filtering the given facet.
   * @return {boolean} true if refined
   * @example
   * helper.isExcludeRefined('color'); // false
   * helper.isExcludeRefined('color', 'blue') // false
   * helper.isExcludeRefined('color', 'red') // false
   *
   * helper.addFacetExclusion('color', 'red');
   *
   * helper.isExcludeRefined('color'); // true
   * helper.isExcludeRefined('color', 'blue') // false
   * helper.isExcludeRefined('color', 'red') // true
   */
  AlgoliaSearchHelper.prototype.isExcluded = function(facet, value) {
    return this.state.isExcludeRefined(facet, value);
  };
  
  /**
   * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasRefinements}
   */
  AlgoliaSearchHelper.prototype.isDisjunctiveRefined = function(facet, value) {
    return this.state.isDisjunctiveFacetRefined(facet, value);
  };
  
  /**
   * Check if the string is a currently filtering tag.
   * @param {string} tag tag to check
   * @return {boolean}
   */
  AlgoliaSearchHelper.prototype.hasTag = function(tag) {
    return this.state.isTagRefined(tag);
  };
  
  /**
   * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasTag}
   */
  AlgoliaSearchHelper.prototype.isTagRefined = function() {
    return this.hasTagRefinements.apply(this, arguments);
  };
  
  
  /**
   * Get the name of the currently used index.
   * @return {string}
   * @example
   * helper.setIndex('highestPrice_products').getIndex();
   * // returns 'highestPrice_products'
   */
  AlgoliaSearchHelper.prototype.getIndex = function() {
    return this.state.index;
  };
  
  function getCurrentPage() {
    return this.state.page;
  }
  
  /**
   * Get the currently selected page
   * @deprecated
   * @return {number} the current page
   */
  AlgoliaSearchHelper.prototype.getCurrentPage = getCurrentPage;
  /**
   * Get the currently selected page
   * @function
   * @return {number} the current page
   */
  AlgoliaSearchHelper.prototype.getPage = getCurrentPage;
  
  /**
   * Get all the tags currently set to filters the results.
   *
   * @return {string[]} The list of tags currently set.
   */
  AlgoliaSearchHelper.prototype.getTags = function() {
    return this.state.tagRefinements;
  };
  
  /**
   * Get a parameter of the search by its name. It is possible that a parameter is directly
   * defined in the index dashboard, but it will be undefined using this method.
   *
   * The complete list of parameters is
   * available on the
   * [Algolia website](https://www.algolia.com/doc/rest#query-an-index).
   * The most commonly used parameters have their own [shortcuts](#query-parameters-shortcuts)
   * or benefit from higher-level APIs (all the kind of filters have their own API)
   * @param {string} parameterName the parameter name
   * @return {any} the parameter value
   * @example
   * var hitsPerPage = helper.getQueryParameter('hitsPerPage');
   */
  AlgoliaSearchHelper.prototype.getQueryParameter = function(parameterName) {
    return this.state.getQueryParameter(parameterName);
  };
  
  /**
   * Get the list of refinements for a given attribute. This method works with
   * conjunctive, disjunctive, excluding and numerical filters.
   *
   * See also SearchResults#getRefinements
   *
   * @param {string} facetName attribute name used for faceting
   * @return {Array.<FacetRefinement|NumericRefinement>} All Refinement are objects that contain a value, and
   * a type. Numeric also contains an operator.
   * @example
   * helper.addNumericRefinement('price', '>', 100);
   * helper.getRefinements('price');
   * // [
   * //   {
   * //     "value": [
   * //       100
   * //     ],
   * //     "operator": ">",
   * //     "type": "numeric"
   * //   }
   * // ]
   * @example
   * helper.addFacetRefinement('color', 'blue');
   * helper.addFacetExclusion('color', 'red');
   * helper.getRefinements('color');
   * // [
   * //   {
   * //     "value": "blue",
   * //     "type": "conjunctive"
   * //   },
   * //   {
   * //     "value": "red",
   * //     "type": "exclude"
   * //   }
   * // ]
   * @example
   * helper.addDisjunctiveFacetRefinement('material', 'plastic');
   * // [
   * //   {
   * //     "value": "plastic",
   * //     "type": "disjunctive"
   * //   }
   * // ]
   */
  AlgoliaSearchHelper.prototype.getRefinements = function(facetName) {
    var refinements = [];
  
    if (this.state.isConjunctiveFacet(facetName)) {
      var conjRefinements = this.state.getConjunctiveRefinements(facetName);
  
      forEach(conjRefinements, function(r) {
        refinements.push({
          value: r,
          type: 'conjunctive'
        });
      });
  
      var excludeRefinements = this.state.getExcludeRefinements(facetName);
  
      forEach(excludeRefinements, function(r) {
        refinements.push({
          value: r,
          type: 'exclude'
        });
      });
    } else if (this.state.isDisjunctiveFacet(facetName)) {
      var disjRefinements = this.state.getDisjunctiveRefinements(facetName);
  
      forEach(disjRefinements, function(r) {
        refinements.push({
          value: r,
          type: 'disjunctive'
        });
      });
    }
  
    var numericRefinements = this.state.getNumericRefinements(facetName);
  
    forEach(numericRefinements, function(value, operator) {
      refinements.push({
        value: value,
        operator: operator,
        type: 'numeric'
      });
    });
  
    return refinements;
  };
  
  /**
   * Return the current refinement for the (attribute, operator)
   * @param {string} attribute of the record
   * @param {string} operator applied
   * @return {number} value of the refinement
   */
  AlgoliaSearchHelper.prototype.getNumericRefinement = function(attribute, operator) {
    return this.state.getNumericRefinement(attribute, operator);
  };
  
  /**
   * Get the current breadcrumb for a hierarchical facet, as an array
   * @param  {string} facetName Hierarchical facet name
   * @return {array.<string>} the path as an array of string
   */
  AlgoliaSearchHelper.prototype.getHierarchicalFacetBreadcrumb = function(facetName) {
    return this.state.getHierarchicalFacetBreadcrumb(facetName);
  };
  
  // /////////// PRIVATE
  
  /**
   * Perform the underlying queries
   * @private
   * @return {undefined}
   * @fires search
   * @fires result
   * @fires error
   */
  AlgoliaSearchHelper.prototype._search = function() {
    var state = this.state;
    var mainQueries = requestBuilder._getQueries(state.index, state);
  
    var states = [{
      state: state,
      queriesCount: mainQueries.length,
      helper: this
    }];
  
    this.emit('search', state, this.lastResults);
  
    var derivedQueries = map(this.derivedHelpers, function(derivedHelper) {
      var derivedState = derivedHelper.getModifiedState(state);
      var queries = requestBuilder._getQueries(derivedState.index, derivedState);
      states.push({
        state: derivedState,
        queriesCount: queries.length,
        helper: derivedHelper
      });
      derivedHelper.emit('search', derivedState, derivedHelper.lastResults);
      return queries;
    });
  
    var queries = mainQueries.concat(flatten(derivedQueries));
    var queryId = this._queryId++;
  
    this._currentNbQueries++;
  
    this.client.search(queries, this._dispatchAlgoliaResponse.bind(this, states, queryId));
  };
  
  /**
   * Transform the responses as sent by the server and transform them into a user
   * usable object that merge the results of all the batch requests. It will dispatch
   * over the different helper + derived helpers (when there are some).
   * @private
   * @param {array.<{SearchParameters, AlgoliaQueries, AlgoliaSearchHelper}>}
   *  state state used for to generate the request
   * @param {number} queryId id of the current request
   * @param {Error} err error if any, null otherwise
   * @param {object} content content of the response
   * @return {undefined}
   */
  AlgoliaSearchHelper.prototype._dispatchAlgoliaResponse = function(states, queryId, err, content) {
    // FIXME remove the number of outdated queries discarded instead of just one
  
    if (queryId < this._lastQueryIdReceived) {
      // Outdated answer
      return;
    }
  
    this._currentNbQueries -= (queryId - this._lastQueryIdReceived);
    if (this._currentNbQueries === 0) this.emit('searchQueueEmpty');
  
    this._lastQueryIdReceived = queryId;
  
    if (err) {
      this.emit('error', err);
      return;
    }
  
    var results = content.results;
    forEach(states, function(s) {
      var state = s.state;
      var queriesCount = s.queriesCount;
      var helper = s.helper;
  
      var specificResults = results.splice(0, queriesCount);
  
      var formattedResponse = helper.lastResults = new SearchResults(state, specificResults);
      helper.emit('result', formattedResponse, state);
    });
  };
  
  AlgoliaSearchHelper.prototype.containsRefinement = function(query, facetFilters, numericFilters, tagFilters) {
    return query ||
      facetFilters.length !== 0 ||
      numericFilters.length !== 0 ||
      tagFilters.length !== 0;
  };
  
  /**
   * Test if there are some disjunctive refinements on the facet
   * @private
   * @param {string} facet the attribute to test
   * @return {boolean}
   */
  AlgoliaSearchHelper.prototype._hasDisjunctiveRefinements = function(facet) {
    return this.state.disjunctiveRefinements[facet] &&
      this.state.disjunctiveRefinements[facet].length > 0;
  };
  
  AlgoliaSearchHelper.prototype._change = function() {
    this.emit('change', this.state, this.lastResults);
  };
  
  /**
   * Clears the cache of the underlying Algolia client.
   * @return {AlgoliaSearchHelper}
   */
  AlgoliaSearchHelper.prototype.clearCache = function() {
    this.client.clearCache();
    return this;
  };
  
  /**
   * Updates the internal client instance. If the reference of the clients
   * are equal then no update is actually done.
   * @param  {AlgoliaSearch} newClient an AlgoliaSearch client
   * @return {AlgoliaSearchHelper}
   */
  AlgoliaSearchHelper.prototype.setClient = function(newClient) {
    if (this.client === newClient) return this;
  
    if (newClient.addAlgoliaAgent && !doesClientAgentContainsHelper(newClient)) newClient.addAlgoliaAgent('JS Helper ' + version);
    this.client = newClient;
  
    return this;
  };
  
  /**
   * Gets the instance of the currently used client.
   * @return {AlgoliaSearch}
   */
  AlgoliaSearchHelper.prototype.getClient = function() {
    return this.client;
  };
  
  /**
   * Creates an derived instance of the Helper. A derived helper
   * is a way to request other indices synchronised with the lifecycle
   * of the main Helper. This mechanism uses the multiqueries feature
   * of Algolia to aggregate all the requests in a single network call.
   *
   * This method takes a function that is used to create a new SearchParameter
   * that will be used to create requests to Algolia. Those new requests
   * are created just before the `search` event. The signature of the function
   * is `SearchParameters -> SearchParameters`.
   *
   * This method returns a new DerivedHelper which is an EventEmitter
   * that fires the same `search`, `result` and `error` events. Those
   * events, however, will receive data specific to this DerivedHelper
   * and the SearchParameters that is returned by the call of the
   * parameter function.
   * @param {function} fn SearchParameters -> SearchParameters
   * @return {DerivedHelper}
   */
  AlgoliaSearchHelper.prototype.derive = function(fn) {
    var derivedHelper = new DerivedHelper(this, fn);
    this.derivedHelpers.push(derivedHelper);
    return derivedHelper;
  };
  
  /**
   * This method detaches a derived Helper from the main one. Prefer using the one from the
   * derived helper itself, to remove the event listeners too.
   * @private
   * @return {undefined}
   * @throws Error
   */
  AlgoliaSearchHelper.prototype.detachDerivedHelper = function(derivedHelper) {
    var pos = this.derivedHelpers.indexOf(derivedHelper);
    if (pos === -1) throw new Error('Derived helper already detached');
    this.derivedHelpers.splice(pos, 1);
  };
  
  /**
   * This method returns true if there is currently at least one on-going search.
   * @return {boolean} true if there is a search pending
   */
  AlgoliaSearchHelper.prototype.hasPendingRequests = function() {
    return this._currentNbQueries > 0;
  };
  
  /**
   * @typedef AlgoliaSearchHelper.NumericRefinement
   * @type {object}
   * @property {number[]} value the numbers that are used for filtering this attribute with
   * the operator specified.
   * @property {string} operator the faceting data: value, number of entries
   * @property {string} type will be 'numeric'
   */
  
  /**
   * @typedef AlgoliaSearchHelper.FacetRefinement
   * @type {object}
   * @property {string} value the string use to filter the attribute
   * @property {string} type the type of filter: 'conjunctive', 'disjunctive', 'exclude'
   */
  
  
  /*
   * This function tests if the _ua parameter of the client
   * already contains the JS Helper UA
   */
  function doesClientAgentContainsHelper(client) {
    // this relies on JS Client internal variable, this might break if implementation changes
    var currentAgent = client._ua;
    return !currentAgent ? false :
      currentAgent.indexOf('JS Helper') !== -1;
  }
  
  module.exports = AlgoliaSearchHelper;
  
  
  /***/ }),
  /* 249 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12),
      baseIntersection = __webpack_require__(250),
      baseRest = __webpack_require__(25),
      castArrayLikeObject = __webpack_require__(251);
  
  /**
   * Creates an array of unique values that are included in all given arrays
   * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * for equality comparisons. The order and references of result values are
   * determined by the first array.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {...Array} [arrays] The arrays to inspect.
   * @returns {Array} Returns the new array of intersecting values.
   * @example
   *
   * _.intersection([2, 1], [2, 3]);
   * // => [2]
   */
  var intersection = baseRest(function(arrays) {
    var mapped = arrayMap(arrays, castArrayLikeObject);
    return (mapped.length && mapped[0] === arrays[0])
      ? baseIntersection(mapped)
      : [];
  });
  
  module.exports = intersection;
  
  
  /***/ }),
  /* 250 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var SetCache = __webpack_require__(59),
      arrayIncludes = __webpack_require__(92),
      arrayIncludesWith = __webpack_require__(164),
      arrayMap = __webpack_require__(12),
      baseUnary = __webpack_require__(42),
      cacheHas = __webpack_require__(60);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMin = Math.min;
  
  /**
   * The base implementation of methods like `_.intersection`, without support
   * for iteratee shorthands, that accepts an array of arrays to inspect.
   *
   * @private
   * @param {Array} arrays The arrays to inspect.
   * @param {Function} [iteratee] The iteratee invoked per element.
   * @param {Function} [comparator] The comparator invoked per element.
   * @returns {Array} Returns the new array of shared values.
   */
  function baseIntersection(arrays, iteratee, comparator) {
    var includes = comparator ? arrayIncludesWith : arrayIncludes,
        length = arrays[0].length,
        othLength = arrays.length,
        othIndex = othLength,
        caches = Array(othLength),
        maxLength = Infinity,
        result = [];
  
    while (othIndex--) {
      var array = arrays[othIndex];
      if (othIndex && iteratee) {
        array = arrayMap(array, baseUnary(iteratee));
      }
      maxLength = nativeMin(array.length, maxLength);
      caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
        ? new SetCache(othIndex && array)
        : undefined;
    }
    array = arrays[0];
  
    var index = -1,
        seen = caches[0];
  
    outer:
    while (++index < length && result.length < maxLength) {
      var value = array[index],
          computed = iteratee ? iteratee(value) : value;
  
      value = (comparator || value !== 0) ? value : 0;
      if (!(seen
            ? cacheHas(seen, computed)
            : includes(result, computed, comparator)
          )) {
        othIndex = othLength;
        while (--othIndex) {
          var cache = caches[othIndex];
          if (!(cache
                ? cacheHas(cache, computed)
                : includes(arrays[othIndex], computed, comparator))
              ) {
            continue outer;
          }
        }
        if (seen) {
          seen.push(computed);
        }
        result.push(value);
      }
    }
    return result;
  }
  
  module.exports = baseIntersection;
  
  
  /***/ }),
  /* 251 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isArrayLikeObject = __webpack_require__(94);
  
  /**
   * Casts `value` to an empty array if it's not an array like object.
   *
   * @private
   * @param {*} value The value to inspect.
   * @returns {Array|Object} Returns the cast array-like object.
   */
  function castArrayLikeObject(value) {
    return isArrayLikeObject(value) ? value : [];
  }
  
  module.exports = castArrayLikeObject;
  
  
  /***/ }),
  /* 252 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseForOwn = __webpack_require__(48),
      castFunction = __webpack_require__(179);
  
  /**
   * Iterates over own enumerable string keyed properties of an object and
   * invokes `iteratee` for each property. The iteratee is invoked with three
   * arguments: (value, key, object). Iteratee functions may exit iteration
   * early by explicitly returning `false`.
   *
   * @static
   * @memberOf _
   * @since 0.3.0
   * @category Object
   * @param {Object} object The object to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @returns {Object} Returns `object`.
   * @see _.forOwnRight
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.forOwn(new Foo, function(value, key) {
   *   console.log(key);
   * });
   * // => Logs 'a' then 'b' (iteration order is not guaranteed).
   */
  function forOwn(object, iteratee) {
    return object && baseForOwn(object, castFunction(iteratee));
  }
  
  module.exports = forOwn;
  
  
  /***/ }),
  /* 253 */
  /***/ (function(module, exports) {
  
  /**
   * Creates a base function for methods like `_.forIn` and `_.forOwn`.
   *
   * @private
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new base function.
   */
  function createBaseFor(fromRight) {
    return function(object, iteratee, keysFunc) {
      var index = -1,
          iterable = Object(object),
          props = keysFunc(object),
          length = props.length;
  
      while (length--) {
        var key = props[fromRight ? length : ++index];
        if (iteratee(iterable[key], key, iterable) === false) {
          break;
        }
      }
      return object;
    };
  }
  
  module.exports = createBaseFor;
  
  
  /***/ }),
  /* 254 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isArrayLike = __webpack_require__(11);
  
  /**
   * Creates a `baseEach` or `baseEachRight` function.
   *
   * @private
   * @param {Function} eachFunc The function to iterate over a collection.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new base function.
   */
  function createBaseEach(eachFunc, fromRight) {
    return function(collection, iteratee) {
      if (collection == null) {
        return collection;
      }
      if (!isArrayLike(collection)) {
        return eachFunc(collection, iteratee);
      }
      var length = collection.length,
          index = fromRight ? length : -1,
          iterable = Object(collection);
  
      while ((fromRight ? index-- : ++index < length)) {
        if (iteratee(iterable[index], index, iterable) === false) {
          break;
        }
      }
      return collection;
    };
  }
  
  module.exports = createBaseEach;
  
  
  /***/ }),
  /* 255 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseEach = __webpack_require__(73);
  
  /**
   * The base implementation of `_.filter` without support for iteratee shorthands.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {Array} Returns the new filtered array.
   */
  function baseFilter(collection, predicate) {
    var result = [];
    baseEach(collection, function(value, index, collection) {
      if (predicate(value, index, collection)) {
        result.push(value);
      }
    });
    return result;
  }
  
  module.exports = baseFilter;
  
  
  /***/ }),
  /* 256 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsMatch = __webpack_require__(257),
      getMatchData = __webpack_require__(258),
      matchesStrictComparable = __webpack_require__(181);
  
  /**
   * The base implementation of `_.matches` which doesn't clone `source`.
   *
   * @private
   * @param {Object} source The object of property values to match.
   * @returns {Function} Returns the new spec function.
   */
  function baseMatches(source) {
    var matchData = getMatchData(source);
    if (matchData.length == 1 && matchData[0][2]) {
      return matchesStrictComparable(matchData[0][0], matchData[0][1]);
    }
    return function(object) {
      return object === source || baseIsMatch(object, source, matchData);
    };
  }
  
  module.exports = baseMatches;
  
  
  /***/ }),
  /* 257 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Stack = __webpack_require__(38),
      baseIsEqual = __webpack_require__(58);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;
  
  /**
   * The base implementation of `_.isMatch` without support for iteratee shorthands.
   *
   * @private
   * @param {Object} object The object to inspect.
   * @param {Object} source The object of property values to match.
   * @param {Array} matchData The property names, values, and compare flags to match.
   * @param {Function} [customizer] The function to customize comparisons.
   * @returns {boolean} Returns `true` if `object` is a match, else `false`.
   */
  function baseIsMatch(object, source, matchData, customizer) {
    var index = matchData.length,
        length = index,
        noCustomizer = !customizer;
  
    if (object == null) {
      return !length;
    }
    object = Object(object);
    while (index--) {
      var data = matchData[index];
      if ((noCustomizer && data[2])
            ? data[1] !== object[data[0]]
            : !(data[0] in object)
          ) {
        return false;
      }
    }
    while (++index < length) {
      data = matchData[index];
      var key = data[0],
          objValue = object[key],
          srcValue = data[1];
  
      if (noCustomizer && data[2]) {
        if (objValue === undefined && !(key in object)) {
          return false;
        }
      } else {
        var stack = new Stack;
        if (customizer) {
          var result = customizer(objValue, srcValue, key, object, source, stack);
        }
        if (!(result === undefined
              ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
              : result
            )) {
          return false;
        }
      }
    }
    return true;
  }
  
  module.exports = baseIsMatch;
  
  
  /***/ }),
  /* 258 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isStrictComparable = __webpack_require__(180),
      keys = __webpack_require__(9);
  
  /**
   * Gets the property names, values, and compare flags of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the match data of `object`.
   */
  function getMatchData(object) {
    var result = keys(object),
        length = result.length;
  
    while (length--) {
      var key = result[length],
          value = object[key];
  
      result[length] = [key, value, isStrictComparable(value)];
    }
    return result;
  }
  
  module.exports = getMatchData;
  
  
  /***/ }),
  /* 259 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIsEqual = __webpack_require__(58),
      get = __webpack_require__(72),
      hasIn = __webpack_require__(182),
      isKey = __webpack_require__(63),
      isStrictComparable = __webpack_require__(180),
      matchesStrictComparable = __webpack_require__(181),
      toKey = __webpack_require__(24);
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;
  
  /**
   * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
   *
   * @private
   * @param {string} path The path of the property to get.
   * @param {*} srcValue The value to match.
   * @returns {Function} Returns the new spec function.
   */
  function baseMatchesProperty(path, srcValue) {
    if (isKey(path) && isStrictComparable(srcValue)) {
      return matchesStrictComparable(toKey(path), srcValue);
    }
    return function(object) {
      var objValue = get(object, path);
      return (objValue === undefined && objValue === srcValue)
        ? hasIn(object, path)
        : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
    };
  }
  
  module.exports = baseMatchesProperty;
  
  
  /***/ }),
  /* 260 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.hasIn` without support for deep paths.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {Array|string} key The key to check.
   * @returns {boolean} Returns `true` if `key` exists, else `false`.
   */
  function baseHasIn(object, key) {
    return object != null && key in Object(object);
  }
  
  module.exports = baseHasIn;
  
  
  /***/ }),
  /* 261 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseProperty = __webpack_require__(262),
      basePropertyDeep = __webpack_require__(263),
      isKey = __webpack_require__(63),
      toKey = __webpack_require__(24);
  
  /**
   * Creates a function that returns the value at `path` of a given object.
   *
   * @static
   * @memberOf _
   * @since 2.4.0
   * @category Util
   * @param {Array|string} path The path of the property to get.
   * @returns {Function} Returns the new accessor function.
   * @example
   *
   * var objects = [
   *   { 'a': { 'b': 2 } },
   *   { 'a': { 'b': 1 } }
   * ];
   *
   * _.map(objects, _.property('a.b'));
   * // => [2, 1]
   *
   * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
   * // => [1, 2]
   */
  function property(path) {
    return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
  }
  
  module.exports = property;
  
  
  /***/ }),
  /* 262 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new accessor function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  module.exports = baseProperty;
  
  
  /***/ }),
  /* 263 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseGet = __webpack_require__(71);
  
  /**
   * A specialized version of `baseProperty` which supports deep paths.
   *
   * @private
   * @param {Array|string} path The path of the property to get.
   * @returns {Function} Returns the new accessor function.
   */
  function basePropertyDeep(path) {
    return function(object) {
      return baseGet(object, path);
    };
  }
  
  module.exports = basePropertyDeep;
  
  
  /***/ }),
  /* 264 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.reduce` and `_.reduceRight`, without support
   * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} accumulator The initial value.
   * @param {boolean} initAccum Specify using the first or last element of
   *  `collection` as the initial value.
   * @param {Function} eachFunc The function to iterate over `collection`.
   * @returns {*} Returns the accumulated value.
   */
  function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
    eachFunc(collection, function(value, index, collection) {
      accumulator = initAccum
        ? (initAccum = false, value)
        : iteratee(accumulator, value, index, collection);
    });
    return accumulator;
  }
  
  module.exports = baseReduce;
  
  
  /***/ }),
  /* 265 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isObject = __webpack_require__(6),
      isSymbol = __webpack_require__(23);
  
  /** Used as references for various `Number` constants. */
  var NAN = 0 / 0;
  
  /** Used to match leading and trailing whitespace. */
  var reTrim = /^\s+|\s+$/g;
  
  /** Used to detect bad signed hexadecimal string values. */
  var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
  
  /** Used to detect binary string values. */
  var reIsBinary = /^0b[01]+$/i;
  
  /** Used to detect octal string values. */
  var reIsOctal = /^0o[0-7]+$/i;
  
  /** Built-in method references without a dependency on `root`. */
  var freeParseInt = parseInt;
  
  /**
   * Converts `value` to a number.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to process.
   * @returns {number} Returns the number.
   * @example
   *
   * _.toNumber(3.2);
   * // => 3.2
   *
   * _.toNumber(Number.MIN_VALUE);
   * // => 5e-324
   *
   * _.toNumber(Infinity);
   * // => Infinity
   *
   * _.toNumber('3.2');
   * // => 3.2
   */
  function toNumber(value) {
    if (typeof value == 'number') {
      return value;
    }
    if (isSymbol(value)) {
      return NAN;
    }
    if (isObject(value)) {
      var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
      value = isObject(other) ? (other + '') : other;
    }
    if (typeof value != 'string') {
      return value === 0 ? value : +value;
    }
    value = value.replace(reTrim, '');
    var isBinary = reIsBinary.test(value);
    return (isBinary || reIsOctal.test(value))
      ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
      : (reIsBadHex.test(value) ? NAN : +value);
  }
  
  module.exports = toNumber;
  
  
  /***/ }),
  /* 266 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIteratee = __webpack_require__(13),
      isArrayLike = __webpack_require__(11),
      keys = __webpack_require__(9);
  
  /**
   * Creates a `_.find` or `_.findLast` function.
   *
   * @private
   * @param {Function} findIndexFunc The function to find the collection index.
   * @returns {Function} Returns the new find function.
   */
  function createFind(findIndexFunc) {
    return function(collection, predicate, fromIndex) {
      var iterable = Object(collection);
      if (!isArrayLike(collection)) {
        var iteratee = baseIteratee(predicate, 3);
        collection = keys(collection);
        predicate = function(key) { return iteratee(iterable[key], key, iterable); };
      }
      var index = findIndexFunc(collection, predicate, fromIndex);
      return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
    };
  }
  
  module.exports = createFind;
  
  
  /***/ }),
  /* 267 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseSlice = __webpack_require__(175);
  
  /**
   * Casts `array` to a slice if it's needed.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {number} start The start position.
   * @param {number} [end=array.length] The end position.
   * @returns {Array} Returns the cast slice.
   */
  function castSlice(array, start, end) {
    var length = array.length;
    end = end === undefined ? length : end;
    return (!start && end >= length) ? array : baseSlice(array, start, end);
  }
  
  module.exports = castSlice;
  
  
  /***/ }),
  /* 268 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIndexOf = __webpack_require__(44);
  
  /**
   * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
   * that is not found in the character symbols.
   *
   * @private
   * @param {Array} strSymbols The string symbols to inspect.
   * @param {Array} chrSymbols The character symbols to find.
   * @returns {number} Returns the index of the last unmatched string symbol.
   */
  function charsEndIndex(strSymbols, chrSymbols) {
    var index = strSymbols.length;
  
    while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
    return index;
  }
  
  module.exports = charsEndIndex;
  
  
  /***/ }),
  /* 269 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIndexOf = __webpack_require__(44);
  
  /**
   * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
   * that is not found in the character symbols.
   *
   * @private
   * @param {Array} strSymbols The string symbols to inspect.
   * @param {Array} chrSymbols The character symbols to find.
   * @returns {number} Returns the index of the first unmatched string symbol.
   */
  function charsStartIndex(strSymbols, chrSymbols) {
    var index = -1,
        length = strSymbols.length;
  
    while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
    return index;
  }
  
  module.exports = charsStartIndex;
  
  
  /***/ }),
  /* 270 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var asciiToArray = __webpack_require__(271),
      hasUnicode = __webpack_require__(272),
      unicodeToArray = __webpack_require__(273);
  
  /**
   * Converts `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function stringToArray(string) {
    return hasUnicode(string)
      ? unicodeToArray(string)
      : asciiToArray(string);
  }
  
  module.exports = stringToArray;
  
  
  /***/ }),
  /* 271 */
  /***/ (function(module, exports) {
  
  /**
   * Converts an ASCII `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function asciiToArray(string) {
    return string.split('');
  }
  
  module.exports = asciiToArray;
  
  
  /***/ }),
  /* 272 */
  /***/ (function(module, exports) {
  
  /** Used to compose unicode character classes. */
  var rsAstralRange = '\\ud800-\\udfff',
      rsComboMarksRange = '\\u0300-\\u036f',
      reComboHalfMarksRange = '\\ufe20-\\ufe2f',
      rsComboSymbolsRange = '\\u20d0-\\u20ff',
      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
      rsVarRange = '\\ufe0e\\ufe0f';
  
  /** Used to compose unicode capture groups. */
  var rsZWJ = '\\u200d';
  
  /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
  var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');
  
  /**
   * Checks if `string` contains Unicode symbols.
   *
   * @private
   * @param {string} string The string to inspect.
   * @returns {boolean} Returns `true` if a symbol is found, else `false`.
   */
  function hasUnicode(string) {
    return reHasUnicode.test(string);
  }
  
  module.exports = hasUnicode;
  
  
  /***/ }),
  /* 273 */
  /***/ (function(module, exports) {
  
  /** Used to compose unicode character classes. */
  var rsAstralRange = '\\ud800-\\udfff',
      rsComboMarksRange = '\\u0300-\\u036f',
      reComboHalfMarksRange = '\\ufe20-\\ufe2f',
      rsComboSymbolsRange = '\\u20d0-\\u20ff',
      rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
      rsVarRange = '\\ufe0e\\ufe0f';
  
  /** Used to compose unicode capture groups. */
  var rsAstral = '[' + rsAstralRange + ']',
      rsCombo = '[' + rsComboRange + ']',
      rsFitz = '\\ud83c[\\udffb-\\udfff]',
      rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
      rsNonAstral = '[^' + rsAstralRange + ']',
      rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
      rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
      rsZWJ = '\\u200d';
  
  /** Used to compose unicode regexes. */
  var reOptMod = rsModifier + '?',
      rsOptVar = '[' + rsVarRange + ']?',
      rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
      rsSeq = rsOptVar + reOptMod + rsOptJoin,
      rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
  
  /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
  var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
  
  /**
   * Converts a Unicode `string` to an array.
   *
   * @private
   * @param {string} string The string to convert.
   * @returns {Array} Returns the converted array.
   */
  function unicodeToArray(string) {
    return string.match(reUnicode) || [];
  }
  
  module.exports = unicodeToArray;
  
  
  /***/ }),
  /* 274 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      createAssigner = __webpack_require__(188),
      keysIn = __webpack_require__(47);
  
  /**
   * This method is like `_.assignIn` except that it accepts `customizer`
   * which is invoked to produce the assigned values. If `customizer` returns
   * `undefined`, assignment is handled by the method instead. The `customizer`
   * is invoked with five arguments: (objValue, srcValue, key, object, source).
   *
   * **Note:** This method mutates `object`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @alias extendWith
   * @category Object
   * @param {Object} object The destination object.
   * @param {...Object} sources The source objects.
   * @param {Function} [customizer] The function to customize assigned values.
   * @returns {Object} Returns `object`.
   * @see _.assignWith
   * @example
   *
   * function customizer(objValue, srcValue) {
   *   return _.isUndefined(objValue) ? srcValue : objValue;
   * }
   *
   * var defaults = _.partialRight(_.assignInWith, customizer);
   *
   * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
   * // => { 'a': 1, 'b': 2 }
   */
  var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
    copyObject(source, keysIn(source), object, customizer);
  });
  
  module.exports = assignInWith;
  
  
  /***/ }),
  /* 275 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var eq = __webpack_require__(18);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
   * of source objects to the destination object for all destination properties
   * that resolve to `undefined`.
   *
   * @private
   * @param {*} objValue The destination value.
   * @param {*} srcValue The source value.
   * @param {string} key The key of the property to assign.
   * @param {Object} object The parent object of `objValue`.
   * @returns {*} Returns the value to assign.
   */
  function customDefaultsAssignIn(objValue, srcValue, key, object) {
    if (objValue === undefined ||
        (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
      return srcValue;
    }
    return objValue;
  }
  
  module.exports = customDefaultsAssignIn;
  
  
  /***/ }),
  /* 276 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var Stack = __webpack_require__(38),
      assignMergeValue = __webpack_require__(189),
      baseFor = __webpack_require__(178),
      baseMergeDeep = __webpack_require__(277),
      isObject = __webpack_require__(6),
      keysIn = __webpack_require__(47);
  
  /**
   * The base implementation of `_.merge` without support for multiple sources.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @param {number} srcIndex The index of `source`.
   * @param {Function} [customizer] The function to customize merged values.
   * @param {Object} [stack] Tracks traversed source values and their merged
   *  counterparts.
   */
  function baseMerge(object, source, srcIndex, customizer, stack) {
    if (object === source) {
      return;
    }
    baseFor(source, function(srcValue, key) {
      if (isObject(srcValue)) {
        stack || (stack = new Stack);
        baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
      }
      else {
        var newValue = customizer
          ? customizer(object[key], srcValue, (key + ''), object, source, stack)
          : undefined;
  
        if (newValue === undefined) {
          newValue = srcValue;
        }
        assignMergeValue(object, key, newValue);
      }
    }, keysIn);
  }
  
  module.exports = baseMerge;
  
  
  /***/ }),
  /* 277 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assignMergeValue = __webpack_require__(189),
      cloneBuffer = __webpack_require__(170),
      cloneTypedArray = __webpack_require__(172),
      copyArray = __webpack_require__(69),
      initCloneObject = __webpack_require__(173),
      isArguments = __webpack_require__(20),
      isArray = __webpack_require__(0),
      isArrayLikeObject = __webpack_require__(94),
      isBuffer = __webpack_require__(21),
      isFunction = __webpack_require__(19),
      isObject = __webpack_require__(6),
      isPlainObject = __webpack_require__(43),
      isTypedArray = __webpack_require__(33),
      toPlainObject = __webpack_require__(278);
  
  /**
   * A specialized version of `baseMerge` for arrays and objects which performs
   * deep merges and tracks traversed objects enabling objects with circular
   * references to be merged.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @param {string} key The key of the value to merge.
   * @param {number} srcIndex The index of `source`.
   * @param {Function} mergeFunc The function to merge values.
   * @param {Function} [customizer] The function to customize assigned values.
   * @param {Object} [stack] Tracks traversed source values and their merged
   *  counterparts.
   */
  function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
    var objValue = object[key],
        srcValue = source[key],
        stacked = stack.get(srcValue);
  
    if (stacked) {
      assignMergeValue(object, key, stacked);
      return;
    }
    var newValue = customizer
      ? customizer(objValue, srcValue, (key + ''), object, source, stack)
      : undefined;
  
    var isCommon = newValue === undefined;
  
    if (isCommon) {
      var isArr = isArray(srcValue),
          isBuff = !isArr && isBuffer(srcValue),
          isTyped = !isArr && !isBuff && isTypedArray(srcValue);
  
      newValue = srcValue;
      if (isArr || isBuff || isTyped) {
        if (isArray(objValue)) {
          newValue = objValue;
        }
        else if (isArrayLikeObject(objValue)) {
          newValue = copyArray(objValue);
        }
        else if (isBuff) {
          isCommon = false;
          newValue = cloneBuffer(srcValue, true);
        }
        else if (isTyped) {
          isCommon = false;
          newValue = cloneTypedArray(srcValue, true);
        }
        else {
          newValue = [];
        }
      }
      else if (isPlainObject(srcValue) || isArguments(srcValue)) {
        newValue = objValue;
        if (isArguments(objValue)) {
          newValue = toPlainObject(objValue);
        }
        else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
          newValue = initCloneObject(srcValue);
        }
      }
      else {
        isCommon = false;
      }
    }
    if (isCommon) {
      // Recursively merge objects and arrays (susceptible to call stack limits).
      stack.set(srcValue, newValue);
      mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
      stack['delete'](srcValue);
    }
    assignMergeValue(object, key, newValue);
  }
  
  module.exports = baseMergeDeep;
  
  
  /***/ }),
  /* 278 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyObject = __webpack_require__(27),
      keysIn = __webpack_require__(47);
  
  /**
   * Converts `value` to a plain object flattening inherited enumerable string
   * keyed properties of `value` to own properties of the plain object.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category Lang
   * @param {*} value The value to convert.
   * @returns {Object} Returns the converted plain object.
   * @example
   *
   * function Foo() {
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.assign({ 'a': 1 }, new Foo);
   * // => { 'a': 1, 'b': 2 }
   *
   * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
   * // => { 'a': 1, 'b': 2, 'c': 3 }
   */
  function toPlainObject(value) {
    return copyObject(value, keysIn(value));
  }
  
  module.exports = toPlainObject;
  
  
  /***/ }),
  /* 279 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var map = __webpack_require__(17);
  var isArray = __webpack_require__(0);
  var isNumber = __webpack_require__(184);
  var isString = __webpack_require__(51);
  function valToNumber(v) {
    if (isNumber(v)) {
      return v;
    } else if (isString(v)) {
      return parseFloat(v);
    } else if (isArray(v)) {
      return map(v, valToNumber);
    }
  
    throw new Error('The value should be a number, a parseable string or an array of those.');
  }
  
  module.exports = valToNumber;
  
  
  /***/ }),
  /* 280 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var forEach = __webpack_require__(35);
  var filter = __webpack_require__(101);
  var map = __webpack_require__(17);
  var isEmpty = __webpack_require__(16);
  var indexOf = __webpack_require__(74);
  
  function filterState(state, filters) {
    var partialState = {};
    var attributeFilters = filter(filters, function(f) { return f.indexOf('attribute:') !== -1; });
    var attributes = map(attributeFilters, function(aF) { return aF.split(':')[1]; });
  
    if (indexOf(attributes, '*') === -1) {
      forEach(attributes, function(attr) {
        if (state.isConjunctiveFacet(attr) && state.isFacetRefined(attr)) {
          if (!partialState.facetsRefinements) partialState.facetsRefinements = {};
          partialState.facetsRefinements[attr] = state.facetsRefinements[attr];
        }
  
        if (state.isDisjunctiveFacet(attr) && state.isDisjunctiveFacetRefined(attr)) {
          if (!partialState.disjunctiveFacetsRefinements) partialState.disjunctiveFacetsRefinements = {};
          partialState.disjunctiveFacetsRefinements[attr] = state.disjunctiveFacetsRefinements[attr];
        }
  
        if (state.isHierarchicalFacet(attr) && state.isHierarchicalFacetRefined(attr)) {
          if (!partialState.hierarchicalFacetsRefinements) partialState.hierarchicalFacetsRefinements = {};
          partialState.hierarchicalFacetsRefinements[attr] = state.hierarchicalFacetsRefinements[attr];
        }
  
        var numericRefinements = state.getNumericRefinements(attr);
        if (!isEmpty(numericRefinements)) {
          if (!partialState.numericRefinements) partialState.numericRefinements = {};
          partialState.numericRefinements[attr] = state.numericRefinements[attr];
        }
      });
    } else {
      if (!isEmpty(state.numericRefinements)) {
        partialState.numericRefinements = state.numericRefinements;
      }
      if (!isEmpty(state.facetsRefinements)) partialState.facetsRefinements = state.facetsRefinements;
      if (!isEmpty(state.disjunctiveFacetsRefinements)) {
        partialState.disjunctiveFacetsRefinements = state.disjunctiveFacetsRefinements;
      }
      if (!isEmpty(state.hierarchicalFacetsRefinements)) {
        partialState.hierarchicalFacetsRefinements = state.hierarchicalFacetsRefinements;
      }
    }
  
    var searchParameters = filter(
      filters,
      function(f) {
        return f.indexOf('attribute:') === -1;
      }
    );
  
    forEach(
      searchParameters,
      function(parameterKey) {
        partialState[parameterKey] = state[parameterKey];
      }
    );
  
    return partialState;
  }
  
  module.exports = filterState;
  
  
  /***/ }),
  /* 281 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  /**
   * Functions to manipulate refinement lists
   *
   * The RefinementList is not formally defined through a prototype but is based
   * on a specific structure.
   *
   * @module SearchParameters.refinementList
   *
   * @typedef {string[]} SearchParameters.refinementList.Refinements
   * @typedef {Object.<string, SearchParameters.refinementList.Refinements>} SearchParameters.refinementList.RefinementList
   */
  
  var isUndefined = __webpack_require__(185);
  var isString = __webpack_require__(51);
  var isFunction = __webpack_require__(19);
  var isEmpty = __webpack_require__(16);
  var defaults = __webpack_require__(102);
  
  var reduce = __webpack_require__(49);
  var filter = __webpack_require__(101);
  var omit = __webpack_require__(45);
  
  var lib = {
    /**
     * Adds a refinement to a RefinementList
     * @param {RefinementList} refinementList the initial list
     * @param {string} attribute the attribute to refine
     * @param {string} value the value of the refinement, if the value is not a string it will be converted
     * @return {RefinementList} a new and updated refinement list
     */
    addRefinement: function addRefinement(refinementList, attribute, value) {
      if (lib.isRefined(refinementList, attribute, value)) {
        return refinementList;
      }
  
      var valueAsString = '' + value;
  
      var facetRefinement = !refinementList[attribute] ?
        [valueAsString] :
        refinementList[attribute].concat(valueAsString);
  
      var mod = {};
  
      mod[attribute] = facetRefinement;
  
      return defaults({}, mod, refinementList);
    },
    /**
     * Removes refinement(s) for an attribute:
     *  - if the value is specified removes the refinement for the value on the attribute
     *  - if no value is specified removes all the refinements for this attribute
     * @param {RefinementList} refinementList the initial list
     * @param {string} attribute the attribute to refine
     * @param {string} [value] the value of the refinement
     * @return {RefinementList} a new and updated refinement lst
     */
    removeRefinement: function removeRefinement(refinementList, attribute, value) {
      if (isUndefined(value)) {
        return lib.clearRefinement(refinementList, attribute);
      }
  
      var valueAsString = '' + value;
  
      return lib.clearRefinement(refinementList, function(v, f) {
        return attribute === f && valueAsString === v;
      });
    },
    /**
     * Toggles the refinement value for an attribute.
     * @param {RefinementList} refinementList the initial list
     * @param {string} attribute the attribute to refine
     * @param {string} value the value of the refinement
     * @return {RefinementList} a new and updated list
     */
    toggleRefinement: function toggleRefinement(refinementList, attribute, value) {
      if (isUndefined(value)) throw new Error('toggleRefinement should be used with a value');
  
      if (lib.isRefined(refinementList, attribute, value)) {
        return lib.removeRefinement(refinementList, attribute, value);
      }
  
      return lib.addRefinement(refinementList, attribute, value);
    },
    /**
     * Clear all or parts of a RefinementList. Depending on the arguments, three
     * kinds of behavior can happen:
     *  - if no attribute is provided: clears the whole list
     *  - if an attribute is provided as a string: clears the list for the specific attribute
     *  - if an attribute is provided as a function: discards the elements for which the function returns true
     * @param {RefinementList} refinementList the initial list
     * @param {string} [attribute] the attribute or function to discard
     * @param {string} [refinementType] optional parameter to give more context to the attribute function
     * @return {RefinementList} a new and updated refinement list
     */
    clearRefinement: function clearRefinement(refinementList, attribute, refinementType) {
      if (isUndefined(attribute)) {
        return {};
      } else if (isString(attribute)) {
        return omit(refinementList, attribute);
      } else if (isFunction(attribute)) {
        return reduce(refinementList, function(memo, values, key) {
          var facetList = filter(values, function(value) {
            return !attribute(value, key, refinementType);
          });
  
          if (!isEmpty(facetList)) memo[key] = facetList;
  
          return memo;
        }, {});
      }
    },
    /**
     * Test if the refinement value is used for the attribute. If no refinement value
     * is provided, test if the refinementList contains any refinement for the
     * given attribute.
     * @param {RefinementList} refinementList the list of refinement
     * @param {string} attribute name of the attribute
     * @param {string} [refinementValue] value of the filter/refinement
     * @return {boolean}
     */
    isRefined: function isRefined(refinementList, attribute, refinementValue) {
      var indexOf = __webpack_require__(74);
  
      var containsRefinements = !!refinementList[attribute] &&
        refinementList[attribute].length > 0;
  
      if (isUndefined(refinementValue) || !containsRefinements) {
        return containsRefinements;
      }
  
      var refinementValueAsString = '' + refinementValue;
  
      return indexOf(refinementList[attribute], refinementValueAsString) !== -1;
    }
  };
  
  module.exports = lib;
  
  
  /***/ }),
  /* 282 */
  /***/ (function(module, exports) {
  
  /**
   * Creates an array with all falsey values removed. The values `false`, `null`,
   * `0`, `""`, `undefined`, and `NaN` are falsey.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Array
   * @param {Array} array The array to compact.
   * @returns {Array} Returns the new array of filtered values.
   * @example
   *
   * _.compact([0, 1, false, 2, '', 3]);
   * // => [1, 2, 3]
   */
  function compact(array) {
    var index = -1,
        length = array == null ? 0 : array.length,
        resIndex = 0,
        result = [];
  
    while (++index < length) {
      var value = array[index];
      if (value) {
        result[resIndex++] = value;
      }
    }
    return result;
  }
  
  module.exports = compact;
  
  
  /***/ }),
  /* 283 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIteratee = __webpack_require__(13),
      baseSum = __webpack_require__(284);
  
  /**
   * This method is like `_.sum` except that it accepts `iteratee` which is
   * invoked for each element in `array` to generate the value to be summed.
   * The iteratee is invoked with one argument: (value).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Math
   * @param {Array} array The array to iterate over.
   * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
   * @returns {number} Returns the sum.
   * @example
   *
   * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
   *
   * _.sumBy(objects, function(o) { return o.n; });
   * // => 20
   *
   * // The `_.property` iteratee shorthand.
   * _.sumBy(objects, 'n');
   * // => 20
   */
  function sumBy(array, iteratee) {
    return (array && array.length)
      ? baseSum(array, baseIteratee(iteratee, 2))
      : 0;
  }
  
  module.exports = sumBy;
  
  
  /***/ }),
  /* 284 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.sum` and `_.sumBy` without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} array The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {number} Returns the sum.
   */
  function baseSum(array, iteratee) {
    var result,
        index = -1,
        length = array.length;
  
    while (++index < length) {
      var current = iteratee(array[index]);
      if (current !== undefined) {
        result = result === undefined ? current : (result + current);
      }
    }
    return result;
  }
  
  module.exports = baseSum;
  
  
  /***/ }),
  /* 285 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseIndexOf = __webpack_require__(44),
      isArrayLike = __webpack_require__(11),
      isString = __webpack_require__(51),
      toInteger = __webpack_require__(50),
      values = __webpack_require__(286);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * Checks if `value` is in `collection`. If `collection` is a string, it's
   * checked for a substring of `value`, otherwise
   * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * is used for equality comparisons. If `fromIndex` is negative, it's used as
   * the offset from the end of `collection`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Collection
   * @param {Array|Object|string} collection The collection to inspect.
   * @param {*} value The value to search for.
   * @param {number} [fromIndex=0] The index to search from.
   * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
   * @returns {boolean} Returns `true` if `value` is found, else `false`.
   * @example
   *
   * _.includes([1, 2, 3], 1);
   * // => true
   *
   * _.includes([1, 2, 3], 1, 2);
   * // => false
   *
   * _.includes({ 'a': 1, 'b': 2 }, 1);
   * // => true
   *
   * _.includes('abcd', 'bc');
   * // => true
   */
  function includes(collection, value, fromIndex, guard) {
    collection = isArrayLike(collection) ? collection : values(collection);
    fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
  
    var length = collection.length;
    if (fromIndex < 0) {
      fromIndex = nativeMax(length + fromIndex, 0);
    }
    return isString(collection)
      ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
      : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
  }
  
  module.exports = includes;
  
  
  /***/ }),
  /* 286 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseValues = __webpack_require__(287),
      keys = __webpack_require__(9);
  
  /**
   * Creates an array of the own enumerable string keyed property values of `object`.
   *
   * **Note:** Non-object values are coerced to objects.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property values.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.values(new Foo);
   * // => [1, 2] (iteration order is not guaranteed)
   *
   * _.values('hi');
   * // => ['h', 'i']
   */
  function values(object) {
    return object == null ? [] : baseValues(object, keys(object));
  }
  
  module.exports = values;
  
  
  /***/ }),
  /* 287 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12);
  
  /**
   * The base implementation of `_.values` and `_.valuesIn` which creates an
   * array of `object` property values corresponding to the property names
   * of `props`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array} props The property names to get values for.
   * @returns {Object} Returns the array of property values.
   */
  function baseValues(object, props) {
    return arrayMap(props, function(key) {
      return object[key];
    });
  }
  
  module.exports = baseValues;
  
  
  /***/ }),
  /* 288 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12),
      baseIteratee = __webpack_require__(13),
      baseMap = __webpack_require__(183),
      baseSortBy = __webpack_require__(289),
      baseUnary = __webpack_require__(42),
      compareMultiple = __webpack_require__(290),
      identity = __webpack_require__(26);
  
  /**
   * The base implementation of `_.orderBy` without param guards.
   *
   * @private
   * @param {Array|Object} collection The collection to iterate over.
   * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
   * @param {string[]} orders The sort orders of `iteratees`.
   * @returns {Array} Returns the new sorted array.
   */
  function baseOrderBy(collection, iteratees, orders) {
    var index = -1;
    iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(baseIteratee));
  
    var result = baseMap(collection, function(value, key, collection) {
      var criteria = arrayMap(iteratees, function(iteratee) {
        return iteratee(value);
      });
      return { 'criteria': criteria, 'index': ++index, 'value': value };
    });
  
    return baseSortBy(result, function(object, other) {
      return compareMultiple(object, other, orders);
    });
  }
  
  module.exports = baseOrderBy;
  
  
  /***/ }),
  /* 289 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.sortBy` which uses `comparer` to define the
   * sort order of `array` and replaces criteria objects with their corresponding
   * values.
   *
   * @private
   * @param {Array} array The array to sort.
   * @param {Function} comparer The function to define sort order.
   * @returns {Array} Returns `array`.
   */
  function baseSortBy(array, comparer) {
    var length = array.length;
  
    array.sort(comparer);
    while (length--) {
      array[length] = array[length].value;
    }
    return array;
  }
  
  module.exports = baseSortBy;
  
  
  /***/ }),
  /* 290 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var compareAscending = __webpack_require__(291);
  
  /**
   * Used by `_.orderBy` to compare multiple properties of a value to another
   * and stable sort them.
   *
   * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
   * specify an order of "desc" for descending or "asc" for ascending sort order
   * of corresponding values.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {boolean[]|string[]} orders The order to sort by for each property.
   * @returns {number} Returns the sort order indicator for `object`.
   */
  function compareMultiple(object, other, orders) {
    var index = -1,
        objCriteria = object.criteria,
        othCriteria = other.criteria,
        length = objCriteria.length,
        ordersLength = orders.length;
  
    while (++index < length) {
      var result = compareAscending(objCriteria[index], othCriteria[index]);
      if (result) {
        if (index >= ordersLength) {
          return result;
        }
        var order = orders[index];
        return result * (order == 'desc' ? -1 : 1);
      }
    }
    // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
    // that causes it, under certain circumstances, to provide the same value for
    // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
    // for more details.
    //
    // This also ensures a stable sort in V8 and other engines.
    // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
    return object.index - other.index;
  }
  
  module.exports = compareMultiple;
  
  
  /***/ }),
  /* 291 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var isSymbol = __webpack_require__(23);
  
  /**
   * Compares values to sort them in ascending order.
   *
   * @private
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {number} Returns the sort order indicator for `value`.
   */
  function compareAscending(value, other) {
    if (value !== other) {
      var valIsDefined = value !== undefined,
          valIsNull = value === null,
          valIsReflexive = value === value,
          valIsSymbol = isSymbol(value);
  
      var othIsDefined = other !== undefined,
          othIsNull = other === null,
          othIsReflexive = other === other,
          othIsSymbol = isSymbol(other);
  
      if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
          (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
          (valIsNull && othIsDefined && othIsReflexive) ||
          (!valIsDefined && othIsReflexive) ||
          !valIsReflexive) {
        return 1;
      }
      if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
          (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
          (othIsNull && valIsDefined && valIsReflexive) ||
          (!othIsDefined && valIsReflexive) ||
          !othIsReflexive) {
        return -1;
      }
    }
    return 0;
  }
  
  module.exports = compareAscending;
  
  
  /***/ }),
  /* 292 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseRest = __webpack_require__(25),
      createWrap = __webpack_require__(105),
      getHolder = __webpack_require__(53),
      replaceHolders = __webpack_require__(36);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_PARTIAL_FLAG = 32;
  
  /**
   * Creates a function that invokes `func` with `partials` prepended to the
   * arguments it receives. This method is like `_.bind` except it does **not**
   * alter the `this` binding.
   *
   * The `_.partial.placeholder` value, which defaults to `_` in monolithic
   * builds, may be used as a placeholder for partially applied arguments.
   *
   * **Note:** This method doesn't set the "length" property of partially
   * applied functions.
   *
   * @static
   * @memberOf _
   * @since 0.2.0
   * @category Function
   * @param {Function} func The function to partially apply arguments to.
   * @param {...*} [partials] The arguments to be partially applied.
   * @returns {Function} Returns the new partially applied function.
   * @example
   *
   * function greet(greeting, name) {
   *   return greeting + ' ' + name;
   * }
   *
   * var sayHelloTo = _.partial(greet, 'hello');
   * sayHelloTo('fred');
   * // => 'hello fred'
   *
   * // Partially applied with placeholders.
   * var greetFred = _.partial(greet, _, 'fred');
   * greetFred('hi');
   * // => 'hi fred'
   */
  var partial = baseRest(function(func, partials) {
    var holders = replaceHolders(partials, getHolder(partial));
    return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
  });
  
  // Assign default placeholders.
  partial.placeholder = {};
  
  module.exports = partial;
  
  
  /***/ }),
  /* 293 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var createCtor = __webpack_require__(75),
      root = __webpack_require__(3);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1;
  
  /**
   * Creates a function that wraps `func` to invoke it with the optional `this`
   * binding of `thisArg`.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @param {*} [thisArg] The `this` binding of `func`.
   * @returns {Function} Returns the new wrapped function.
   */
  function createBind(func, bitmask, thisArg) {
    var isBind = bitmask & WRAP_BIND_FLAG,
        Ctor = createCtor(func);
  
    function wrapper() {
      var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
      return fn.apply(isBind ? thisArg : this, arguments);
    }
    return wrapper;
  }
  
  module.exports = createBind;
  
  
  /***/ }),
  /* 294 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var apply = __webpack_require__(68),
      createCtor = __webpack_require__(75),
      createHybrid = __webpack_require__(193),
      createRecurry = __webpack_require__(196),
      getHolder = __webpack_require__(53),
      replaceHolders = __webpack_require__(36),
      root = __webpack_require__(3);
  
  /**
   * Creates a function that wraps `func` to enable currying.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @param {number} arity The arity of `func`.
   * @returns {Function} Returns the new wrapped function.
   */
  function createCurry(func, bitmask, arity) {
    var Ctor = createCtor(func);
  
    function wrapper() {
      var length = arguments.length,
          args = Array(length),
          index = length,
          placeholder = getHolder(wrapper);
  
      while (index--) {
        args[index] = arguments[index];
      }
      var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
        ? []
        : replaceHolders(args, placeholder);
  
      length -= holders.length;
      if (length < arity) {
        return createRecurry(
          func, bitmask, createHybrid, wrapper.placeholder, undefined,
          args, holders, undefined, undefined, arity - length);
      }
      var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
      return apply(fn, this, args);
    }
    return wrapper;
  }
  
  module.exports = createCurry;
  
  
  /***/ }),
  /* 295 */
  /***/ (function(module, exports) {
  
  /**
   * Gets the number of `placeholder` occurrences in `array`.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} placeholder The placeholder to search for.
   * @returns {number} Returns the placeholder count.
   */
  function countHolders(array, placeholder) {
    var length = array.length,
        result = 0;
  
    while (length--) {
      if (array[length] === placeholder) {
        ++result;
      }
    }
    return result;
  }
  
  module.exports = countHolders;
  
  
  /***/ }),
  /* 296 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var LazyWrapper = __webpack_require__(106),
      getData = __webpack_require__(197),
      getFuncName = __webpack_require__(298),
      lodash = __webpack_require__(300);
  
  /**
   * Checks if `func` has a lazy counterpart.
   *
   * @private
   * @param {Function} func The function to check.
   * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
   *  else `false`.
   */
  function isLaziable(func) {
    var funcName = getFuncName(func),
        other = lodash[funcName];
  
    if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
      return false;
    }
    if (func === other) {
      return true;
    }
    var data = getData(other);
    return !!data && func === data[0];
  }
  
  module.exports = isLaziable;
  
  
  /***/ }),
  /* 297 */
  /***/ (function(module, exports) {
  
  /**
   * This method returns `undefined`.
   *
   * @static
   * @memberOf _
   * @since 2.3.0
   * @category Util
   * @example
   *
   * _.times(2, _.noop);
   * // => [undefined, undefined]
   */
  function noop() {
    // No operation performed.
  }
  
  module.exports = noop;
  
  
  /***/ }),
  /* 298 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var realNames = __webpack_require__(299);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Gets the name of `func`.
   *
   * @private
   * @param {Function} func The function to query.
   * @returns {string} Returns the function name.
   */
  function getFuncName(func) {
    var result = (func.name + ''),
        array = realNames[result],
        length = hasOwnProperty.call(realNames, result) ? array.length : 0;
  
    while (length--) {
      var data = array[length],
          otherFunc = data.func;
      if (otherFunc == null || otherFunc == func) {
        return data.name;
      }
    }
    return result;
  }
  
  module.exports = getFuncName;
  
  
  /***/ }),
  /* 299 */
  /***/ (function(module, exports) {
  
  /** Used to lookup unminified function names. */
  var realNames = {};
  
  module.exports = realNames;
  
  
  /***/ }),
  /* 300 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var LazyWrapper = __webpack_require__(106),
      LodashWrapper = __webpack_require__(198),
      baseLodash = __webpack_require__(107),
      isArray = __webpack_require__(0),
      isObjectLike = __webpack_require__(7),
      wrapperClone = __webpack_require__(301);
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Creates a `lodash` object which wraps `value` to enable implicit method
   * chain sequences. Methods that operate on and return arrays, collections,
   * and functions can be chained together. Methods that retrieve a single value
   * or may return a primitive value will automatically end the chain sequence
   * and return the unwrapped value. Otherwise, the value must be unwrapped
   * with `_#value`.
   *
   * Explicit chain sequences, which must be unwrapped with `_#value`, may be
   * enabled using `_.chain`.
   *
   * The execution of chained methods is lazy, that is, it's deferred until
   * `_#value` is implicitly or explicitly called.
   *
   * Lazy evaluation allows several methods to support shortcut fusion.
   * Shortcut fusion is an optimization to merge iteratee calls; this avoids
   * the creation of intermediate arrays and can greatly reduce the number of
   * iteratee executions. Sections of a chain sequence qualify for shortcut
   * fusion if the section is applied to an array and iteratees accept only
   * one argument. The heuristic for whether a section qualifies for shortcut
   * fusion is subject to change.
   *
   * Chaining is supported in custom builds as long as the `_#value` method is
   * directly or indirectly included in the build.
   *
   * In addition to lodash methods, wrappers have `Array` and `String` methods.
   *
   * The wrapper `Array` methods are:
   * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
   *
   * The wrapper `String` methods are:
   * `replace` and `split`
   *
   * The wrapper methods that support shortcut fusion are:
   * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
   * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
   * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
   *
   * The chainable wrapper methods are:
   * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
   * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
   * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
   * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
   * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
   * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
   * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
   * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
   * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
   * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
   * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
   * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
   * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
   * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
   * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
   * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
   * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
   * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
   * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
   * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
   * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
   * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
   * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
   * `zipObject`, `zipObjectDeep`, and `zipWith`
   *
   * The wrapper methods that are **not** chainable by default are:
   * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
   * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
   * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
   * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
   * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
   * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
   * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
   * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
   * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
   * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
   * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
   * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
   * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
   * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
   * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
   * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
   * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
   * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
   * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
   * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
   * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
   * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
   * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
   * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
   * `upperFirst`, `value`, and `words`
   *
   * @name _
   * @constructor
   * @category Seq
   * @param {*} value The value to wrap in a `lodash` instance.
   * @returns {Object} Returns the new `lodash` wrapper instance.
   * @example
   *
   * function square(n) {
   *   return n * n;
   * }
   *
   * var wrapped = _([1, 2, 3]);
   *
   * // Returns an unwrapped value.
   * wrapped.reduce(_.add);
   * // => 6
   *
   * // Returns a wrapped value.
   * var squares = wrapped.map(square);
   *
   * _.isArray(squares);
   * // => false
   *
   * _.isArray(squares.value());
   * // => true
   */
  function lodash(value) {
    if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
      if (value instanceof LodashWrapper) {
        return value;
      }
      if (hasOwnProperty.call(value, '__wrapped__')) {
        return wrapperClone(value);
      }
    }
    return new LodashWrapper(value);
  }
  
  // Ensure wrappers are instances of `baseLodash`.
  lodash.prototype = baseLodash.prototype;
  lodash.prototype.constructor = lodash;
  
  module.exports = lodash;
  
  
  /***/ }),
  /* 301 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var LazyWrapper = __webpack_require__(106),
      LodashWrapper = __webpack_require__(198),
      copyArray = __webpack_require__(69);
  
  /**
   * Creates a clone of `wrapper`.
   *
   * @private
   * @param {Object} wrapper The wrapper to clone.
   * @returns {Object} Returns the cloned wrapper.
   */
  function wrapperClone(wrapper) {
    if (wrapper instanceof LazyWrapper) {
      return wrapper.clone();
    }
    var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
    result.__actions__ = copyArray(wrapper.__actions__);
    result.__index__  = wrapper.__index__;
    result.__values__ = wrapper.__values__;
    return result;
  }
  
  module.exports = wrapperClone;
  
  
  /***/ }),
  /* 302 */
  /***/ (function(module, exports) {
  
  /** Used to match wrap detail comments. */
  var reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
      reSplitDetails = /,? & /;
  
  /**
   * Extracts wrapper details from the `source` body comment.
   *
   * @private
   * @param {string} source The source to inspect.
   * @returns {Array} Returns the wrapper details.
   */
  function getWrapDetails(source) {
    var match = source.match(reWrapDetails);
    return match ? match[1].split(reSplitDetails) : [];
  }
  
  module.exports = getWrapDetails;
  
  
  /***/ }),
  /* 303 */
  /***/ (function(module, exports) {
  
  /** Used to match wrap detail comments. */
  var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/;
  
  /**
   * Inserts wrapper `details` in a comment at the top of the `source` body.
   *
   * @private
   * @param {string} source The source to modify.
   * @returns {Array} details The details to insert.
   * @returns {string} Returns the modified source.
   */
  function insertWrapDetails(source, details) {
    var length = details.length;
    if (!length) {
      return source;
    }
    var lastIndex = length - 1;
    details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
    details = details.join(length > 2 ? ', ' : ' ');
    return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
  }
  
  module.exports = insertWrapDetails;
  
  
  /***/ }),
  /* 304 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayEach = __webpack_require__(95),
      arrayIncludes = __webpack_require__(92);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_FLAG = 8,
      WRAP_CURRY_RIGHT_FLAG = 16,
      WRAP_PARTIAL_FLAG = 32,
      WRAP_PARTIAL_RIGHT_FLAG = 64,
      WRAP_ARY_FLAG = 128,
      WRAP_REARG_FLAG = 256,
      WRAP_FLIP_FLAG = 512;
  
  /** Used to associate wrap methods with their bit flags. */
  var wrapFlags = [
    ['ary', WRAP_ARY_FLAG],
    ['bind', WRAP_BIND_FLAG],
    ['bindKey', WRAP_BIND_KEY_FLAG],
    ['curry', WRAP_CURRY_FLAG],
    ['curryRight', WRAP_CURRY_RIGHT_FLAG],
    ['flip', WRAP_FLIP_FLAG],
    ['partial', WRAP_PARTIAL_FLAG],
    ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
    ['rearg', WRAP_REARG_FLAG]
  ];
  
  /**
   * Updates wrapper `details` based on `bitmask` flags.
   *
   * @private
   * @returns {Array} details The details to modify.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @returns {Array} Returns `details`.
   */
  function updateWrapDetails(details, bitmask) {
    arrayEach(wrapFlags, function(pair) {
      var value = '_.' + pair[0];
      if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
        details.push(value);
      }
    });
    return details.sort();
  }
  
  module.exports = updateWrapDetails;
  
  
  /***/ }),
  /* 305 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var copyArray = __webpack_require__(69),
      isIndex = __webpack_require__(32);
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMin = Math.min;
  
  /**
   * Reorder `array` according to the specified indexes where the element at
   * the first index is assigned as the first element, the element at
   * the second index is assigned as the second element, and so on.
   *
   * @private
   * @param {Array} array The array to reorder.
   * @param {Array} indexes The arranged array indexes.
   * @returns {Array} Returns `array`.
   */
  function reorder(array, indexes) {
    var arrLength = array.length,
        length = nativeMin(indexes.length, arrLength),
        oldArray = copyArray(array);
  
    while (length--) {
      var index = indexes[length];
      array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
    }
    return array;
  }
  
  module.exports = reorder;
  
  
  /***/ }),
  /* 306 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var apply = __webpack_require__(68),
      createCtor = __webpack_require__(75),
      root = __webpack_require__(3);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1;
  
  /**
   * Creates a function that wraps `func` to invoke it with the `this` binding
   * of `thisArg` and `partials` prepended to the arguments it receives.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
   * @param {*} thisArg The `this` binding of `func`.
   * @param {Array} partials The arguments to prepend to those provided to
   *  the new function.
   * @returns {Function} Returns the new wrapped function.
   */
  function createPartial(func, bitmask, thisArg, partials) {
    var isBind = bitmask & WRAP_BIND_FLAG,
        Ctor = createCtor(func);
  
    function wrapper() {
      var argsIndex = -1,
          argsLength = arguments.length,
          leftIndex = -1,
          leftLength = partials.length,
          args = Array(leftLength + argsLength),
          fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
  
      while (++leftIndex < leftLength) {
        args[leftIndex] = partials[leftIndex];
      }
      while (argsLength--) {
        args[leftIndex++] = arguments[++argsIndex];
      }
      return apply(fn, isBind ? thisArg : this, args);
    }
    return wrapper;
  }
  
  module.exports = createPartial;
  
  
  /***/ }),
  /* 307 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var composeArgs = __webpack_require__(194),
      composeArgsRight = __webpack_require__(195),
      replaceHolders = __webpack_require__(36);
  
  /** Used as the internal argument placeholder. */
  var PLACEHOLDER = '__lodash_placeholder__';
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_BIND_KEY_FLAG = 2,
      WRAP_CURRY_BOUND_FLAG = 4,
      WRAP_CURRY_FLAG = 8,
      WRAP_ARY_FLAG = 128,
      WRAP_REARG_FLAG = 256;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeMin = Math.min;
  
  /**
   * Merges the function metadata of `source` into `data`.
   *
   * Merging metadata reduces the number of wrappers used to invoke a function.
   * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
   * may be applied regardless of execution order. Methods like `_.ary` and
   * `_.rearg` modify function arguments, making the order in which they are
   * executed important, preventing the merging of metadata. However, we make
   * an exception for a safe combined case where curried functions have `_.ary`
   * and or `_.rearg` applied.
   *
   * @private
   * @param {Array} data The destination metadata.
   * @param {Array} source The source metadata.
   * @returns {Array} Returns `data`.
   */
  function mergeData(data, source) {
    var bitmask = data[1],
        srcBitmask = source[1],
        newBitmask = bitmask | srcBitmask,
        isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
  
    var isCombo =
      ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
      ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
      ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
  
    // Exit early if metadata can't be merged.
    if (!(isCommon || isCombo)) {
      return data;
    }
    // Use source `thisArg` if available.
    if (srcBitmask & WRAP_BIND_FLAG) {
      data[2] = source[2];
      // Set when currying a bound function.
      newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
    }
    // Compose partial arguments.
    var value = source[3];
    if (value) {
      var partials = data[3];
      data[3] = partials ? composeArgs(partials, value, source[4]) : value;
      data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
    }
    // Compose partial right arguments.
    value = source[5];
    if (value) {
      partials = data[5];
      data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
      data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
    }
    // Use source `argPos` if available.
    value = source[7];
    if (value) {
      data[7] = value;
    }
    // Use source `ary` if it's smaller.
    if (srcBitmask & WRAP_ARY_FLAG) {
      data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
    }
    // Use source `arity` if one is not provided.
    if (data[9] == null) {
      data[9] = source[9];
    }
    // Use source `func` and merge bitmasks.
    data[0] = source[0];
    data[1] = newBitmask;
  
    return data;
  }
  
  module.exports = mergeData;
  
  
  /***/ }),
  /* 308 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseRest = __webpack_require__(25),
      createWrap = __webpack_require__(105),
      getHolder = __webpack_require__(53),
      replaceHolders = __webpack_require__(36);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_PARTIAL_RIGHT_FLAG = 64;
  
  /**
   * This method is like `_.partial` except that partially applied arguments
   * are appended to the arguments it receives.
   *
   * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
   * builds, may be used as a placeholder for partially applied arguments.
   *
   * **Note:** This method doesn't set the "length" property of partially
   * applied functions.
   *
   * @static
   * @memberOf _
   * @since 1.0.0
   * @category Function
   * @param {Function} func The function to partially apply arguments to.
   * @param {...*} [partials] The arguments to be partially applied.
   * @returns {Function} Returns the new partially applied function.
   * @example
   *
   * function greet(greeting, name) {
   *   return greeting + ' ' + name;
   * }
   *
   * var greetFred = _.partialRight(greet, 'fred');
   * greetFred('hi');
   * // => 'hi fred'
   *
   * // Partially applied with placeholders.
   * var sayHelloTo = _.partialRight(greet, 'hello', _);
   * sayHelloTo('fred');
   * // => 'hello fred'
   */
  var partialRight = baseRest(function(func, partials) {
    var holders = replaceHolders(partials, getHolder(partialRight));
    return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
  });
  
  // Assign default placeholders.
  partialRight.placeholder = {};
  
  module.exports = partialRight;
  
  
  /***/ }),
  /* 309 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseClamp = __webpack_require__(310),
      baseToString = __webpack_require__(65),
      toInteger = __webpack_require__(50),
      toString = __webpack_require__(64);
  
  /**
   * Checks if `string` starts with the given target string.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category String
   * @param {string} [string=''] The string to inspect.
   * @param {string} [target] The string to search for.
   * @param {number} [position=0] The position to search from.
   * @returns {boolean} Returns `true` if `string` starts with `target`,
   *  else `false`.
   * @example
   *
   * _.startsWith('abc', 'a');
   * // => true
   *
   * _.startsWith('abc', 'b');
   * // => false
   *
   * _.startsWith('abc', 'b', 1);
   * // => true
   */
  function startsWith(string, target, position) {
    string = toString(string);
    position = position == null
      ? 0
      : baseClamp(toInteger(position), 0, string.length);
  
    target = baseToString(target);
    return string.slice(position, position + target.length) == target;
  }
  
  module.exports = startsWith;
  
  
  /***/ }),
  /* 310 */
  /***/ (function(module, exports) {
  
  /**
   * The base implementation of `_.clamp` which doesn't coerce arguments.
   *
   * @private
   * @param {number} number The number to clamp.
   * @param {number} [lower] The lower bound.
   * @param {number} upper The upper bound.
   * @returns {number} Returns the clamped number.
   */
  function baseClamp(number, lower, upper) {
    if (number === number) {
      if (upper !== undefined) {
        number = number <= upper ? number : upper;
      }
      if (lower !== undefined) {
        number = number >= lower ? number : lower;
      }
    }
    return number;
  }
  
  module.exports = baseClamp;
  
  
  /***/ }),
  /* 311 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = generateTrees;
  
  var last = __webpack_require__(174);
  var map = __webpack_require__(17);
  var reduce = __webpack_require__(49);
  var orderBy = __webpack_require__(104);
  var trim = __webpack_require__(187);
  var find = __webpack_require__(52);
  var pickBy = __webpack_require__(312);
  
  var prepareHierarchicalFacetSortBy = __webpack_require__(201);
  
  function generateTrees(state) {
    return function generate(hierarchicalFacetResult, hierarchicalFacetIndex) {
      var hierarchicalFacet = state.hierarchicalFacets[hierarchicalFacetIndex];
      var hierarchicalFacetRefinement = state.hierarchicalFacetsRefinements[hierarchicalFacet.name] &&
        state.hierarchicalFacetsRefinements[hierarchicalFacet.name][0] || '';
      var hierarchicalSeparator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
      var hierarchicalRootPath = state._getHierarchicalRootPath(hierarchicalFacet);
      var hierarchicalShowParentLevel = state._getHierarchicalShowParentLevel(hierarchicalFacet);
      var sortBy = prepareHierarchicalFacetSortBy(state._getHierarchicalFacetSortBy(hierarchicalFacet));
  
      var generateTreeFn = generateHierarchicalTree(sortBy, hierarchicalSeparator, hierarchicalRootPath,
        hierarchicalShowParentLevel, hierarchicalFacetRefinement);
  
      var results = hierarchicalFacetResult;
  
      if (hierarchicalRootPath) {
        results = hierarchicalFacetResult.slice(hierarchicalRootPath.split(hierarchicalSeparator).length);
      }
  
      return reduce(results, generateTreeFn, {
        name: state.hierarchicalFacets[hierarchicalFacetIndex].name,
        count: null, // root level, no count
        isRefined: true, // root level, always refined
        path: null, // root level, no path
        data: null
      });
    };
  }
  
  function generateHierarchicalTree(sortBy, hierarchicalSeparator, hierarchicalRootPath,
                                    hierarchicalShowParentLevel, currentRefinement) {
    return function generateTree(hierarchicalTree, hierarchicalFacetResult, currentHierarchicalLevel) {
      var parent = hierarchicalTree;
  
      if (currentHierarchicalLevel > 0) {
        var level = 0;
  
        parent = hierarchicalTree;
  
        while (level < currentHierarchicalLevel) {
          parent = parent && find(parent.data, {isRefined: true});
          level++;
        }
      }
  
      // we found a refined parent, let's add current level data under it
      if (parent) {
        // filter values in case an object has multiple categories:
        //   {
        //     categories: {
        //       level0: ['beers', 'bières'],
        //       level1: ['beers > IPA', 'bières > Belges']
        //     }
        //   }
        //
        // If parent refinement is `beers`, then we do not want to have `bières > Belges`
        // showing up
  
        var onlyMatchingValuesFn = filterFacetValues(parent.path || hierarchicalRootPath,
          currentRefinement, hierarchicalSeparator, hierarchicalRootPath, hierarchicalShowParentLevel);
  
        parent.data = orderBy(
          map(
            pickBy(hierarchicalFacetResult.data, onlyMatchingValuesFn),
            formatHierarchicalFacetValue(hierarchicalSeparator, currentRefinement)
          ),
          sortBy[0], sortBy[1]
        );
      }
  
      return hierarchicalTree;
    };
  }
  
  function filterFacetValues(parentPath, currentRefinement, hierarchicalSeparator, hierarchicalRootPath,
                             hierarchicalShowParentLevel) {
    return function(facetCount, facetValue) {
      // we want the facetValue is a child of hierarchicalRootPath
      if (hierarchicalRootPath &&
        (facetValue.indexOf(hierarchicalRootPath) !== 0 || hierarchicalRootPath === facetValue)) {
        return false;
      }
  
      // we always want root levels (only when there is no prefix path)
      return !hierarchicalRootPath && facetValue.indexOf(hierarchicalSeparator) === -1 ||
        // if there is a rootPath, being root level mean 1 level under rootPath
        hierarchicalRootPath &&
        facetValue.split(hierarchicalSeparator).length - hierarchicalRootPath.split(hierarchicalSeparator).length === 1 ||
        // if current refinement is a root level and current facetValue is a root level,
        // keep the facetValue
        facetValue.indexOf(hierarchicalSeparator) === -1 &&
        currentRefinement.indexOf(hierarchicalSeparator) === -1 ||
        // currentRefinement is a child of the facet value
        currentRefinement.indexOf(facetValue) === 0 ||
        // facetValue is a child of the current parent, add it
        facetValue.indexOf(parentPath + hierarchicalSeparator) === 0 &&
        (hierarchicalShowParentLevel || facetValue.indexOf(currentRefinement) === 0);
    };
  }
  
  function formatHierarchicalFacetValue(hierarchicalSeparator, currentRefinement) {
    return function format(facetCount, facetValue) {
      return {
        name: trim(last(facetValue.split(hierarchicalSeparator))),
        path: facetValue,
        count: facetCount,
        isRefined: currentRefinement === facetValue || currentRefinement.indexOf(facetValue + hierarchicalSeparator) === 0,
        data: null
      };
    };
  }
  
  
  /***/ }),
  /* 312 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var arrayMap = __webpack_require__(12),
      baseIteratee = __webpack_require__(13),
      basePickBy = __webpack_require__(202),
      getAllKeysIn = __webpack_require__(97);
  
  /**
   * Creates an object composed of the `object` properties `predicate` returns
   * truthy for. The predicate is invoked with two arguments: (value, key).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Object
   * @param {Object} object The source object.
   * @param {Function} [predicate=_.identity] The function invoked per property.
   * @returns {Object} Returns the new object.
   * @example
   *
   * var object = { 'a': 1, 'b': '2', 'c': 3 };
   *
   * _.pickBy(object, _.isNumber);
   * // => { 'a': 1, 'c': 3 }
   */
  function pickBy(object, predicate) {
    if (object == null) {
      return {};
    }
    var props = arrayMap(getAllKeysIn(object), function(prop) {
      return [prop];
    });
    predicate = baseIteratee(predicate);
    return basePickBy(object, props, function(value, path) {
      return predicate(value, path[0]);
    });
  }
  
  module.exports = pickBy;
  
  
  /***/ }),
  /* 313 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var assignValue = __webpack_require__(96),
      castPath = __webpack_require__(22),
      isIndex = __webpack_require__(32),
      isObject = __webpack_require__(6),
      toKey = __webpack_require__(24);
  
  /**
   * The base implementation of `_.set`.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {Array|string} path The path of the property to set.
   * @param {*} value The value to set.
   * @param {Function} [customizer] The function to customize path creation.
   * @returns {Object} Returns `object`.
   */
  function baseSet(object, path, value, customizer) {
    if (!isObject(object)) {
      return object;
    }
    path = castPath(path, object);
  
    var index = -1,
        length = path.length,
        lastIndex = length - 1,
        nested = object;
  
    while (nested != null && ++index < length) {
      var key = toKey(path[index]),
          newValue = value;
  
      if (index != lastIndex) {
        var objValue = nested[key];
        newValue = customizer ? customizer(objValue, key, nested) : undefined;
        if (newValue === undefined) {
          newValue = isObject(objValue)
            ? objValue
            : (isIndex(path[index + 1]) ? [] : {});
        }
      }
      assignValue(nested, key, newValue);
      nested = nested[key];
    }
    return object;
  }
  
  module.exports = baseSet;
  
  
  /***/ }),
  /* 314 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  var util = __webpack_require__(203);
  var events = __webpack_require__(204);
  
  /**
   * A DerivedHelper is a way to create sub requests to
   * Algolia from a main helper.
   * @class
   * @classdesc The DerivedHelper provides an event based interface for search callbacks:
   *  - search: when a search is triggered using the `search()` method.
   *  - result: when the response is retrieved from Algolia and is processed.
   *    This event contains a {@link SearchResults} object and the
   *    {@link SearchParameters} corresponding to this answer.
   */
  function DerivedHelper(mainHelper, fn) {
    this.main = mainHelper;
    this.fn = fn;
    this.lastResults = null;
  }
  
  util.inherits(DerivedHelper, events.EventEmitter);
  
  /**
   * Detach this helper from the main helper
   * @return {undefined}
   * @throws Error if the derived helper is already detached
   */
  DerivedHelper.prototype.detach = function() {
    this.removeAllListeners();
    this.main.detachDerivedHelper(this);
  };
  
  DerivedHelper.prototype.getModifiedState = function(parameters) {
    return this.fn(parameters);
  };
  
  module.exports = DerivedHelper;
  
  
  /***/ }),
  /* 315 */
  /***/ (function(module, exports) {
  
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  
  /***/ }),
  /* 316 */
  /***/ (function(module, exports) {
  
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  
  /***/ }),
  /* 317 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var forEach = __webpack_require__(35);
  var map = __webpack_require__(17);
  var reduce = __webpack_require__(49);
  var merge = __webpack_require__(103);
  var isArray = __webpack_require__(0);
  
  var requestBuilder = {
    /**
     * Get all the queries to send to the client, those queries can used directly
     * with the Algolia client.
     * @private
     * @return {object[]} The queries
     */
    _getQueries: function getQueries(index, state) {
      var queries = [];
  
      // One query for the hits
      queries.push({
        indexName: index,
        params: requestBuilder._getHitsSearchParams(state)
      });
  
      // One for each disjunctive facets
      forEach(state.getRefinedDisjunctiveFacets(), function(refinedFacet) {
        queries.push({
          indexName: index,
          params: requestBuilder._getDisjunctiveFacetSearchParams(state, refinedFacet)
        });
      });
  
      // maybe more to get the root level of hierarchical facets when activated
      forEach(state.getRefinedHierarchicalFacets(), function(refinedFacet) {
        var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet);
  
        var currentRefinement = state.getHierarchicalRefinement(refinedFacet);
        // if we are deeper than level 0 (starting from `beer > IPA`)
        // we want to get the root values
        var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
        if (currentRefinement.length > 0 && currentRefinement[0].split(separator).length > 1) {
          queries.push({
            indexName: index,
            params: requestBuilder._getDisjunctiveFacetSearchParams(state, refinedFacet, true)
          });
        }
      });
  
      return queries;
    },
  
    /**
     * Build search parameters used to fetch hits
     * @private
     * @return {object.<string, any>}
     */
    _getHitsSearchParams: function(state) {
      var facets = state.facets
        .concat(state.disjunctiveFacets)
        .concat(requestBuilder._getHitsHierarchicalFacetsAttributes(state));
  
  
      var facetFilters = requestBuilder._getFacetFilters(state);
      var numericFilters = requestBuilder._getNumericFilters(state);
      var tagFilters = requestBuilder._getTagFilters(state);
      var additionalParams = {
        facets: facets,
        tagFilters: tagFilters
      };
  
      if (facetFilters.length > 0) {
        additionalParams.facetFilters = facetFilters;
      }
  
      if (numericFilters.length > 0) {
        additionalParams.numericFilters = numericFilters;
      }
  
      return merge(state.getQueryParams(), additionalParams);
    },
  
    /**
     * Build search parameters used to fetch a disjunctive facet
     * @private
     * @param  {string} facet the associated facet name
     * @param  {boolean} hierarchicalRootLevel ?? FIXME
     * @return {object}
     */
    _getDisjunctiveFacetSearchParams: function(state, facet, hierarchicalRootLevel) {
      var facetFilters = requestBuilder._getFacetFilters(state, facet, hierarchicalRootLevel);
      var numericFilters = requestBuilder._getNumericFilters(state, facet);
      var tagFilters = requestBuilder._getTagFilters(state);
      var additionalParams = {
        hitsPerPage: 1,
        page: 0,
        attributesToRetrieve: [],
        attributesToHighlight: [],
        attributesToSnippet: [],
        tagFilters: tagFilters
      };
  
      var hierarchicalFacet = state.getHierarchicalFacetByName(facet);
  
      if (hierarchicalFacet) {
        additionalParams.facets = requestBuilder._getDisjunctiveHierarchicalFacetAttribute(
          state,
          hierarchicalFacet,
          hierarchicalRootLevel
        );
      } else {
        additionalParams.facets = facet;
      }
  
      if (numericFilters.length > 0) {
        additionalParams.numericFilters = numericFilters;
      }
  
      if (facetFilters.length > 0) {
        additionalParams.facetFilters = facetFilters;
      }
  
      return merge(state.getQueryParams(), additionalParams);
    },
  
    /**
     * Return the numeric filters in an algolia request fashion
     * @private
     * @param {string} [facetName] the name of the attribute for which the filters should be excluded
     * @return {string[]} the numeric filters in the algolia format
     */
    _getNumericFilters: function(state, facetName) {
      if (state.numericFilters) {
        return state.numericFilters;
      }
  
      var numericFilters = [];
  
      forEach(state.numericRefinements, function(operators, attribute) {
        forEach(operators, function(values, operator) {
          if (facetName !== attribute) {
            forEach(values, function(value) {
              if (isArray(value)) {
                var vs = map(value, function(v) {
                  return attribute + operator + v;
                });
                numericFilters.push(vs);
              } else {
                numericFilters.push(attribute + operator + value);
              }
            });
          }
        });
      });
  
      return numericFilters;
    },
  
    /**
     * Return the tags filters depending
     * @private
     * @return {string}
     */
    _getTagFilters: function(state) {
      if (state.tagFilters) {
        return state.tagFilters;
      }
  
      return state.tagRefinements.join(',');
    },
  
  
    /**
     * Build facetFilters parameter based on current refinements. The array returned
     * contains strings representing the facet filters in the algolia format.
     * @private
     * @param  {string} [facet] if set, the current disjunctive facet
     * @return {array.<string>}
     */
    _getFacetFilters: function(state, facet, hierarchicalRootLevel) {
      var facetFilters = [];
  
      forEach(state.facetsRefinements, function(facetValues, facetName) {
        forEach(facetValues, function(facetValue) {
          facetFilters.push(facetName + ':' + facetValue);
        });
      });
  
      forEach(state.facetsExcludes, function(facetValues, facetName) {
        forEach(facetValues, function(facetValue) {
          facetFilters.push(facetName + ':-' + facetValue);
        });
      });
  
      forEach(state.disjunctiveFacetsRefinements, function(facetValues, facetName) {
        if (facetName === facet || !facetValues || facetValues.length === 0) return;
        var orFilters = [];
  
        forEach(facetValues, function(facetValue) {
          orFilters.push(facetName + ':' + facetValue);
        });
  
        facetFilters.push(orFilters);
      });
  
      forEach(state.hierarchicalFacetsRefinements, function(facetValues, facetName) {
        var facetValue = facetValues[0];
  
        if (facetValue === undefined) {
          return;
        }
  
        var hierarchicalFacet = state.getHierarchicalFacetByName(facetName);
        var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
        var rootPath = state._getHierarchicalRootPath(hierarchicalFacet);
        var attributeToRefine;
        var attributesIndex;
  
        // we ask for parent facet values only when the `facet` is the current hierarchical facet
        if (facet === facetName) {
          // if we are at the root level already, no need to ask for facet values, we get them from
          // the hits query
          if (facetValue.indexOf(separator) === -1 || (!rootPath && hierarchicalRootLevel === true) ||
            (rootPath && rootPath.split(separator).length === facetValue.split(separator).length)) {
            return;
          }
  
          if (!rootPath) {
            attributesIndex = facetValue.split(separator).length - 2;
            facetValue = facetValue.slice(0, facetValue.lastIndexOf(separator));
          } else {
            attributesIndex = rootPath.split(separator).length - 1;
            facetValue = rootPath;
          }
  
          attributeToRefine = hierarchicalFacet.attributes[attributesIndex];
        } else {
          attributesIndex = facetValue.split(separator).length - 1;
  
          attributeToRefine = hierarchicalFacet.attributes[attributesIndex];
        }
  
        if (attributeToRefine) {
          facetFilters.push([attributeToRefine + ':' + facetValue]);
        }
      });
  
      return facetFilters;
    },
  
    _getHitsHierarchicalFacetsAttributes: function(state) {
      var out = [];
  
      return reduce(
        state.hierarchicalFacets,
        // ask for as much levels as there's hierarchical refinements
        function getHitsAttributesForHierarchicalFacet(allAttributes, hierarchicalFacet) {
          var hierarchicalRefinement = state.getHierarchicalRefinement(hierarchicalFacet.name)[0];
  
          // if no refinement, ask for root level
          if (!hierarchicalRefinement) {
            allAttributes.push(hierarchicalFacet.attributes[0]);
            return allAttributes;
          }
  
          var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
          var level = hierarchicalRefinement.split(separator).length;
          var newAttributes = hierarchicalFacet.attributes.slice(0, level + 1);
  
          return allAttributes.concat(newAttributes);
        }, out);
    },
  
    _getDisjunctiveHierarchicalFacetAttribute: function(state, hierarchicalFacet, rootLevel) {
      var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet);
      if (rootLevel === true) {
        var rootPath = state._getHierarchicalRootPath(hierarchicalFacet);
        var attributeIndex = 0;
  
        if (rootPath) {
          attributeIndex = rootPath.split(separator).length;
        }
        return [hierarchicalFacet.attributes[attributeIndex]];
      }
  
      var hierarchicalRefinement = state.getHierarchicalRefinement(hierarchicalFacet.name)[0] || '';
      // if refinement is 'beers > IPA > Flying dog',
      // then we want `facets: ['beers > IPA']` as disjunctive facet (parent level values)
  
      var parentLevel = hierarchicalRefinement.split(separator).length - 1;
      return hierarchicalFacet.attributes.slice(0, parentLevel + 1);
    },
  
    getSearchForFacetQuery: function(facetName, query, maxFacetHits, state) {
      var stateForSearchForFacetValues = state.isDisjunctiveFacet(facetName) ?
        state.clearRefinements(facetName) :
        state;
      var searchForFacetSearchParameters = {
        facetQuery: query,
        facetName: facetName
      };
      if (typeof maxFacetHits === 'number') {
        searchForFacetSearchParameters.maxFacetHits = maxFacetHits;
      }
      var queries = merge(requestBuilder._getHitsSearchParams(stateForSearchForFacetValues), searchForFacetSearchParameters);
      return queries;
    }
  };
  
  module.exports = requestBuilder;
  
  
  /***/ }),
  /* 318 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var invert = __webpack_require__(206);
  var keys = __webpack_require__(9);
  
  var keys2Short = {
    advancedSyntax: 'aS',
    allowTyposOnNumericTokens: 'aTONT',
    analyticsTags: 'aT',
    analytics: 'a',
    aroundLatLngViaIP: 'aLLVIP',
    aroundLatLng: 'aLL',
    aroundPrecision: 'aP',
    aroundRadius: 'aR',
    attributesToHighlight: 'aTH',
    attributesToRetrieve: 'aTR',
    attributesToSnippet: 'aTS',
    disjunctiveFacetsRefinements: 'dFR',
    disjunctiveFacets: 'dF',
    distinct: 'd',
    facetsExcludes: 'fE',
    facetsRefinements: 'fR',
    facets: 'f',
    getRankingInfo: 'gRI',
    hierarchicalFacetsRefinements: 'hFR',
    hierarchicalFacets: 'hF',
    highlightPostTag: 'hPoT',
    highlightPreTag: 'hPrT',
    hitsPerPage: 'hPP',
    ignorePlurals: 'iP',
    index: 'idx',
    insideBoundingBox: 'iBB',
    insidePolygon: 'iPg',
    length: 'l',
    maxValuesPerFacet: 'mVPF',
    minimumAroundRadius: 'mAR',
    minProximity: 'mP',
    minWordSizefor1Typo: 'mWS1T',
    minWordSizefor2Typos: 'mWS2T',
    numericFilters: 'nF',
    numericRefinements: 'nR',
    offset: 'o',
    optionalWords: 'oW',
    page: 'p',
    queryType: 'qT',
    query: 'q',
    removeWordsIfNoResults: 'rWINR',
    replaceSynonymsInHighlight: 'rSIH',
    restrictSearchableAttributes: 'rSA',
    synonyms: 's',
    tagFilters: 'tF',
    tagRefinements: 'tR',
    typoTolerance: 'tT',
    optionalTagFilters: 'oTF',
    optionalFacetFilters: 'oFF',
    snippetEllipsisText: 'sET',
    disableExactOnAttributes: 'dEOA',
    enableExactOnSingleWordQuery: 'eEOSWQ'
  };
  
  var short2Keys = invert(keys2Short);
  
  module.exports = {
    /**
     * All the keys of the state, encoded.
     * @const
     */
    ENCODED_PARAMETERS: keys(short2Keys),
    /**
     * Decode a shorten attribute
     * @param {string} shortKey the shorten attribute
     * @return {string} the decoded attribute, undefined otherwise
     */
    decode: function(shortKey) {
      return short2Keys[shortKey];
    },
    /**
     * Encode an attribute into a short version
     * @param {string} key the attribute
     * @return {string} the shorten attribute
     */
    encode: function(key) {
      return keys2Short[key];
    }
  };
  
  
  /***/ }),
  /* 319 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseInverter = __webpack_require__(320);
  
  /**
   * Creates a function like `_.invertBy`.
   *
   * @private
   * @param {Function} setter The function to set accumulator values.
   * @param {Function} toIteratee The function to resolve iteratees.
   * @returns {Function} Returns the new inverter function.
   */
  function createInverter(setter, toIteratee) {
    return function(object, iteratee) {
      return baseInverter(object, setter, toIteratee(iteratee), {});
    };
  }
  
  module.exports = createInverter;
  
  
  /***/ }),
  /* 320 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseForOwn = __webpack_require__(48);
  
  /**
   * The base implementation of `_.invert` and `_.invertBy` which inverts
   * `object` with values transformed by `iteratee` and set by `setter`.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} setter The function to set `accumulator` values.
   * @param {Function} iteratee The iteratee to transform values.
   * @param {Object} accumulator The initial inverted object.
   * @returns {Function} Returns `accumulator`.
   */
  function baseInverter(object, setter, iteratee, accumulator) {
    baseForOwn(object, function(value, key, object) {
      setter(accumulator, iteratee(value), key, object);
    });
    return accumulator;
  }
  
  module.exports = baseInverter;
  
  
  /***/ }),
  /* 321 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var stringify = __webpack_require__(322);
  var parse = __webpack_require__(323);
  var formats = __webpack_require__(207);
  
  module.exports = {
      formats: formats,
      parse: parse,
      stringify: stringify
  };
  
  
  /***/ }),
  /* 322 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var utils = __webpack_require__(108);
  var formats = __webpack_require__(207);
  
  var arrayPrefixGenerators = {
      brackets: function brackets(prefix) {
          return prefix + '[]';
      },
      indices: function indices(prefix, key) {
          return prefix + '[' + key + ']';
      },
      repeat: function repeat(prefix) {
          return prefix;
      }
  };
  
  var toISO = Date.prototype.toISOString;
  
  var defaults = {
      delimiter: '&',
      encode: true,
      encoder: utils.encode,
      serializeDate: function serializeDate(date) {
          return toISO.call(date);
      },
      skipNulls: false,
      strictNullHandling: false
  };
  
  var stringify = function stringify(object, prefix, generateArrayPrefix, strictNullHandling, skipNulls, encoder, filter, sort, allowDots, serializeDate, formatter) {
      var obj = object;
      if (typeof filter === 'function') {
          obj = filter(prefix, obj);
      } else if (obj instanceof Date) {
          obj = serializeDate(obj);
      } else if (obj === null) {
          if (strictNullHandling) {
              return encoder ? encoder(prefix) : prefix;
          }
  
          obj = '';
      }
  
      if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean' || utils.isBuffer(obj)) {
          if (encoder) {
              return [formatter(encoder(prefix)) + '=' + formatter(encoder(obj))];
          }
          return [formatter(prefix) + '=' + formatter(String(obj))];
      }
  
      var values = [];
  
      if (typeof obj === 'undefined') {
          return values;
      }
  
      var objKeys;
      if (Array.isArray(filter)) {
          objKeys = filter;
      } else {
          var keys = Object.keys(obj);
          objKeys = sort ? keys.sort(sort) : keys;
      }
  
      for (var i = 0; i < objKeys.length; ++i) {
          var key = objKeys[i];
  
          if (skipNulls && obj[key] === null) {
              continue;
          }
  
          if (Array.isArray(obj)) {
              values = values.concat(stringify(
                  obj[key],
                  generateArrayPrefix(prefix, key),
                  generateArrayPrefix,
                  strictNullHandling,
                  skipNulls,
                  encoder,
                  filter,
                  sort,
                  allowDots,
                  serializeDate,
                  formatter
              ));
          } else {
              values = values.concat(stringify(
                  obj[key],
                  prefix + (allowDots ? '.' + key : '[' + key + ']'),
                  generateArrayPrefix,
                  strictNullHandling,
                  skipNulls,
                  encoder,
                  filter,
                  sort,
                  allowDots,
                  serializeDate,
                  formatter
              ));
          }
      }
  
      return values;
  };
  
  module.exports = function (object, opts) {
      var obj = object;
      var options = opts || {};
      var delimiter = typeof options.delimiter === 'undefined' ? defaults.delimiter : options.delimiter;
      var strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
      var skipNulls = typeof options.skipNulls === 'boolean' ? options.skipNulls : defaults.skipNulls;
      var encode = typeof options.encode === 'boolean' ? options.encode : defaults.encode;
      var encoder = encode ? (typeof options.encoder === 'function' ? options.encoder : defaults.encoder) : null;
      var sort = typeof options.sort === 'function' ? options.sort : null;
      var allowDots = typeof options.allowDots === 'undefined' ? false : options.allowDots;
      var serializeDate = typeof options.serializeDate === 'function' ? options.serializeDate : defaults.serializeDate;
      if (typeof options.format === 'undefined') {
          options.format = formats.default;
      } else if (!Object.prototype.hasOwnProperty.call(formats.formatters, options.format)) {
          throw new TypeError('Unknown format option provided.');
      }
      var formatter = formats.formatters[options.format];
      var objKeys;
      var filter;
  
      if (options.encoder !== null && options.encoder !== undefined && typeof options.encoder !== 'function') {
          throw new TypeError('Encoder has to be a function.');
      }
  
      if (typeof options.filter === 'function') {
          filter = options.filter;
          obj = filter('', obj);
      } else if (Array.isArray(options.filter)) {
          filter = options.filter;
          objKeys = filter;
      }
  
      var keys = [];
  
      if (typeof obj !== 'object' || obj === null) {
          return '';
      }
  
      var arrayFormat;
      if (options.arrayFormat in arrayPrefixGenerators) {
          arrayFormat = options.arrayFormat;
      } else if ('indices' in options) {
          arrayFormat = options.indices ? 'indices' : 'repeat';
      } else {
          arrayFormat = 'indices';
      }
  
      var generateArrayPrefix = arrayPrefixGenerators[arrayFormat];
  
      if (!objKeys) {
          objKeys = Object.keys(obj);
      }
  
      if (sort) {
          objKeys.sort(sort);
      }
  
      for (var i = 0; i < objKeys.length; ++i) {
          var key = objKeys[i];
  
          if (skipNulls && obj[key] === null) {
              continue;
          }
  
          keys = keys.concat(stringify(
              obj[key],
              key,
              generateArrayPrefix,
              strictNullHandling,
              skipNulls,
              encoder,
              filter,
              sort,
              allowDots,
              serializeDate,
              formatter
          ));
      }
  
      return keys.join(delimiter);
  };
  
  
  /***/ }),
  /* 323 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  var utils = __webpack_require__(108);
  
  var has = Object.prototype.hasOwnProperty;
  
  var defaults = {
      allowDots: false,
      allowPrototypes: false,
      arrayLimit: 20,
      decoder: utils.decode,
      delimiter: '&',
      depth: 5,
      parameterLimit: 1000,
      plainObjects: false,
      strictNullHandling: false
  };
  
  var parseValues = function parseValues(str, options) {
      var obj = {};
      var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit);
  
      for (var i = 0; i < parts.length; ++i) {
          var part = parts[i];
          var pos = part.indexOf(']=') === -1 ? part.indexOf('=') : part.indexOf(']=') + 1;
  
          var key, val;
          if (pos === -1) {
              key = options.decoder(part);
              val = options.strictNullHandling ? null : '';
          } else {
              key = options.decoder(part.slice(0, pos));
              val = options.decoder(part.slice(pos + 1));
          }
          if (has.call(obj, key)) {
              obj[key] = [].concat(obj[key]).concat(val);
          } else {
              obj[key] = val;
          }
      }
  
      return obj;
  };
  
  var parseObject = function parseObject(chain, val, options) {
      if (!chain.length) {
          return val;
      }
  
      var root = chain.shift();
  
      var obj;
      if (root === '[]') {
          obj = [];
          obj = obj.concat(parseObject(chain, val, options));
      } else {
          obj = options.plainObjects ? Object.create(null) : {};
          var cleanRoot = root[0] === '[' && root[root.length - 1] === ']' ? root.slice(1, root.length - 1) : root;
          var index = parseInt(cleanRoot, 10);
          if (
              !isNaN(index) &&
              root !== cleanRoot &&
              String(index) === cleanRoot &&
              index >= 0 &&
              (options.parseArrays && index <= options.arrayLimit)
          ) {
              obj = [];
              obj[index] = parseObject(chain, val, options);
          } else {
              obj[cleanRoot] = parseObject(chain, val, options);
          }
      }
  
      return obj;
  };
  
  var parseKeys = function parseKeys(givenKey, val, options) {
      if (!givenKey) {
          return;
      }
  
      // Transform dot notation to bracket notation
      var key = options.allowDots ? givenKey.replace(/\.([^\.\[]+)/g, '[$1]') : givenKey;
  
      // The regex chunks
  
      var parent = /^([^\[\]]*)/;
      var child = /(\[[^\[\]]*\])/g;
  
      // Get the parent
  
      var segment = parent.exec(key);
  
      // Stash the parent if it exists
  
      var keys = [];
      if (segment[1]) {
          // If we aren't using plain objects, optionally prefix keys
          // that would overwrite object prototype properties
          if (!options.plainObjects && has.call(Object.prototype, segment[1])) {
              if (!options.allowPrototypes) {
                  return;
              }
          }
  
          keys.push(segment[1]);
      }
  
      // Loop through children appending to the array until we hit depth
  
      var i = 0;
      while ((segment = child.exec(key)) !== null && i < options.depth) {
          i += 1;
          if (!options.plainObjects && has.call(Object.prototype, segment[1].replace(/\[|\]/g, ''))) {
              if (!options.allowPrototypes) {
                  continue;
              }
          }
          keys.push(segment[1]);
      }
  
      // If there's a remainder, just add whatever is left
  
      if (segment) {
          keys.push('[' + key.slice(segment.index) + ']');
      }
  
      return parseObject(keys, val, options);
  };
  
  module.exports = function (str, opts) {
      var options = opts || {};
  
      if (options.decoder !== null && options.decoder !== undefined && typeof options.decoder !== 'function') {
          throw new TypeError('Decoder has to be a function.');
      }
  
      options.delimiter = typeof options.delimiter === 'string' || utils.isRegExp(options.delimiter) ? options.delimiter : defaults.delimiter;
      options.depth = typeof options.depth === 'number' ? options.depth : defaults.depth;
      options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : defaults.arrayLimit;
      options.parseArrays = options.parseArrays !== false;
      options.decoder = typeof options.decoder === 'function' ? options.decoder : defaults.decoder;
      options.allowDots = typeof options.allowDots === 'boolean' ? options.allowDots : defaults.allowDots;
      options.plainObjects = typeof options.plainObjects === 'boolean' ? options.plainObjects : defaults.plainObjects;
      options.allowPrototypes = typeof options.allowPrototypes === 'boolean' ? options.allowPrototypes : defaults.allowPrototypes;
      options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : defaults.parameterLimit;
      options.strictNullHandling = typeof options.strictNullHandling === 'boolean' ? options.strictNullHandling : defaults.strictNullHandling;
  
      if (str === '' || str === null || typeof str === 'undefined') {
          return options.plainObjects ? Object.create(null) : {};
      }
  
      var tempObj = typeof str === 'string' ? parseValues(str, options) : str;
      var obj = options.plainObjects ? Object.create(null) : {};
  
      // Iterate over the keys and setup the new object
  
      var keys = Object.keys(tempObj);
      for (var i = 0; i < keys.length; ++i) {
          var key = keys[i];
          var newObj = parseKeys(key, tempObj[key], options);
          obj = utils.merge(obj, newObj, options);
      }
  
      return utils.compact(obj);
  };
  
  
  /***/ }),
  /* 324 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseRest = __webpack_require__(25),
      createWrap = __webpack_require__(105),
      getHolder = __webpack_require__(53),
      replaceHolders = __webpack_require__(36);
  
  /** Used to compose bitmasks for function metadata. */
  var WRAP_BIND_FLAG = 1,
      WRAP_PARTIAL_FLAG = 32;
  
  /**
   * Creates a function that invokes `func` with the `this` binding of `thisArg`
   * and `partials` prepended to the arguments it receives.
   *
   * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
   * may be used as a placeholder for partially applied arguments.
   *
   * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
   * property of bound functions.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Function
   * @param {Function} func The function to bind.
   * @param {*} thisArg The `this` binding of `func`.
   * @param {...*} [partials] The arguments to be partially applied.
   * @returns {Function} Returns the new bound function.
   * @example
   *
   * function greet(greeting, punctuation) {
   *   return greeting + ' ' + this.user + punctuation;
   * }
   *
   * var object = { 'user': 'fred' };
   *
   * var bound = _.bind(greet, object, 'hi');
   * bound('!');
   * // => 'hi fred!'
   *
   * // Bound with placeholders.
   * var bound = _.bind(greet, object, _, '!');
   * bound('hi');
   * // => 'hi fred!'
   */
  var bind = baseRest(function(func, thisArg, partials) {
    var bitmask = WRAP_BIND_FLAG;
    if (partials.length) {
      var holders = replaceHolders(partials, getHolder(bind));
      bitmask |= WRAP_PARTIAL_FLAG;
    }
    return createWrap(func, bitmask, thisArg, partials, holders);
  });
  
  // Assign default placeholders.
  bind.placeholder = {};
  
  module.exports = bind;
  
  
  /***/ }),
  /* 325 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var basePickBy = __webpack_require__(202),
      hasIn = __webpack_require__(182);
  
  /**
   * The base implementation of `_.pick` without support for individual
   * property identifiers.
   *
   * @private
   * @param {Object} object The source object.
   * @param {string[]} paths The property paths to pick.
   * @returns {Object} Returns the new object.
   */
  function basePick(object, paths) {
    return basePickBy(object, paths, function(value, path) {
      return hasIn(object, path);
    });
  }
  
  module.exports = basePick;
  
  
  /***/ }),
  /* 326 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseAssignValue = __webpack_require__(46),
      baseForOwn = __webpack_require__(48),
      baseIteratee = __webpack_require__(13);
  
  /**
   * The opposite of `_.mapValues`; this method creates an object with the
   * same values as `object` and keys generated by running each own enumerable
   * string keyed property of `object` thru `iteratee`. The iteratee is invoked
   * with three arguments: (value, key, object).
   *
   * @static
   * @memberOf _
   * @since 3.8.0
   * @category Object
   * @param {Object} object The object to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @returns {Object} Returns the new mapped object.
   * @see _.mapValues
   * @example
   *
   * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
   *   return key + value;
   * });
   * // => { 'a1': 1, 'b2': 2 }
   */
  function mapKeys(object, iteratee) {
    var result = {};
    iteratee = baseIteratee(iteratee, 3);
  
    baseForOwn(object, function(value, key, object) {
      baseAssignValue(result, iteratee(value, key, object), value);
    });
    return result;
  }
  
  module.exports = mapKeys;
  
  
  /***/ }),
  /* 327 */
  /***/ (function(module, exports, __webpack_require__) {
  
  var baseAssignValue = __webpack_require__(46),
      baseForOwn = __webpack_require__(48),
      baseIteratee = __webpack_require__(13);
  
  /**
   * Creates an object with the same keys as `object` and values generated
   * by running each own enumerable string keyed property of `object` thru
   * `iteratee`. The iteratee is invoked with three arguments:
   * (value, key, object).
   *
   * @static
   * @memberOf _
   * @since 2.4.0
   * @category Object
   * @param {Object} object The object to iterate over.
   * @param {Function} [iteratee=_.identity] The function invoked per iteration.
   * @returns {Object} Returns the new mapped object.
   * @see _.mapKeys
   * @example
   *
   * var users = {
   *   'fred':    { 'user': 'fred',    'age': 40 },
   *   'pebbles': { 'user': 'pebbles', 'age': 1 }
   * };
   *
   * _.mapValues(users, function(o) { return o.age; });
   * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
   *
   * // The `_.property` iteratee shorthand.
   * _.mapValues(users, 'age');
   * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
   */
  function mapValues(object, iteratee) {
    var result = {};
    iteratee = baseIteratee(iteratee, 3);
  
    baseForOwn(object, function(value, key, object) {
      baseAssignValue(result, key, iteratee(value, key, object));
    });
    return result;
  }
  
  module.exports = mapValues;
  
  
  /***/ }),
  /* 328 */,
  /* 329 */,
  /* 330 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _get2 = __webpack_require__(72);
  
  var _get3 = _interopRequireDefault(_get2);
  
  exports.default = parseAlgoliaHit;
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * Find an highlighted attribute given an `attributeName` and an `highlightProperty`, parses it,
   * and provided an array of objects with the string value and a boolean if this
   * value is highlighted.
   *
   * In order to use this feature, highlight must be activated in the configuration of
   * the index. The `preTag` and `postTag` attributes are respectively highlightPreTag and
   * highligtPostTag in Algolia configuration.
   *
   * @param {string} preTag - string used to identify the start of an highlighted value
   * @param {string} postTag - string used to identify the end of an highlighted value
   * @param {string} highlightProperty - the property that contains the highlight structure in the results
   * @param {string} attributeName - the highlighted attribute to look for
   * @param {object} hit - the actual hit returned by Algolia.
   * @return {object[]} - An array of {value: string, isDefined: boolean}.
   */
  function parseAlgoliaHit(_ref) {
    var _ref$preTag = _ref.preTag,
        preTag = _ref$preTag === undefined ? '<em>' : _ref$preTag,
        _ref$postTag = _ref.postTag,
        postTag = _ref$postTag === undefined ? '</em>' : _ref$postTag,
        highlightProperty = _ref.highlightProperty,
        attributeName = _ref.attributeName,
        hit = _ref.hit;
  
    if (!hit) throw new Error('`hit`, the matching record, must be provided');
  
    var highlightObject = (0, _get3.default)(hit[highlightProperty], attributeName);
    var highlightedValue = !highlightObject ? '' : highlightObject.value;
  
    return parseHighlightedAttribute({ preTag: preTag, postTag: postTag, highlightedValue: highlightedValue });
  }
  
  /**
   * Parses an highlighted attribute into an array of objects with the string value, and
   * a boolean that indicated if this part is highlighted.
   *
   * @param {string} preTag - string used to identify the start of an highlighted value
   * @param {string} postTag - string used to identify the end of an highlighted value
   * @param {string} highlightedValue - highlighted attribute as returned by Algolia highlight feature
   * @return {object[]} - An array of {value: string, isDefined: boolean}.
   */
  function parseHighlightedAttribute(_ref2) {
    var preTag = _ref2.preTag,
        postTag = _ref2.postTag,
        highlightedValue = _ref2.highlightedValue;
  
    var splitByPreTag = highlightedValue.split(preTag);
    var firstValue = splitByPreTag.shift();
    var elements = firstValue === '' ? [] : [{ value: firstValue, isHighlighted: false }];
  
    if (postTag === preTag) {
      var isHighlighted = true;
      splitByPreTag.forEach(function (split) {
        elements.push({ value: split, isHighlighted: isHighlighted });
        isHighlighted = !isHighlighted;
      });
    } else {
      splitByPreTag.forEach(function (split) {
        var splitByPostTag = split.split(postTag);
        elements.push({
          value: splitByPostTag[0],
          isHighlighted: true
        });
  
        if (splitByPostTag[1] !== '') {
          elements.push({
            value: splitByPostTag[1],
            isHighlighted: false
          });
        }
      });
    }
  
    return elements;
  }
  
  /***/ }),
  /* 331 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * connectHits connector provides the logic to create connected
   * components that will render the results retrieved from
   * Algolia.
   *
   * To configure the number of hits retrieved, use [HitsPerPage widget](widgets/HitsPerPage.html),
   * [connectHitsPerPage connector](connectors/connectHitsPerPage.html) or pass the hitsPerPage
   * prop to a [Configure](guide/Search_parameters.html) widget.
   * @name connectHits
   * @kind connector
   * @providedPropType {array.<object>} hits - the records that matched the search state
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaHits',
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
      var hits = results ? results.hits : [];
  
      return { hits: hits };
    },
  
  
    /* Hits needs to be considered as a widget to trigger a search if no others widgets are used.
     * To be considered as a widget you need either getSearchParameters, getMetadata or getTransitionState
     * See createConnector.js
     * */
    getSearchParameters: function getSearchParameters(searchParameters) {
      return searchParameters;
    }
  });
  
  /***/ }),
  /* 332 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  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; };
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId() {
    return 'hitsPerPage';
  }
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId();
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, null, function (currentRefinement) {
      if (typeof currentRefinement === 'string') {
        return parseInt(currentRefinement, 10);
      }
      return currentRefinement;
    });
  }
  
  /**
   * connectHitsPerPage connector provides the logic to create connected
   * components that will allow a user to choose to display more or less results from Algolia.
   * @name connectHitsPerPage
   * @kind connector
   * @propType {number} defaultRefinement - The number of items selected by default
   * @propType {{value: number, label: string}[]} items - List of hits per page options.
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @providedPropType {function} refine - a function to remove a single filter
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the refinement currently applied
   * @providedPropType {array.<{isRefined: boolean, label?: string, value: number}>} items - the list of items the HitsPerPage can display. If no label provided, the value will be displayed.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaHitsPerPage',
  
    propTypes: {
      defaultRefinement: _propTypes2.default.number.isRequired,
      items: _propTypes2.default.arrayOf(_propTypes2.default.shape({
        label: _propTypes2.default.string,
        value: _propTypes2.default.number.isRequired
      })).isRequired,
      transformItems: _propTypes2.default.func
    },
  
    getProvidedProps: function getProvidedProps(props, searchState) {
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      var items = props.items.map(function (item) {
        return item.value === currentRefinement ? _extends({}, item, { isRefined: true }) : _extends({}, item, { isRefined: false });
      });
      return {
        items: props.transformItems ? props.transformItems(items) : items,
        currentRefinement: currentRefinement
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      var id = getId();
      var nextValue = _defineProperty({}, id, nextRefinement);
      var resetPage = true;
      return (0, _indexUtils.refineValue)(searchState, nextValue, this.context, resetPage);
    },
    cleanUp: function cleanUp(props, searchState) {
      return (0, _indexUtils.cleanUpValue)(searchState, this.context, getId());
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      return searchParameters.setHitsPerPage(getCurrentRefinement(props, searchState, this.context));
    },
    getMetadata: function getMetadata() {
      return { id: getId() };
    }
  });
  
  /***/ }),
  /* 333 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  
  function getId() {
    return 'page';
  }
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId();
    var page = 1;
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, page, function (currentRefinement) {
      if (typeof currentRefinement === 'string') {
        currentRefinement = parseInt(currentRefinement, 10);
      }
      return currentRefinement;
    });
  }
  
  /**
   * InfiniteHits connector provides the logic to create connected
   * components that will render an continuous list of results retrieved from
   * Algolia. This connector provides a function to load more results.
   * @name connectInfiniteHits
   * @kind connector
   * @providedPropType {array.<object>} hits - the records that matched the search state
   * @providedPropType {boolean} hasMore - indicates if there are more pages to load
   * @providedPropType {function} refine - call to load more results
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaInfiniteHits',
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      if (!results) {
        this._allResults = [];
        return {
          hits: this._allResults,
          hasMore: false
        };
      }
  
      var hits = results.hits,
          page = results.page,
          nbPages = results.nbPages;
  
  
      if (page === 0) {
        this._allResults = hits;
      } else {
        if (page > this.previousPage) {
          this._allResults = [].concat(_toConsumableArray(this._allResults), _toConsumableArray(hits));
        } else if (page < this.previousPage) {
          this._allResults = hits;
        }
        // If it is the same page we do not touch the page result list
      }
  
      var lastPageIndex = nbPages - 1;
      var hasMore = page < lastPageIndex;
      this.previousPage = page;
      return {
        hits: this._allResults,
        hasMore: hasMore
      };
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      return searchParameters.setQueryParameters({
        page: getCurrentRefinement(props, searchState, this.context) - 1
      });
    },
    refine: function refine(props, searchState) {
      var id = getId();
      var nextPage = getCurrentRefinement(props, searchState, this.context) + 1;
      var nextValue = _defineProperty({}, id, nextPage);
      var resetPage = false;
      return (0, _indexUtils.refineValue)(searchState, nextValue, this.context, resetPage);
    }
  });
  
  /***/ }),
  /* 334 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _orderBy2 = __webpack_require__(104);
  
  var _orderBy3 = _interopRequireDefault(_orderBy2);
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  var namespace = 'menu';
  
  function getId(props) {
    return props.attributeName;
  }
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), null, function (currentRefinement) {
      if (currentRefinement === '') {
        return null;
      }
      return currentRefinement;
    });
  }
  
  function getValue(name, props, searchState, context) {
    var currentRefinement = getCurrentRefinement(props, searchState, context);
    return name === currentRefinement ? '' : name;
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId(props);
    var nextValue = _defineProperty({}, id, nextRefinement ? nextRefinement : '');
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  
  var sortBy = ['count:desc', 'name:asc'];
  
  /**
   * connectMenu connector provides the logic to build a widget that will
   * give the user the ability to choose a single value for a specific facet.
   * @name connectMenu
   * @requirements The attribute passed to the `attributeName` prop must be present in "attributes for faceting"
   * on the Algolia dashboard or configured as `attributesForFaceting` via a set settings call to the Algolia API.
   * @kind connector
   * @propType {string} attributeName - the name of the attribute in the record
   * @propType {boolean} [showMore=false] - true if the component should display a button that will expand the number of items
   * @propType {number} [limitMin=10] - the minimum number of diplayed items
   * @propType {number} [limitMax=20] - the maximun number of displayed items. Only used when showMore is set to `true`
   * @propType {string} [defaultRefinement] - the value of the item selected by default
   * @propType {boolean} [withSearchBox=false] - allow search inside values
   * @providedPropType {function} refine - a function to toggle a refinement
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the refinement currently applied
   * @providedPropType {array.<{count: number, isRefined: boolean, label: string, value: string}>} items - the list of items the Menu can display.
   * @providedPropType {function} searchForItems - a function to toggle a search inside items values
   * @providedPropType {boolean} isFromSearch - a boolean that says if the `items` props contains facet values from the global search or from the search inside items.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaMenu',
  
    propTypes: {
      attributeName: _propTypes2.default.string.isRequired,
      showMore: _propTypes2.default.bool,
      limitMin: _propTypes2.default.number,
      limitMax: _propTypes2.default.number,
      defaultRefinement: _propTypes2.default.string,
      transformItems: _propTypes2.default.func,
      withSearchBox: _propTypes2.default.bool,
      searchForFacetValues: _propTypes2.default.bool //@deprecated
    },
  
    defaultProps: {
      showMore: false,
      limitMin: 10,
      limitMax: 20
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults, meta, searchForFacetValuesResults) {
      var _this = this;
  
      var attributeName = props.attributeName,
          showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
      var limit = showMore ? limitMax : limitMin;
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      var canRefine = Boolean(results) && Boolean(results.getFacetByName(attributeName));
  
      var isFromSearch = Boolean(searchForFacetValuesResults && searchForFacetValuesResults[attributeName] && searchForFacetValuesResults.query !== '');
      var withSearchBox = props.withSearchBox || props.searchForFacetValues;
      if (false) {
        // eslint-disable-next-line no-console
        console.warn('react-instantsearch: `searchForFacetValues` has been renamed to' + '`withSearchBox`, this will break in the next major version.');
      }
      // Search For Facet Values is not available with derived helper (used for multi index search)
      if (props.withSearchBox && this.context.multiIndexContext) {
        throw new Error('react-instantsearch: searching in *List is not available when used inside a' + ' multi index context');
      }
  
      if (!canRefine) {
        return {
          items: [],
          currentRefinement: getCurrentRefinement(props, searchState, this.context),
          isFromSearch: isFromSearch,
          withSearchBox: withSearchBox,
          canRefine: canRefine
        };
      }
  
      var items = isFromSearch ? searchForFacetValuesResults[attributeName].map(function (v) {
        return {
          label: v.value,
          value: getValue(v.value, props, searchState, _this.context),
          _highlightResult: { label: { value: v.highlighted } },
          count: v.count,
          isRefined: v.isRefined
        };
      }) : results.getFacetValues(attributeName, { sortBy: sortBy }).map(function (v) {
        return {
          label: v.name,
          value: getValue(v.name, props, searchState, _this.context),
          count: v.count,
          isRefined: v.isRefined
        };
      });
  
      var sortedItems = withSearchBox && !isFromSearch ? (0, _orderBy3.default)(items, ['isRefined', 'count', 'label'], ['desc', 'desc', 'asc']) : items;
      var transformedItems = props.transformItems ? props.transformItems(sortedItems) : sortedItems;
      return {
        items: transformedItems.slice(0, limit),
        currentRefinement: getCurrentRefinement(props, searchState, this.context),
        isFromSearch: isFromSearch,
        withSearchBox: withSearchBox,
        canRefine: items.length > 0
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    searchForFacetValues: function searchForFacetValues(props, searchState, nextRefinement) {
      return { facetName: props.attributeName, query: nextRefinement };
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var attributeName = props.attributeName,
          showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
      var limit = showMore ? limitMax : limitMin;
  
      searchParameters = searchParameters.setQueryParameters({
        maxValuesPerFacet: Math.max(searchParameters.maxValuesPerFacet || 0, limit)
      });
  
      searchParameters = searchParameters.addDisjunctiveFacet(attributeName);
  
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      if (currentRefinement !== null) {
        searchParameters = searchParameters.addDisjunctiveFacetRefinement(attributeName, currentRefinement);
      }
  
      return searchParameters;
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this2 = this;
  
      var id = getId(props);
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      return {
        id: id,
        index: (0, _indexUtils.getIndex)(this.context),
        items: currentRefinement === null ? [] : [{
          label: props.attributeName + ': ' + currentRefinement,
          attributeName: props.attributeName,
          value: function value(nextState) {
            return _refine(props, nextState, '', _this2.context);
          },
          currentRefinement: currentRefinement
        }]
      };
    }
  });
  
  /***/ }),
  /* 335 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _isEmpty2 = __webpack_require__(16);
  
  var _isEmpty3 = _interopRequireDefault(_isEmpty2);
  
  var _find3 = __webpack_require__(52);
  
  var _find4 = _interopRequireDefault(_find3);
  
  var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _indexUtils = __webpack_require__(5);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function stringifyItem(item) {
    if (typeof item.start === 'undefined' && typeof item.end === 'undefined') {
      return '';
    }
    return (item.start ? item.start : '') + ':' + (item.end ? item.end : '');
  }
  
  function parseItem(value) {
    if (value.length === 0) {
      return { start: null, end: null };
    }
  
    var _value$split = value.split(':'),
        _value$split2 = _slicedToArray(_value$split, 2),
        startStr = _value$split2[0],
        endStr = _value$split2[1];
  
    return {
      start: startStr.length > 0 ? parseInt(startStr, 10) : null,
      end: endStr.length > 0 ? parseInt(endStr, 10) : null
    };
  }
  
  var namespace = 'multiRange';
  
  function getId(props) {
    return props.attributeName;
  }
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), '', function (currentRefinement) {
      if (currentRefinement === '') {
        return '';
      }
      return currentRefinement;
    });
  }
  
  function isRefinementsRangeIncludesInsideItemRange(stats, start, end) {
    return stats.min > start && stats.min < end || stats.max > start && stats.max < end;
  }
  
  function isItemRangeIncludedInsideRefinementsRange(stats, start, end) {
    return start > stats.min && start < stats.max || end > stats.min && end < stats.max;
  }
  
  function itemHasRefinement(attributeName, results, value) {
    var stats = results.getFacetByName(attributeName) ? results.getFacetStats(attributeName) : null;
    var range = value.split(':');
    var start = Number(range[0]) === 0 || value === '' ? Number.NEGATIVE_INFINITY : Number(range[0]);
    var end = Number(range[1]) === 0 || value === '' ? Number.POSITIVE_INFINITY : Number(range[1]);
    return !(Boolean(stats) && (isRefinementsRangeIncludesInsideItemRange(stats, start, end) || isItemRangeIncludedInsideRefinementsRange(stats, start, end)));
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var nextValue = _defineProperty({}, getId(props, searchState), nextRefinement);
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  
  /**
   * connectMultiRange connector provides the logic to build a widget that will
   * give the user the ability to select a range value for a numeric attribute.
   * Ranges are defined statically.
   * @name connectMultiRange
   * @requirements The attribute passed to the `attributeName` prop must be holding numerical values.
   * @kind connector
   * @propType {string} attributeName - the name of the attribute in the records
   * @propType {{label: string, start: number, end: number}[]} items - List of options. With a text label, and upper and lower bounds.
   * @propType {string} [defaultRefinement] - the value of the item selected by default, follow the shape of a `string` with a pattern of `'{start}:{end}'`.
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @providedPropType {function} refine - a function to select a range.
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the refinement currently applied.  follow the shape of a `string` with a pattern of `'{start}:{end}'` which corresponds to the current selected item. For instance, when the selected item is `{start: 10, end: 20}`, the searchState of the widget is `'10:20'`. When `start` isn't defined, the searchState of the widget is `':{end}'`, and the same way around when `end` isn't defined. However, when neither `start` nor `end` are defined, the searchState is an empty string.
   * @providedPropType {array.<{isRefined: boolean, label: string, value: string, isRefined: boolean, noRefinement: boolean}>} items - the list of ranges the MultiRange can display.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaMultiRange',
  
    propTypes: {
      id: _propTypes2.default.string,
      attributeName: _propTypes2.default.string.isRequired,
      items: _propTypes2.default.arrayOf(_propTypes2.default.shape({
        label: _propTypes2.default.node,
        start: _propTypes2.default.number,
        end: _propTypes2.default.number
      })).isRequired,
      transformItems: _propTypes2.default.func
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var attributeName = props.attributeName;
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      var items = props.items.map(function (item) {
        var value = stringifyItem(item);
        return {
          label: item.label,
          value: value,
          isRefined: value === currentRefinement,
          noRefinement: results ? itemHasRefinement(getId(props), results, value) : false
        };
      });
  
      var stats = results && results.getFacetByName(attributeName) ? results.getFacetStats(attributeName) : null;
      var refinedItem = (0, _find4.default)(items, function (item) {
        return item.isRefined === true;
      });
      if (!items.some(function (item) {
        return item.value === '';
      })) {
        items.push({
          value: '',
          isRefined: (0, _isEmpty3.default)(refinedItem),
          noRefinement: !stats,
          label: 'All'
        });
      }
  
      return {
        items: props.transformItems ? props.transformItems(items) : items,
        currentRefinement: currentRefinement,
        canRefine: items.length > 0 && items.some(function (item) {
          return item.noRefinement === false;
        })
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var attributeName = props.attributeName;
  
      var _parseItem = parseItem(getCurrentRefinement(props, searchState, this.context)),
          start = _parseItem.start,
          end = _parseItem.end;
  
      searchParameters = searchParameters.addDisjunctiveFacet(attributeName);
  
      if (start) {
        searchParameters = searchParameters.addNumericRefinement(attributeName, '>=', start);
      }
      if (end) {
        searchParameters = searchParameters.addNumericRefinement(attributeName, '<=', end);
      }
      return searchParameters;
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this = this;
  
      var id = getId(props);
      var value = getCurrentRefinement(props, searchState, this.context);
      var items = [];
      var index = (0, _indexUtils.getIndex)(this.context);
      if (value !== '') {
        var _find2 = (0, _find4.default)(props.items, function (item) {
          return stringifyItem(item) === value;
        }),
            label = _find2.label;
  
        items.push({
          label: props.attributeName + ': ' + label,
          attributeName: props.attributeName,
          currentRefinement: label,
          value: function value(nextState) {
            return _refine(props, nextState, '', _this.context);
          }
        });
      }
      return { id: id, index: index, items: items };
    }
  });
  
  /***/ }),
  /* 336 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _indexUtils = __webpack_require__(5);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId() {
    return 'page';
  }
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId();
    var page = 1;
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, page, function (currentRefinement) {
      if (typeof currentRefinement === 'string') {
        return parseInt(currentRefinement, 10);
      }
      return currentRefinement;
    });
  }
  
  function _refine(props, searchState, nextPage, context) {
    var id = getId();
    var nextValue = _defineProperty({}, id, nextPage);
    var resetPage = false;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage);
  }
  
  /**
   * connectPagination connector provides the logic to build a widget that will
   * let the user displays hits corresponding to a certain page.
   * @name connectPagination
   * @kind connector
   * @propType {boolean} [showFirst=true] - Display the first page link.
   * @propType {boolean} [showLast=false] - Display the last page link.
   * @propType {boolean} [showPrevious=true] - Display the previous page link.
   * @propType {boolean} [showNext=true] - Display the next page link.
   * @propType {number} [pagesPadding=3] - How many page links to display around the current page.
   * @propType {number} [maxPages=Infinity] - Maximum number of pages to display.
   * @providedPropType {function} refine - a function to remove a single filter
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {number} nbPages - the total of existing pages
   * @providedPropType {number} currentRefinement - the page refinement currently applied
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaPagination',
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      if (!results) {
        return null;
      }
  
      var nbPages = results.nbPages;
      return {
        nbPages: nbPages,
        currentRefinement: getCurrentRefinement(props, searchState, this.context),
        canRefine: nbPages > 1
      };
    },
    refine: function refine(props, searchState, nextPage) {
      return _refine(props, searchState, nextPage, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return (0, _indexUtils.cleanUpValue)(searchState, this.context, getId());
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      return searchParameters.setPage(getCurrentRefinement(props, searchState, this.context) - 1);
    },
    getMetadata: function getMetadata() {
      return { id: getId() };
    }
  });
  
  /***/ }),
  /* 337 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * connectPoweredBy connector provides the logic to build a widget that
   * will display a link to algolia.
   * @name connectPoweredBy
   * @kind connector
   * @providedPropType {string} url - the url to redirect to algolia
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaPoweredBy',
  
    propTypes: {},
  
    getProvidedProps: function getProvidedProps() {
      var url = 'https://www.algolia.com/?' + 'utm_source=react-instantsearch&' + 'utm_medium=website&' + ('utm_content=' + location.hostname + '&') + 'utm_campaign=poweredby';
      return { url: url };
    }
  });
  
  /***/ }),
  /* 338 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _indexUtils = __webpack_require__(5);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  var namespace = 'refinementList';
  
  function getId(props) {
    return props.attributeName;
  }
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), [], function (currentRefinement) {
      if (typeof currentRefinement === 'string') {
        // All items were unselected
        if (currentRefinement === '') {
          return [];
        }
  
        // Only one item was in the searchState but we know it should be an array
        return [currentRefinement];
      }
      return currentRefinement;
    });
  }
  
  function getValue(name, props, searchState, context) {
    var currentRefinement = getCurrentRefinement(props, searchState, context);
    var isAnewValue = currentRefinement.indexOf(name) === -1;
    var nextRefinement = isAnewValue ? currentRefinement.concat([name]) // cannot use .push(), it mutates
    : currentRefinement.filter(function (selectedValue) {
      return selectedValue !== name;
    }); // cannot use .splice(), it mutates
    return nextRefinement;
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId(props);
    // Setting the value to an empty string ensures that it is persisted in
    // the URL as an empty value.
    // This is necessary in the case where `defaultRefinement` contains one
    // item and we try to deselect it. `nextSelected` would be an empty array,
    // which would not be persisted to the URL.
    // {foo: ['bar']} => "foo[0]=bar"
    // {foo: []} => ""
    var nextValue = _defineProperty({}, id, nextRefinement.length > 0 ? nextRefinement : '');
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  /**
   * connectRefinementList connector provides the logic to build a widget that will
   * give the user the ability to choose multiple values for a specific facet.
   * @name connectRefinementList
   * @kind connector
   * @requirements The attribute passed to the `attributeName` prop must be present in "attributes for faceting"
   * on the Algolia dashboard or configured as `attributesForFaceting` via a set settings call to the Algolia API.
   * @propType {string} attributeName - the name of the attribute in the record
   * @propType {boolean} [withSearchBox=false] - allow search inside values
   * @propType {string} [operator=or] - How to apply the refinements. Possible values: 'or' or 'and'.
   * @propType {boolean} [showMore=false] - true if the component should display a button that will expand the number of items
   * @propType {number} [limitMin=10] - the minimum number of displayed items
   * @propType {number} [limitMax=20] - the maximun number of displayed items. Only used when showMore is set to `true`
   * @propType {string[]} defaultRefinement - the values of the items selected by default. The searchState of this widget takes the form of a list of `string`s, which correspond to the values of all selected refinements. However, when there are no refinements selected, the value of the searchState is an empty string.
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @providedPropType {function} refine - a function to toggle a refinement
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string[]} currentRefinement - the refinement currently applied
   * @providedPropType {array.<{count: number, isRefined: boolean, label: string, value: string}>} items - the list of items the RefinementList can display.
   * @providedPropType {function} searchForItems - a function to toggle a search inside items values
   * @providedPropType {boolean} isFromSearch - a boolean that says if the `items` props contains facet values from the global search or from the search inside items.
   */
  
  var sortBy = ['isRefined', 'count:desc', 'name:asc'];
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaRefinementList',
  
    propTypes: {
      id: _propTypes2.default.string,
      attributeName: _propTypes2.default.string.isRequired,
      operator: _propTypes2.default.oneOf(['and', 'or']),
      showMore: _propTypes2.default.bool,
      limitMin: _propTypes2.default.number,
      limitMax: _propTypes2.default.number,
      defaultRefinement: _propTypes2.default.arrayOf(_propTypes2.default.string),
      withSearchBox: _propTypes2.default.bool,
      searchForFacetValues: _propTypes2.default.bool, // @deprecated
      transformItems: _propTypes2.default.func
    },
  
    defaultProps: {
      operator: 'or',
      showMore: false,
      limitMin: 10,
      limitMax: 20
    },
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults, metadata, searchForFacetValuesResults) {
      var _this = this;
  
      var attributeName = props.attributeName,
          showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
      var limit = showMore ? limitMax : limitMin;
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      var canRefine = Boolean(results) && Boolean(results.getFacetByName(attributeName));
  
      var isFromSearch = Boolean(searchForFacetValuesResults && searchForFacetValuesResults[attributeName] && searchForFacetValuesResults.query !== '');
      var withSearchBox = props.withSearchBox || props.searchForFacetValues;
      if (false) {
        // eslint-disable-next-line no-console
        console.warn('react-instantsearch: `searchForFacetValues` has been renamed to' + '`withSearchBox`, this will break in the next major version.');
      }
      // Search For Facet Values is not available with derived helper (used for multi index search)
      if (props.withSearchBox && this.context.multiIndexContext) {
        throw new Error('react-instantsearch: searching in *List is not available when used inside a' + ' multi index context');
      }
  
      if (!canRefine) {
        return {
          items: [],
          currentRefinement: getCurrentRefinement(props, searchState, this.context),
          canRefine: canRefine,
          isFromSearch: isFromSearch,
          withSearchBox: withSearchBox
        };
      }
  
      var items = isFromSearch ? searchForFacetValuesResults[attributeName].map(function (v) {
        return {
          label: v.value,
          value: getValue(v.value, props, searchState, _this.context),
          _highlightResult: { label: { value: v.highlighted } },
          count: v.count,
          isRefined: v.isRefined
        };
      }) : results.getFacetValues(attributeName, { sortBy: sortBy }).map(function (v) {
        return {
          label: v.name,
          value: getValue(v.name, props, searchState, _this.context),
          count: v.count,
          isRefined: v.isRefined
        };
      });
  
      var transformedItems = props.transformItems ? props.transformItems(items) : items;
  
      return {
        items: transformedItems.slice(0, limit),
        currentRefinement: getCurrentRefinement(props, searchState, this.context),
        isFromSearch: isFromSearch,
        withSearchBox: withSearchBox,
        canRefine: items.length > 0
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    searchForFacetValues: function searchForFacetValues(props, searchState, nextRefinement) {
      return { facetName: props.attributeName, query: nextRefinement };
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var attributeName = props.attributeName,
          operator = props.operator,
          showMore = props.showMore,
          limitMin = props.limitMin,
          limitMax = props.limitMax;
  
      var limit = showMore ? limitMax : limitMin;
  
      var addKey = operator === 'and' ? 'addFacet' : 'addDisjunctiveFacet';
      var addRefinementKey = addKey + 'Refinement';
  
      searchParameters = searchParameters.setQueryParameters({
        maxValuesPerFacet: Math.max(searchParameters.maxValuesPerFacet || 0, limit)
      });
  
      searchParameters = searchParameters[addKey](attributeName);
  
      return getCurrentRefinement(props, searchState, this.context).reduce(function (res, val) {
        return res[addRefinementKey](attributeName, val);
      }, searchParameters);
    },
    getMetadata: function getMetadata(props, searchState) {
      var id = getId(props);
      var context = this.context;
      return {
        id: id,
        index: (0, _indexUtils.getIndex)(this.context),
        items: getCurrentRefinement(props, searchState, context).length > 0 ? [{
          attributeName: props.attributeName,
          label: props.attributeName + ': ',
          currentRefinement: getCurrentRefinement(props, searchState, context),
          value: function value(nextState) {
            return _refine(props, nextState, [], context);
          },
          items: getCurrentRefinement(props, searchState, context).map(function (item) {
            return {
              label: '' + item,
              value: function value(nextState) {
                var nextSelectedItems = getCurrentRefinement(props, nextState, context).filter(function (other) {
                  return other !== item;
                });
                return _refine(props, searchState, nextSelectedItems, context);
              }
            };
          })
        }] : []
      };
    }
  });
  
  /***/ }),
  /* 339 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * connectScrollTo connector provides the logic to build a widget that will
   * let the page scroll to a certain point.
   * @name connectScrollTo
   * @kind connector
   * @propType {string} [scrollOn="page"] - Widget searchState key on which to listen for changes, default to the pagination widget.
   * @providedPropType {any} value - the current refinement applied to the widget listened by scrollTo
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaScrollTo',
  
    propTypes: {
      scrollOn: _propTypes2.default.string
    },
  
    defaultProps: {
      scrollOn: 'page'
    },
  
    getProvidedProps: function getProvidedProps(props, searchState) {
      var id = props.scrollOn;
      var value = (0, _indexUtils.getCurrentRefinementValue)(props, searchState, this.context, id, null, function (currentRefinement) {
        return currentRefinement;
      });
      return { value: value };
    }
  });
  
  /***/ }),
  /* 340 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId() {
    return 'query';
  }
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId(props);
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, '', function (currentRefinement) {
      if (currentRefinement) {
        return currentRefinement;
      }
      return '';
    });
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId();
    var nextValue = _defineProperty({}, id, nextRefinement);
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, getId());
  }
  
  /**
   * connectSearchBox connector provides the logic to build a widget that will
   * let the user search for a query.
   * @name connectSearchBox
   * @kind connector
   * @providedPropType {function} refine - a function to remove a single filter
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string} currentRefinement - the query to search for.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaSearchBox',
  
    propTypes: {
      defaultRefinement: _propTypes2.default.string
    },
  
    getProvidedProps: function getProvidedProps(props, searchState) {
      return {
        currentRefinement: getCurrentRefinement(props, searchState, this.context)
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      return searchParameters.setQuery(getCurrentRefinement(props, searchState, this.context));
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this = this;
  
      var id = getId(props);
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      return {
        id: id,
        index: (0, _indexUtils.getIndex)(this.context),
        items: currentRefinement === null ? [] : [{
          label: id + ': ' + currentRefinement,
          value: function value(nextState) {
            return _refine(props, nextState, '', _this.context);
          },
          currentRefinement: currentRefinement
        }]
      };
    }
  });
  
  /***/ }),
  /* 341 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  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; };
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _indexUtils = __webpack_require__(5);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId() {
    return 'sortBy';
  }
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId(props);
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, null, function (currentRefinement) {
      if (currentRefinement) {
        return currentRefinement;
      }
      return null;
    });
  }
  
  /**
   * The connectSortBy connector provides the logic to build a widget that will
   *  display a list of indices. This allows a user to change how the hits are being sorted.
   * @name connectSortBy
   * @requirements Algolia handles sorting by creating replica indices. [Read more about sorting](https://www.algolia.com/doc/guides/relevance/sorting/) on
   * the Algolia website.
   * @kind connector
   * @propType {string} defaultRefinement - The default selected index.
   * @propType {{value: string, label: string}[]} items - The list of indexes to search in.
   * @propType {function} [transformItems] - Function to modify the items being displayed, e.g. for filtering or sorting them. Takes an items as parameter and expects it back in return.
   * @providedPropType {function} refine - a function to remove a single filter
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {string[]} currentRefinement - the refinement currently applied
   * @providedPropType {array.<{isRefined: boolean, label?: string, value: string}>} items - the list of items the HitsPerPage can display.  If no label provided, the value will be displayed.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaSortBy',
  
    propTypes: {
      defaultRefinement: _propTypes2.default.string,
      items: _propTypes2.default.arrayOf(_propTypes2.default.shape({
        label: _propTypes2.default.string,
        value: _propTypes2.default.string.isRequired
      })).isRequired,
      transformItems: _propTypes2.default.func
    },
  
    getProvidedProps: function getProvidedProps(props, searchState) {
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      var items = props.items.map(function (item) {
        return item.value === currentRefinement ? _extends({}, item, { isRefined: true }) : _extends({}, item, { isRefined: false });
      });
      return {
        items: props.transformItems ? props.transformItems(items) : items,
        currentRefinement: currentRefinement
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      var id = getId();
      var nextValue = _defineProperty({}, id, nextRefinement);
      var resetPage = true;
      return (0, _indexUtils.refineValue)(searchState, nextValue, this.context, resetPage);
    },
    cleanUp: function cleanUp(props, searchState) {
      return (0, _indexUtils.cleanUpValue)(searchState, this.context, getId());
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var selectedIndex = getCurrentRefinement(props, searchState, this.context);
      return searchParameters.setIndex(selectedIndex);
    },
    getMetadata: function getMetadata() {
      return { id: getId() };
    }
  });
  
  /***/ }),
  /* 342 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /**
   * connectStats connector provides the logic to build a widget that will
   *  displays algolia search statistics (hits number and processing time).
   * @name connectStats
   * @kind connector
   * @providedPropType {number} nbHits - number of hits returned by Algolia.
   * @providedPropType {number} processingTimeMS - the time in ms took by Algolia to search for results.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaStats',
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      var results = (0, _indexUtils.getResults)(searchResults, this.context);
  
      if (!results) {
        return null;
      }
      return {
        nbHits: results.nbHits,
        processingTimeMS: results.processingTimeMS
      };
    }
  });
  
  /***/ }),
  /* 343 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _propTypes = __webpack_require__(1);
  
  var _propTypes2 = _interopRequireDefault(_propTypes);
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function getId(props) {
    return props.attributeName;
  }
  
  var namespace = 'toggle';
  
  function getCurrentRefinement(props, searchState, context) {
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, namespace + '.' + getId(props), false, function (currentRefinement) {
      if (currentRefinement) {
        return currentRefinement;
      }
      return false;
    });
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId(props);
    var nextValue = _defineProperty({}, id, nextRefinement ? nextRefinement : false);
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage, namespace);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, namespace + '.' + getId(props));
  }
  
  /**
   * connectToggle connector provides the logic to build a widget that will
   *  provides an on/off filtering feature based on an attribute value. Note that if you provide an “off” option, it will be refined at initialization.
   * @name connectToggle
   * @kind connector
   * @propType {string} attributeName - Name of the attribute on which to apply the `value` refinement. Required when `value` is present.
   * @propType {string} label - Label for the toggle.
   * @propType {string} value - Value of the refinement to apply on `attributeName`.
   * @propType {boolean} [defaultRefinement=false] - Default searchState of the widget. Should the toggle be checked by default?
   * @providedPropType {function} refine - a function to toggle a refinement
   * @providedPropType {function} createURL - a function to generate a URL for the corresponding search state
   * @providedPropType {boolean} currentRefinement - the refinement currently applied
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaToggle',
  
    propTypes: {
      label: _propTypes2.default.string,
      filter: _propTypes2.default.func,
      attributeName: _propTypes2.default.string,
      value: _propTypes2.default.any,
      defaultRefinement: _propTypes2.default.bool
    },
  
    getProvidedProps: function getProvidedProps(props, searchState) {
      var currentRefinement = getCurrentRefinement(props, searchState, this.context);
      return { currentRefinement: currentRefinement };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      var attributeName = props.attributeName,
          value = props.value,
          filter = props.filter;
  
      var checked = getCurrentRefinement(props, searchState, this.context);
  
      if (checked) {
        if (attributeName) {
          searchParameters = searchParameters.addFacet(attributeName).addFacetRefinement(attributeName, value);
        }
        if (filter) {
          searchParameters = filter(searchParameters);
        }
      }
  
      return searchParameters;
    },
    getMetadata: function getMetadata(props, searchState) {
      var _this = this;
  
      var id = getId(props);
      var checked = getCurrentRefinement(props, searchState, this.context);
      var items = [];
      var index = (0, _indexUtils.getIndex)(this.context);
      if (checked) {
        items.push({
          label: props.label,
          currentRefinement: props.label,
          attributeName: props.attributeName,
          value: function value(nextState) {
            return _refine(props, nextState, false, _this.context);
          }
        });
      }
      return { id: id, index: index, items: items };
    }
  });
  
  /***/ }),
  /* 344 */,
  /* 345 */,
  /* 346 */,
  /* 347 */,
  /* 348 */,
  /* 349 */,
  /* 350 */,
  /* 351 */,
  /* 352 */,
  /* 353 */,
  /* 354 */,
  /* 355 */,
  /* 356 */,
  /* 357 */,
  /* 358 */,
  /* 359 */,
  /* 360 */,
  /* 361 */,
  /* 362 */,
  /* 363 */,
  /* 364 */,
  /* 365 */,
  /* 366 */,
  /* 367 */,
  /* 368 */,
  /* 369 */,
  /* 370 */,
  /* 371 */,
  /* 372 */,
  /* 373 */,
  /* 374 */,
  /* 375 */,
  /* 376 */,
  /* 377 */,
  /* 378 */,
  /* 379 */,
  /* 380 */,
  /* 381 */,
  /* 382 */,
  /* 383 */,
  /* 384 */,
  /* 385 */,
  /* 386 */,
  /* 387 */,
  /* 388 */,
  /* 389 */,
  /* 390 */,
  /* 391 */,
  /* 392 */,
  /* 393 */,
  /* 394 */,
  /* 395 */,
  /* 396 */,
  /* 397 */,
  /* 398 */,
  /* 399 */,
  /* 400 */,
  /* 401 */,
  /* 402 */,
  /* 403 */,
  /* 404 */,
  /* 405 */,
  /* 406 */,
  /* 407 */,
  /* 408 */,
  /* 409 */,
  /* 410 */,
  /* 411 */,
  /* 412 */,
  /* 413 */,
  /* 414 */,
  /* 415 */,
  /* 416 */,
  /* 417 */,
  /* 418 */,
  /* 419 */,
  /* 420 */,
  /* 421 */,
  /* 422 */,
  /* 423 */,
  /* 424 */,
  /* 425 */,
  /* 426 */,
  /* 427 */,
  /* 428 */,
  /* 429 */,
  /* 430 */,
  /* 431 */,
  /* 432 */,
  /* 433 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _connectConfigure = __webpack_require__(221);
  
  Object.defineProperty(exports, 'connectConfigure', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectConfigure).default;
    }
  });
  
  var _connectCurrentRefinements = __webpack_require__(211);
  
  Object.defineProperty(exports, 'connectCurrentRefinements', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectCurrentRefinements).default;
    }
  });
  
  var _connectHierarchicalMenu = __webpack_require__(247);
  
  Object.defineProperty(exports, 'connectHierarchicalMenu', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectHierarchicalMenu).default;
    }
  });
  
  var _connectHighlight = __webpack_require__(217);
  
  Object.defineProperty(exports, 'connectHighlight', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectHighlight).default;
    }
  });
  
  var _connectHits = __webpack_require__(331);
  
  Object.defineProperty(exports, 'connectHits', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectHits).default;
    }
  });
  
  var _connectAutoComplete = __webpack_require__(434);
  
  Object.defineProperty(exports, 'connectAutoComplete', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectAutoComplete).default;
    }
  });
  
  var _connectHitsPerPage = __webpack_require__(332);
  
  Object.defineProperty(exports, 'connectHitsPerPage', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectHitsPerPage).default;
    }
  });
  
  var _connectInfiniteHits = __webpack_require__(333);
  
  Object.defineProperty(exports, 'connectInfiniteHits', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectInfiniteHits).default;
    }
  });
  
  var _connectMenu = __webpack_require__(334);
  
  Object.defineProperty(exports, 'connectMenu', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectMenu).default;
    }
  });
  
  var _connectMultiRange = __webpack_require__(335);
  
  Object.defineProperty(exports, 'connectMultiRange', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectMultiRange).default;
    }
  });
  
  var _connectPagination = __webpack_require__(336);
  
  Object.defineProperty(exports, 'connectPagination', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectPagination).default;
    }
  });
  
  var _connectPoweredBy = __webpack_require__(337);
  
  Object.defineProperty(exports, 'connectPoweredBy', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectPoweredBy).default;
    }
  });
  
  var _connectRange = __webpack_require__(209);
  
  Object.defineProperty(exports, 'connectRange', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectRange).default;
    }
  });
  
  var _connectRefinementList = __webpack_require__(338);
  
  Object.defineProperty(exports, 'connectRefinementList', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectRefinementList).default;
    }
  });
  
  var _connectScrollTo = __webpack_require__(339);
  
  Object.defineProperty(exports, 'connectScrollTo', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectScrollTo).default;
    }
  });
  
  var _connectSearchBox = __webpack_require__(340);
  
  Object.defineProperty(exports, 'connectSearchBox', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectSearchBox).default;
    }
  });
  
  var _connectSortBy = __webpack_require__(341);
  
  Object.defineProperty(exports, 'connectSortBy', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectSortBy).default;
    }
  });
  
  var _connectStats = __webpack_require__(342);
  
  Object.defineProperty(exports, 'connectStats', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectStats).default;
    }
  });
  
  var _connectToggle = __webpack_require__(343);
  
  Object.defineProperty(exports, 'connectToggle', {
    enumerable: true,
    get: function get() {
      return _interopRequireDefault(_connectToggle).default;
    }
  });
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  /***/ }),
  /* 434 */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _createConnector = __webpack_require__(2);
  
  var _createConnector2 = _interopRequireDefault(_createConnector);
  
  var _indexUtils = __webpack_require__(5);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  
  var getId = function getId() {
    return 'query';
  };
  
  function getCurrentRefinement(props, searchState, context) {
    var id = getId();
    return (0, _indexUtils.getCurrentRefinementValue)(props, searchState, context, id, '', function (currentRefinement) {
      if (currentRefinement) {
        return currentRefinement;
      }
      return '';
    });
  }
  
  function getHits(searchResults) {
    if (searchResults.results) {
      if (searchResults.results.hits && Array.isArray(searchResults.results.hits)) {
        return searchResults.results.hits;
      } else {
        return Object.keys(searchResults.results).reduce(function (hits, index) {
          return [].concat(_toConsumableArray(hits), [{
            index: index,
            hits: searchResults.results[index].hits
          }]);
        }, []);
      }
    } else {
      return [];
    }
  }
  
  function _refine(props, searchState, nextRefinement, context) {
    var id = getId();
    var nextValue = _defineProperty({}, id, nextRefinement);
    var resetPage = true;
    return (0, _indexUtils.refineValue)(searchState, nextValue, context, resetPage);
  }
  
  function _cleanUp(props, searchState, context) {
    return (0, _indexUtils.cleanUpValue)(searchState, context, getId());
  }
  
  /**
   * connectAutoComplete connector provides the logic to create connected
   * components that will render the results retrieved from
   * Algolia.
   *
   * To configure the number of hits retrieved, use [HitsPerPage widget](widgets/HitsPerPage.html),
   * [connectHitsPerPage connector](connectors/connectHitsPerPage.html) or pass the hitsPerPage
   * prop to a [Configure](guide/Search_parameters.html) widget.
   * @name connectAutoComplete
   * @kind connector
   * @providedPropType {array.<object>} hits - the records that matched the search state.
   * @providedPropType {function} refine - a function to change the query.
   * @providedPropType {string} currentRefinement - the query to search for.
   */
  exports.default = (0, _createConnector2.default)({
    displayName: 'AlgoliaAutoComplete',
  
    getProvidedProps: function getProvidedProps(props, searchState, searchResults) {
      return {
        hits: getHits(searchResults),
        currentRefinement: getCurrentRefinement(props, searchState, this.context)
      };
    },
    refine: function refine(props, searchState, nextRefinement) {
      return _refine(props, searchState, nextRefinement, this.context);
    },
    cleanUp: function cleanUp(props, searchState) {
      return _cleanUp(props, searchState, this.context);
    },
  
  
    /* connectAutoComplete needs to be considered as a widget to trigger a search if no others widgets are used.
     * To be considered as a widget you need either getSearchParameters, getMetadata or getTransitionState
     * See createConnector.js
      * */
    getSearchParameters: function getSearchParameters(searchParameters, props, searchState) {
      return searchParameters.setQuery(getCurrentRefinement(props, searchState, this.context));
    }
  });
  
  /***/ })
  /******/ ]);
  });
  //# sourceMappingURL=Connectors.js.map