import _objectWithoutPropertiesLoose from '@babel/runtime/helpers/esm/objectWithoutPropertiesLoose';
import _extends from '@babel/runtime/helpers/esm/extends';
import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
import PropTypes from 'prop-types';
import * as React from 'react';
import { cloneElement, Component, useRef, useCallback, useEffect, useMemo } from 'react';
import { isForwardRef } from 'react-is';
import { compute } from 'compute-scroll-into-view';

var unknown = process.env.NODE_ENV !== "production" ? '__autocomplete_unknown__' : 0;
var mouseUp = process.env.NODE_ENV !== "production" ? '__autocomplete_mouseup__' : 1;
var itemMouseEnter = process.env.NODE_ENV !== "production" ? '__autocomplete_item_mouseenter__' : 2;
var keyDownArrowUp = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_arrow_up__' : 3;
var keyDownArrowDown = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_arrow_down__' : 4;
var keyDownEscape = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_escape__' : 5;
var keyDownEnter = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_enter__' : 6;
var keyDownHome = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_home__' : 7;
var keyDownEnd = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_end__' : 8;
var clickItem = process.env.NODE_ENV !== "production" ? '__autocomplete_click_item__' : 9;
var blurInput = process.env.NODE_ENV !== "production" ? '__autocomplete_blur_input__' : 10;
var changeInput = process.env.NODE_ENV !== "production" ? '__autocomplete_change_input__' : 11;
var keyDownSpaceButton = process.env.NODE_ENV !== "production" ? '__autocomplete_keydown_space_button__' : 12;
var clickButton = process.env.NODE_ENV !== "production" ? '__autocomplete_click_button__' : 13;
var blurButton = process.env.NODE_ENV !== "production" ? '__autocomplete_blur_button__' : 14;
var controlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__autocomplete_controlled_prop_updated_selected_item__' : 15;
var touchEnd = process.env.NODE_ENV !== "production" ? '__autocomplete_touchend__' : 16;

var stateChangeTypes$4 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  blurButton: blurButton,
  blurInput: blurInput,
  changeInput: changeInput,
  clickButton: clickButton,
  clickItem: clickItem,
  controlledPropUpdatedSelectedItem: controlledPropUpdatedSelectedItem,
  itemMouseEnter: itemMouseEnter,
  keyDownArrowDown: keyDownArrowDown,
  keyDownArrowUp: keyDownArrowUp,
  keyDownEnd: keyDownEnd,
  keyDownEnter: keyDownEnter,
  keyDownEscape: keyDownEscape,
  keyDownHome: keyDownHome,
  keyDownSpaceButton: keyDownSpaceButton,
  mouseUp: mouseUp,
  touchEnd: touchEnd,
  unknown: unknown
});

var idCounter = 0;

/**
 * This generates a unique ID for an instance of Downshift
 * @return {string} the unique ID
 */
function generateId() {
  return String(idCounter++);
}

/**
 * Resets idCounter to 0. Used for SSR.
 */
function resetIdCounter() {
  // istanbul ignore next
  if ('useId' in React) {
    console.warn("It is not necessary to call resetIdCounter when using React 18+");
    return;
  }
  idCounter = 0;
}

function useLatestRef(val) {
  var ref = React.useRef(val);
  // technically this is not "concurrent mode safe" because we're manipulating
  // the value during render (so it's not idempotent). However, the places this
  // hook is used is to support memoizing callbacks which will be called
  // *during* render, so we need the latest values *during* render.
  // If not for this, then we'd probably want to use useLayoutEffect instead.
  ref.current = val;
  return ref;
}

function handleRefs$1() {
  for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
    refs[_key] = arguments[_key];
  }
  return function (node) {
    refs.forEach(function (ref) {
      if (typeof ref === 'function') {
        ref(node);
      } else if (ref) {
        ref.current = node;
      }
    });
  };
}

/**
 * This is intended to be used to compose event handlers.
 * They are executed in order until one of them sets
 * `event.preventDownshiftDefault = true`.
 * @param fns the event handler functions
 * @return the event handler to add to an element
 */
function callAllEventHandlers$1() {
  for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
    fns[_key] = arguments[_key];
  }
  return function (event) {
    for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
      args[_key2 - 1] = arguments[_key2];
    }
    return fns.some(function (fn) {
      if (fn) {
        fn.apply(void 0, [event].concat(args));
      }
      return event.preventDownshiftDefault || event.hasOwnProperty('nativeEvent') && event.nativeEvent.preventDownshiftDefault;
    });
  };
}

/**
 * Simple debounce implementation. Will call the given
 * function once after the time given has passed since
 * it was last called.
 */
function debounce$1(fn, time) {
  var timeoutId;
  function cancel() {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  }
  function wrapper() {
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    cancel();
    timeoutId = setTimeout(function () {
      timeoutId = null;
      fn.apply(void 0, args);
    }, time);
  }
  wrapper.cancel = cancel;
  return wrapper;
}

var cleanupStatus = debounce$1(function (document) {
  getStatusDiv(document).textContent = '';
}, 500);

/**
 * Get the status node or create it if it does not already exist.
 */
function getStatusDiv(document) {
  var statusDiv = document.getElementById('a11y-status-message');
  if (statusDiv) {
    return statusDiv;
  }
  statusDiv = document.createElement('div');
  statusDiv.setAttribute('id', 'a11y-status-message');
  statusDiv.setAttribute('role', 'status');
  statusDiv.setAttribute('aria-live', 'polite');
  statusDiv.setAttribute('aria-relevant', 'additions text');
  Object.assign(statusDiv.style, {
    border: '0',
    clip: 'rect(0 0 0 0)',
    height: '1px',
    margin: '-1px',
    overflow: 'hidden',
    padding: '0',
    position: 'absolute',
    width: '1px'
  });
  document.body.appendChild(statusDiv);
  return statusDiv;
}

/**
 * Sets aria live status to a div element that's visually hidden.
 */
function setStatus(status, document) {
  if (!status || !document) {
    return;
  }
  var div = getStatusDiv(document);
  div.textContent = status;
  cleanupStatus(document);
}

/**
 * Removes the status element from the DOM
 */
function cleanupStatusDiv(document) {
  var statusDiv = document == null ? void 0 : document.getElementById('a11y-status-message');
  if (statusDiv) {
    statusDiv.remove();
  }
}

function noop() {}

// eslint-disable-next-line import/no-mutable-exports
var validatePropTypes$1 = noop;
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'production') {
  validatePropTypes$1 = function validatePropTypes(options, caller, propTypes) {
    PropTypes.checkPropTypes(propTypes, options, 'prop', caller.name);
  };
}

/**
 * This will perform a shallow merge of the given state object
 * with the state coming from props
 * (for the controlled component scenario)
 * This is used in state updater functions so they're referencing
 * the right state regardless of where it comes from.
 *
 * @param state The state of the component/hook.
 * @param props The props that may contain controlled values.
 * @returns The merged controlled state.
 */
function getState(state, props) {
  if (!props) {
    return state;
  }
  var keys = Object.keys(state);
  return keys.reduce(function (newState, key) {
    if (props[key] !== undefined) {
      newState[key] = props[key];
    }
    return newState;
  }, _extends({}, state));
}

/**
 * Scroll node into view if necessary
 * @param {HTMLElement} node the element that should scroll into view
 * @param {HTMLElement} menuNode the menu element of the component
 */
function scrollIntoView(node, menuNode) {
  if (!node) {
    return;
  }
  var actions = compute(node, {
    boundary: menuNode,
    block: 'nearest',
    scrollMode: 'if-needed'
  });
  actions.forEach(function (_ref) {
    var el = _ref.el,
      top = _ref.top,
      left = _ref.left;
    el.scrollTop = top;
    el.scrollLeft = left;
  });
}

/**
 * Accepts a parameter and returns it if it's a function
 * or a noop function if it's not. This allows us to
 * accept a callback, but not worry about it if it's not
 * passed.
 * @param {Function} cb the callback
 * @return {Function} a function
 */
function cbToCb(cb) {
  return typeof cb === 'function' ? cb : noop;
}

/**
 * @param {HTMLElement} parent the parent node
 * @param {HTMLElement} child the child node
 * @param {Window} environment The window context where downshift renders.
 * @return {Boolean} whether the parent is the child or the child is in the parent
 */
function isOrContainsNode(parent, child, environment) {
  var result = parent === child || child instanceof environment.Node && parent.contains && parent.contains(child);
  return result;
}

/**
 * Simple debounce implementation. Will call the given
 * function once after the time given has passed since
 * it was last called.
 * @param {Function} fn the function to call after the time
 * @param {Number} time the time to wait
 * @return {Function} the debounced function
 */
function debounce(fn, time) {
  var timeoutId;
  function cancel() {
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
  }
  function wrapper() {
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    cancel();
    timeoutId = setTimeout(function () {
      timeoutId = null;
      fn.apply(void 0, args);
    }, time);
  }
  wrapper.cancel = cancel;
  return wrapper;
}

/**
 * This is intended to be used to compose event handlers.
 * They are executed in order until one of them sets
 * `event.preventDownshiftDefault = true`.
 * @param {...Function} fns the event handler functions
 * @return {Function} the event handler to add to an element
 */
function callAllEventHandlers() {
  for (var _len2 = arguments.length, fns = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
    fns[_key2] = arguments[_key2];
  }
  return function (event) {
    for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
      args[_key3 - 1] = arguments[_key3];
    }
    return fns.some(function (fn) {
      if (fn) {
        fn.apply(void 0, [event].concat(args));
      }
      return event.preventDownshiftDefault || event.hasOwnProperty('nativeEvent') && event.nativeEvent.preventDownshiftDefault;
    });
  };
}
function handleRefs() {
  for (var _len4 = arguments.length, refs = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
    refs[_key4] = arguments[_key4];
  }
  return function (node) {
    refs.forEach(function (ref) {
      if (typeof ref === 'function') {
        ref(node);
      } else if (ref) {
        ref.current = node;
      }
    });
  };
}

/**
 * Default implementation for status message. Only added when menu is open.
 * Will specify if there are results in the list, and if so, how many,
 * and what keys are relevant.
 *
 * @param {Object} param the downshift state and other relevant properties
 * @return {String} the a11y status message
 */
function getA11yStatusMessage(_ref) {
  var isOpen = _ref.isOpen,
    resultCount = _ref.resultCount,
    previousResultCount = _ref.previousResultCount;
  if (!isOpen) {
    return '';
  }
  if (!resultCount) {
    return 'No results are available.';
  }
  if (resultCount !== previousResultCount) {
    return resultCount + " result" + (resultCount === 1 ? ' is' : 's are') + " available, use up and down arrow keys to navigate. Press Enter key to select.";
  }
  return '';
}

/**
 * Takes an argument and if it's an array, returns the first item in the array
 * otherwise returns the argument
 * @param {*} arg the maybe-array
 * @param {*} defaultValue the value if arg is falsey not defined
 * @return {*} the arg or it's first item
 */
function unwrapArray(arg, defaultValue) {
  arg = Array.isArray(arg) ? /* istanbul ignore next (preact) */arg[0] : arg;
  if (!arg && defaultValue) {
    return defaultValue;
  } else {
    return arg;
  }
}

/**
 * @param {Object} element (P)react element
 * @return {Boolean} whether it's a DOM element
 */
function isDOMElement(element) {

  // then we assume this is react
  return typeof element.type === 'string';
}

/**
 * @param {Object} element (P)react element
 * @return {Object} the props
 */
function getElementProps(element) {
  return element.props;
}

/**
 * Throws a helpful error message for required properties. Useful
 * to be used as a default in destructuring or object params.
 * @param {String} fnName the function name
 * @param {String} propName the prop name
 */
function requiredProp(fnName, propName) {
  // eslint-disable-next-line no-console
  console.error("The property \"" + propName + "\" is required in \"" + fnName + "\"");
}
var stateKeys = ['highlightedIndex', 'inputValue', 'isOpen', 'selectedItem', 'type'];
/**
 * @param {Object} state the state object
 * @return {Object} state that is relevant to downshift
 */
function pickState(state) {
  if (state === void 0) {
    state = {};
  }
  var result = {};
  stateKeys.forEach(function (k) {
    if (state.hasOwnProperty(k)) {
      result[k] = state[k];
    }
  });
  return result;
}

/**
 * This determines whether a prop is a "controlled prop" meaning it is
 * state which is controlled by the outside of this component rather
 * than within this component.
 *
 * @param {Object} props The props that may contain controlled values.
 * @param {String} key the key to check
 * @return {Boolean} whether it is a controlled controlled prop
 */
function isControlledProp(props, key) {
  return props[key] !== undefined;
}

/**
 * Normalizes the 'key' property of a KeyboardEvent in IE/Edge
 * @param {Object} event a keyboardEvent object
 * @return {String} keyboard key
 */
function normalizeArrowKey(event) {
  var key = event.key,
    keyCode = event.keyCode;
  /* istanbul ignore next (ie) */
  if (keyCode >= 37 && keyCode <= 40 && key.indexOf('Arrow') !== 0) {
    return "Arrow" + key;
  }
  return key;
}

/**
 * Simple check if the value passed is object literal
 * @param {*} obj any things
 * @return {Boolean} whether it's object literal
 */
function isPlainObject(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

/**
 * Returns the next non-disabled highlightedIndex value.
 *
 * @param {number} start The current highlightedIndex.
 * @param {number} offset The offset from the current highlightedIndex to start searching.
 * @param {unknown[]} items The items array.
 * @param {(item: unknown, index: number) => boolean} isItemDisabled Function that tells if an item is disabled or not.
 * @param {boolean?} circular If the search reaches the end, if it can search again starting from the other end.
 * @returns {number} The next highlightedIndex.
 */
function getHighlightedIndex(start, offset, items, isItemDisabled, circular) {
  if (circular === void 0) {
    circular = false;
  }
  var count = items.length;
  if (count === 0) {
    return -1;
  }
  var itemsLastIndex = count - 1;
  if (typeof start !== 'number' || start < 0 || start > itemsLastIndex) {
    start = offset > 0 ? -1 : itemsLastIndex + 1;
  }
  var current = start + offset;
  if (current < 0) {
    current = circular ? itemsLastIndex : 0;
  } else if (current > itemsLastIndex) {
    current = circular ? 0 : itemsLastIndex;
  }
  var highlightedIndex = getNonDisabledIndex(current, offset < 0, items, isItemDisabled, circular);
  if (highlightedIndex === -1) {
    return start >= count ? -1 : start;
  }
  return highlightedIndex;
}

/**
 * Returns the next non-disabled highlightedIndex value.
 *
 * @param {number} start The current highlightedIndex.
 * @param {boolean} backwards If true, it will search backwards from the start.
 * @param {unknown[]} items The items array.
 * @param {(item: unknown, index: number) => boolean} isItemDisabled Function that tells if an item is disabled or not.
 * @param {boolean} circular If the search reaches the end, if it can search again starting from the other end.
 * @returns {number} The next non-disabled index.
 */
function getNonDisabledIndex(start, backwards, items, isItemDisabled, circular) {
  if (circular === void 0) {
    circular = false;
  }
  var count = items.length;
  if (backwards) {
    for (var index = start; index >= 0; index--) {
      if (!isItemDisabled(items[index], index)) {
        return index;
      }
    }
  } else {
    for (var _index = start; _index < count; _index++) {
      if (!isItemDisabled(items[_index], _index)) {
        return _index;
      }
    }
  }
  if (circular) {
    return getNonDisabledIndex(backwards ? count - 1 : 0, backwards, items, isItemDisabled);
  }
  return -1;
}

/**
 * Checks if event target is within the downshift elements.
 *
 * @param {EventTarget} target Target to check.
 * @param {HTMLElement[]} downshiftElements The elements that form downshift (list, toggle button etc).
 * @param {Window} environment The window context where downshift renders.
 * @param {boolean} checkActiveElement Whether to also check activeElement.
 *
 * @returns {boolean} Whether or not the target is within downshift elements.
 */
function targetWithinDownshift(target, downshiftElements, environment, checkActiveElement) {
  if (checkActiveElement === void 0) {
    checkActiveElement = true;
  }
  return environment && downshiftElements.some(function (contextNode) {
    return contextNode && (isOrContainsNode(contextNode, target, environment) || checkActiveElement && isOrContainsNode(contextNode, environment.document.activeElement, environment));
  });
}

// eslint-disable-next-line import/no-mutable-exports
var validateControlledUnchanged = noop;
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'production') {
  validateControlledUnchanged = function validateControlledUnchanged(state, prevProps, nextProps) {
    var warningDescription = "This prop should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled Downshift element for the lifetime of the component. More info: https://github.com/downshift-js/downshift#control-props";
    Object.keys(state).forEach(function (propKey) {
      if (prevProps[propKey] !== undefined && nextProps[propKey] === undefined) {
        // eslint-disable-next-line no-console
        console.error("downshift: A component has changed the controlled prop \"" + propKey + "\" to be uncontrolled. " + warningDescription);
      } else if (prevProps[propKey] === undefined && nextProps[propKey] !== undefined) {
        // eslint-disable-next-line no-console
        console.error("downshift: A component has changed the uncontrolled prop \"" + propKey + "\" to be controlled. " + warningDescription);
      }
    });
  };
}

var _excluded$4 = ["refKey", "ref"],
  _excluded2$4 = ["onClick", "onPress", "onKeyDown", "onKeyUp", "onBlur"],
  _excluded3$3 = ["onKeyDown", "onBlur", "onChange", "onInput", "onChangeText"],
  _excluded4$2 = ["refKey", "ref"],
  _excluded5 = ["onMouseMove", "onMouseDown", "onClick", "onPress", "index", "item"];
var Downshift = /*#__PURE__*/function () {
  var Downshift = /*#__PURE__*/function (_Component) {
    function Downshift(_props) {
      var _this;
      _this = _Component.call(this, _props) || this;
      // fancy destructuring + defaults + aliases
      // this basically says each value of state should either be set to
      // the initial value or the default value if the initial value is not provided
      _this.id = _this.props.id || "downshift-" + generateId();
      _this.menuId = _this.props.menuId || _this.id + "-menu";
      _this.labelId = _this.props.labelId || _this.id + "-label";
      _this.inputId = _this.props.inputId || _this.id + "-input";
      _this.getItemId = _this.props.getItemId || function (index) {
        return _this.id + "-item-" + index;
      };
      _this.items = [];
      // itemCount can be changed asynchronously
      // from within downshift (so it can't come from a prop)
      // this is why we store it as an instance and use
      // getItemCount rather than just use items.length
      // (to support windowing + async)
      _this.itemCount = null;
      _this.previousResultCount = 0;
      _this.timeoutIds = [];
      /**
       * @param {Function} fn the function to call after the time
       * @param {Number} time the time to wait
       */
      _this.internalSetTimeout = function (fn, time) {
        var id = setTimeout(function () {
          _this.timeoutIds = _this.timeoutIds.filter(function (i) {
            return i !== id;
          });
          fn();
        }, time);
        _this.timeoutIds.push(id);
      };
      _this.setItemCount = function (count) {
        _this.itemCount = count;
      };
      _this.unsetItemCount = function () {
        _this.itemCount = null;
      };
      _this.isItemDisabled = function (_item, index) {
        var currentElementNode = _this.getItemNodeFromIndex(index);
        return currentElementNode && currentElementNode.hasAttribute('disabled');
      };
      _this.setHighlightedIndex = function (highlightedIndex, otherStateToSet) {
        if (highlightedIndex === void 0) {
          highlightedIndex = _this.props.defaultHighlightedIndex;
        }
        if (otherStateToSet === void 0) {
          otherStateToSet = {};
        }
        otherStateToSet = pickState(otherStateToSet);
        _this.internalSetState(_extends({
          highlightedIndex: highlightedIndex
        }, otherStateToSet));
      };
      _this.clearSelection = function (cb) {
        _this.internalSetState({
          selectedItem: null,
          inputValue: '',
          highlightedIndex: _this.props.defaultHighlightedIndex,
          isOpen: _this.props.defaultIsOpen
        }, cb);
      };
      _this.selectItem = function (item, otherStateToSet, cb) {
        otherStateToSet = pickState(otherStateToSet);
        _this.internalSetState(_extends({
          isOpen: _this.props.defaultIsOpen,
          highlightedIndex: _this.props.defaultHighlightedIndex,
          selectedItem: item,
          inputValue: _this.props.itemToString(item)
        }, otherStateToSet), cb);
      };
      _this.selectItemAtIndex = function (itemIndex, otherStateToSet, cb) {
        var item = _this.items[itemIndex];
        if (item == null) {
          return;
        }
        _this.selectItem(item, otherStateToSet, cb);
      };
      _this.selectHighlightedItem = function (otherStateToSet, cb) {
        return _this.selectItemAtIndex(_this.getState().highlightedIndex, otherStateToSet, cb);
      };
      // any piece of our state can live in two places:
      // 1. Uncontrolled: it's internal (this.state)
      //    We will call this.setState to update that state
      // 2. Controlled: it's external (this.props)
      //    We will call this.props.onStateChange to update that state
      //
      // In addition, we'll call this.props.onChange if the
      // selectedItem is changed.
      _this.internalSetState = function (stateToSet, cb) {
        var isItemSelected, onChangeArg;
        var onStateChangeArg = {};
        var isStateToSetFunction = typeof stateToSet === 'function';

        // we want to call `onInputValueChange` before the `setState` call
        // so someone controlling the `inputValue` state gets notified of
        // the input change as soon as possible. This avoids issues with
        // preserving the cursor position.
        // See https://github.com/downshift-js/downshift/issues/217 for more info.
        if (!isStateToSetFunction && stateToSet.hasOwnProperty('inputValue')) {
          _this.props.onInputValueChange(stateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), stateToSet));
        }
        return _this.setState(function (state) {
          var _newStateToSet;
          state = _this.getState(state);
          var newStateToSet = isStateToSetFunction ? stateToSet(state) : stateToSet;

          // Your own function that could modify the state that will be set.
          newStateToSet = _this.props.stateReducer(state, newStateToSet);

          // checks if an item is selected, regardless of if it's different from
          // what was selected before
          // used to determine if onSelect and onChange callbacks should be called
          isItemSelected = newStateToSet.hasOwnProperty('selectedItem');
          // this keeps track of the object we want to call with setState
          var nextState = {};
          // we need to call on change if the outside world is controlling any of our state
          // and we're trying to update that state. OR if the selection has changed and we're
          // trying to update the selection
          if (isItemSelected && newStateToSet.selectedItem !== state.selectedItem) {
            onChangeArg = newStateToSet.selectedItem;
          }
          (_newStateToSet = newStateToSet).type || (_newStateToSet.type = unknown);
          Object.keys(newStateToSet).forEach(function (key) {
            // onStateChangeArg should only have the state that is
            // actually changing
            if (state[key] !== newStateToSet[key]) {
              onStateChangeArg[key] = newStateToSet[key];
            }
            // the type is useful for the onStateChangeArg
            // but we don't actually want to set it in internal state.
            // this is an undocumented feature for now... Not all internalSetState
            // calls support it and I'm not certain we want them to yet.
            // But it enables users controlling the isOpen state to know when
            // the isOpen state changes due to mouseup events which is quite handy.
            if (key === 'type') {
              return;
            }
            newStateToSet[key];
            // if it's coming from props, then we don't care to set it internally
            if (!isControlledProp(_this.props, key)) {
              nextState[key] = newStateToSet[key];
            }
          });

          // if stateToSet is a function, then we weren't able to call onInputValueChange
          // earlier, so we'll call it now that we know what the inputValue state will be.
          if (isStateToSetFunction && newStateToSet.hasOwnProperty('inputValue')) {
            _this.props.onInputValueChange(newStateToSet.inputValue, _extends({}, _this.getStateAndHelpers(), newStateToSet));
          }
          return nextState;
        }, function () {
          // call the provided callback if it's a function
          cbToCb(cb)();

          // only call the onStateChange and onChange callbacks if
          // we have relevant information to pass them.
          var hasMoreStateThanType = Object.keys(onStateChangeArg).length > 1;
          if (hasMoreStateThanType) {
            _this.props.onStateChange(onStateChangeArg, _this.getStateAndHelpers());
          }
          if (isItemSelected) {
            _this.props.onSelect(stateToSet.selectedItem, _this.getStateAndHelpers());
          }
          if (onChangeArg !== undefined) {
            _this.props.onChange(onChangeArg, _this.getStateAndHelpers());
          }
          // this is currently undocumented and therefore subject to change
          // We'll try to not break it, but just be warned.
          _this.props.onUserAction(onStateChangeArg, _this.getStateAndHelpers());
        });
      };
      //////////////////////////// ROOT
      _this.rootRef = function (node) {
        return _this._rootNode = node;
      };
      _this.getRootProps = function (_temp, _temp2) {
        var _extends2;
        var _ref = _temp === void 0 ? {} : _temp,
          _ref$refKey = _ref.refKey,
          refKey = _ref$refKey === void 0 ? 'ref' : _ref$refKey,
          ref = _ref.ref,
          rest = _objectWithoutPropertiesLoose(_ref, _excluded$4);
        var _ref2 = _temp2 === void 0 ? {} : _temp2,
          _ref2$suppressRefErro = _ref2.suppressRefError,
          suppressRefError = _ref2$suppressRefErro === void 0 ? false : _ref2$suppressRefErro;
        // this is used in the render to know whether the user has called getRootProps.
        // It uses that to know whether to apply the props automatically
        _this.getRootProps.called = true;
        _this.getRootProps.refKey = refKey;
        _this.getRootProps.suppressRefError = suppressRefError;
        var _this$getState = _this.getState(),
          isOpen = _this$getState.isOpen;
        return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, _this.rootRef), _extends2.role = 'combobox', _extends2['aria-expanded'] = isOpen, _extends2['aria-haspopup'] = 'listbox', _extends2['aria-owns'] = isOpen ? _this.menuId : undefined, _extends2['aria-labelledby'] = _this.labelId, _extends2), rest);
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\ ROOT
      _this.keyDownHandlers = {
        ArrowDown: function ArrowDown(event) {
          var _this2 = this;
          event.preventDefault();
          if (this.getState().isOpen) {
            var amount = event.shiftKey ? 5 : 1;
            this.moveHighlightedIndex(amount, {
              type: keyDownArrowDown
            });
          } else {
            this.internalSetState({
              isOpen: true,
              type: keyDownArrowDown
            }, function () {
              var itemCount = _this2.getItemCount();
              if (itemCount > 0) {
                var _this2$getState = _this2.getState(),
                  highlightedIndex = _this2$getState.highlightedIndex;
                var nextHighlightedIndex = getHighlightedIndex(highlightedIndex, 1, {
                  length: itemCount
                }, _this2.isItemDisabled, true);
                _this2.setHighlightedIndex(nextHighlightedIndex, {
                  type: keyDownArrowDown
                });
              }
            });
          }
        },
        ArrowUp: function ArrowUp(event) {
          var _this3 = this;
          event.preventDefault();
          if (this.getState().isOpen) {
            var amount = event.shiftKey ? -5 : -1;
            this.moveHighlightedIndex(amount, {
              type: keyDownArrowUp
            });
          } else {
            this.internalSetState({
              isOpen: true,
              type: keyDownArrowUp
            }, function () {
              var itemCount = _this3.getItemCount();
              if (itemCount > 0) {
                var _this3$getState = _this3.getState(),
                  highlightedIndex = _this3$getState.highlightedIndex;
                var nextHighlightedIndex = getHighlightedIndex(highlightedIndex, -1, {
                  length: itemCount
                }, _this3.isItemDisabled, true);
                _this3.setHighlightedIndex(nextHighlightedIndex, {
                  type: keyDownArrowUp
                });
              }
            });
          }
        },
        Enter: function Enter(event) {
          if (event.which === 229) {
            return;
          }
          var _this$getState2 = this.getState(),
            isOpen = _this$getState2.isOpen,
            highlightedIndex = _this$getState2.highlightedIndex;
          if (isOpen && highlightedIndex != null) {
            event.preventDefault();
            var item = this.items[highlightedIndex];
            var itemNode = this.getItemNodeFromIndex(highlightedIndex);
            if (item == null || itemNode && itemNode.hasAttribute('disabled')) {
              return;
            }
            this.selectHighlightedItem({
              type: keyDownEnter
            });
          }
        },
        Escape: function Escape(event) {
          event.preventDefault();
          this.reset(_extends({
            type: keyDownEscape
          }, !this.state.isOpen && {
            selectedItem: null,
            inputValue: ''
          }));
        }
      };
      //////////////////////////// BUTTON
      _this.buttonKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
        ' ': function _(event) {
          event.preventDefault();
          this.toggleMenu({
            type: keyDownSpaceButton
          });
        }
      });
      _this.inputKeyDownHandlers = _extends({}, _this.keyDownHandlers, {
        Home: function Home(event) {
          var _this$getState3 = this.getState(),
            isOpen = _this$getState3.isOpen;
          if (!isOpen) {
            return;
          }
          event.preventDefault();
          var itemCount = this.getItemCount();
          if (itemCount <= 0 || !isOpen) {
            return;
          }

          // get next non-disabled starting downwards from 0 if that's disabled.
          var newHighlightedIndex = getNonDisabledIndex(0, false, {
            length: itemCount
          }, this.isItemDisabled);
          this.setHighlightedIndex(newHighlightedIndex, {
            type: keyDownHome
          });
        },
        End: function End(event) {
          var _this$getState4 = this.getState(),
            isOpen = _this$getState4.isOpen;
          if (!isOpen) {
            return;
          }
          event.preventDefault();
          var itemCount = this.getItemCount();
          if (itemCount <= 0 || !isOpen) {
            return;
          }

          // get next non-disabled starting upwards from last index if that's disabled.
          var newHighlightedIndex = getNonDisabledIndex(itemCount - 1, true, {
            length: itemCount
          }, this.isItemDisabled);
          this.setHighlightedIndex(newHighlightedIndex, {
            type: keyDownEnd
          });
        }
      });
      _this.getToggleButtonProps = function (_temp3) {
        var _ref3 = _temp3 === void 0 ? {} : _temp3,
          onClick = _ref3.onClick;
          _ref3.onPress;
          var onKeyDown = _ref3.onKeyDown,
          onKeyUp = _ref3.onKeyUp,
          onBlur = _ref3.onBlur,
          rest = _objectWithoutPropertiesLoose(_ref3, _excluded2$4);
        var _this$getState5 = _this.getState(),
          isOpen = _this$getState5.isOpen;
        var enabledEventHandlers = {
          onClick: callAllEventHandlers(onClick, _this.buttonHandleClick),
          onKeyDown: callAllEventHandlers(onKeyDown, _this.buttonHandleKeyDown),
          onKeyUp: callAllEventHandlers(onKeyUp, _this.buttonHandleKeyUp),
          onBlur: callAllEventHandlers(onBlur, _this.buttonHandleBlur)
        };
        var eventHandlers = rest.disabled ? {} : enabledEventHandlers;
        return _extends({
          type: 'button',
          role: 'button',
          'aria-label': isOpen ? 'close menu' : 'open menu',
          'aria-haspopup': true,
          'data-toggle': true
        }, eventHandlers, rest);
      };
      _this.buttonHandleKeyUp = function (event) {
        // Prevent click event from emitting in Firefox
        event.preventDefault();
      };
      _this.buttonHandleKeyDown = function (event) {
        var key = normalizeArrowKey(event);
        if (_this.buttonKeyDownHandlers[key]) {
          _this.buttonKeyDownHandlers[key].call(_this, event);
        }
      };
      _this.buttonHandleClick = function (event) {
        event.preventDefault();
        // handle odd case for Safari and Firefox which
        // don't give the button the focus properly.
        /* istanbul ignore if (can't reasonably test this) */
        if (_this.props.environment) {
          var _this$props$environme = _this.props.environment.document,
            body = _this$props$environme.body,
            activeElement = _this$props$environme.activeElement;
          if (body && body === activeElement) {
            event.target.focus();
          }
        }
        // to simplify testing components that use downshift, we'll not wrap this in a setTimeout
        // if the NODE_ENV is test. With the proper build system, this should be dead code eliminated
        // when building for production and should therefore have no impact on production code.
        if (process.env.NODE_ENV === 'test') {
          _this.toggleMenu({
            type: clickButton
          });
        } else {
          // Ensure that toggle of menu occurs after the potential blur event in iOS
          _this.internalSetTimeout(function () {
            return _this.toggleMenu({
              type: clickButton
            });
          });
        }
      };
      _this.buttonHandleBlur = function (event) {
        var blurTarget = event.target; // Save blur target for comparison with activeElement later
        // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not body element
        _this.internalSetTimeout(function () {
          if (_this.isMouseDown || !_this.props.environment) {
            return;
          }
          var activeElement = _this.props.environment.document.activeElement;
          if ((activeElement == null || activeElement.id !== _this.inputId) && activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
          ) {
            _this.reset({
              type: blurButton
            });
          }
        });
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ BUTTON
      /////////////////////////////// LABEL
      _this.getLabelProps = function (props) {
        return _extends({
          htmlFor: _this.inputId,
          id: _this.labelId
        }, props);
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ LABEL
      /////////////////////////////// INPUT
      _this.getInputProps = function (_temp4) {
        var _ref4 = _temp4 === void 0 ? {} : _temp4,
          onKeyDown = _ref4.onKeyDown,
          onBlur = _ref4.onBlur,
          onChange = _ref4.onChange,
          onInput = _ref4.onInput;
          _ref4.onChangeText;
          var rest = _objectWithoutPropertiesLoose(_ref4, _excluded3$3);
        var onChangeKey;
        var eventHandlers = {};

        /* istanbul ignore next (preact) */
        {
          onChangeKey = 'onChange';
        }
        var _this$getState6 = _this.getState(),
          inputValue = _this$getState6.inputValue,
          isOpen = _this$getState6.isOpen,
          highlightedIndex = _this$getState6.highlightedIndex;
        if (!rest.disabled) {
          var _eventHandlers;
          eventHandlers = (_eventHandlers = {}, _eventHandlers[onChangeKey] = callAllEventHandlers(onChange, onInput, _this.inputHandleChange), _eventHandlers.onKeyDown = callAllEventHandlers(onKeyDown, _this.inputHandleKeyDown), _eventHandlers.onBlur = callAllEventHandlers(onBlur, _this.inputHandleBlur), _eventHandlers);
        }
        return _extends({
          'aria-autocomplete': 'list',
          'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : undefined,
          'aria-controls': isOpen ? _this.menuId : undefined,
          'aria-labelledby': rest && rest['aria-label'] ? undefined : _this.labelId,
          // https://developer.mozilla.org/en-US/docs/Web/Security/Securing_your_site/Turning_off_form_autocompletion
          // revert back since autocomplete="nope" is ignored on latest Chrome and Opera
          autoComplete: 'off',
          value: inputValue,
          id: _this.inputId
        }, eventHandlers, rest);
      };
      _this.inputHandleKeyDown = function (event) {
        var key = normalizeArrowKey(event);
        if (key && _this.inputKeyDownHandlers[key]) {
          _this.inputKeyDownHandlers[key].call(_this, event);
        }
      };
      _this.inputHandleChange = function (event) {
        _this.internalSetState({
          type: changeInput,
          isOpen: true,
          inputValue: event.target.value,
          highlightedIndex: _this.props.defaultHighlightedIndex
        });
      };
      _this.inputHandleBlur = function () {
        // Need setTimeout, so that when the user presses Tab, the activeElement is the next focused element, not the body element
        _this.internalSetTimeout(function () {
          var _activeElement$datase;
          if (_this.isMouseDown || !_this.props.environment) {
            return;
          }
          var activeElement = _this.props.environment.document.activeElement;
          var downshiftButtonIsActive = (activeElement == null || (_activeElement$datase = activeElement.dataset) == null ? void 0 : _activeElement$datase.toggle) && _this._rootNode && _this._rootNode.contains(activeElement);
          if (!downshiftButtonIsActive) {
            _this.reset({
              type: blurInput
            });
          }
        });
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ INPUT
      /////////////////////////////// MENU
      _this.menuRef = function (node) {
        _this._menuNode = node;
      };
      _this.getMenuProps = function (_temp5, _temp6) {
        var _extends3;
        var _ref5 = _temp5 === void 0 ? {} : _temp5,
          _ref5$refKey = _ref5.refKey,
          refKey = _ref5$refKey === void 0 ? 'ref' : _ref5$refKey,
          ref = _ref5.ref,
          props = _objectWithoutPropertiesLoose(_ref5, _excluded4$2);
        var _ref6 = _temp6 === void 0 ? {} : _temp6,
          _ref6$suppressRefErro = _ref6.suppressRefError,
          suppressRefError = _ref6$suppressRefErro === void 0 ? false : _ref6$suppressRefErro;
        _this.getMenuProps.called = true;
        _this.getMenuProps.refKey = refKey;
        _this.getMenuProps.suppressRefError = suppressRefError;
        return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, _this.menuRef), _extends3.role = 'listbox', _extends3['aria-labelledby'] = props && props['aria-label'] ? undefined : _this.labelId, _extends3.id = _this.menuId, _extends3), props);
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ MENU
      /////////////////////////////// ITEM
      _this.getItemProps = function (_temp7) {
        var _enabledEventHandlers;
        var _ref7 = _temp7 === void 0 ? {} : _temp7,
          onMouseMove = _ref7.onMouseMove,
          onMouseDown = _ref7.onMouseDown,
          onClick = _ref7.onClick;
          _ref7.onPress;
          var index = _ref7.index,
          _ref7$item = _ref7.item,
          item = _ref7$item === void 0 ? process.env.NODE_ENV === 'production' ? /* istanbul ignore next */undefined : requiredProp('getItemProps', 'item') : _ref7$item,
          rest = _objectWithoutPropertiesLoose(_ref7, _excluded5);
        if (index === undefined) {
          _this.items.push(item);
          index = _this.items.indexOf(item);
        } else {
          _this.items[index] = item;
        }
        var onSelectKey = 'onClick';
        var customClickHandler = onClick;
        var enabledEventHandlers = (_enabledEventHandlers = {
          // onMouseMove is used over onMouseEnter here. onMouseMove
          // is only triggered on actual mouse movement while onMouseEnter
          // can fire on DOM changes, interrupting keyboard navigation
          onMouseMove: callAllEventHandlers(onMouseMove, function () {
            if (index === _this.getState().highlightedIndex) {
              return;
            }
            _this.setHighlightedIndex(index, {
              type: itemMouseEnter
            });

            // We never want to manually scroll when changing state based
            // on `onMouseMove` because we will be moving the element out
            // from under the user which is currently scrolling/moving the
            // cursor
            _this.avoidScrolling = true;
            _this.internalSetTimeout(function () {
              return _this.avoidScrolling = false;
            }, 250);
          }),
          onMouseDown: callAllEventHandlers(onMouseDown, function (event) {
            // This prevents the activeElement from being changed
            // to the item so it can remain with the current activeElement
            // which is a more common use case.
            event.preventDefault();
          })
        }, _enabledEventHandlers[onSelectKey] = callAllEventHandlers(customClickHandler, function () {
          _this.selectItemAtIndex(index, {
            type: clickItem
          });
        }), _enabledEventHandlers);

        // Passing down the onMouseDown handler to prevent redirect
        // of the activeElement if clicking on disabled items
        var eventHandlers = rest.disabled ? {
          onMouseDown: enabledEventHandlers.onMouseDown
        } : enabledEventHandlers;
        return _extends({
          id: _this.getItemId(index),
          role: 'option',
          'aria-selected': _this.getState().highlightedIndex === index
        }, eventHandlers, rest);
      };
      //\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ITEM
      _this.clearItems = function () {
        _this.items = [];
      };
      _this.reset = function (otherStateToSet, cb) {
        if (otherStateToSet === void 0) {
          otherStateToSet = {};
        }
        otherStateToSet = pickState(otherStateToSet);
        _this.internalSetState(function (_ref8) {
          var selectedItem = _ref8.selectedItem;
          return _extends({
            isOpen: _this.props.defaultIsOpen,
            highlightedIndex: _this.props.defaultHighlightedIndex,
            inputValue: _this.props.itemToString(selectedItem)
          }, otherStateToSet);
        }, cb);
      };
      _this.toggleMenu = function (otherStateToSet, cb) {
        if (otherStateToSet === void 0) {
          otherStateToSet = {};
        }
        otherStateToSet = pickState(otherStateToSet);
        _this.internalSetState(function (_ref9) {
          var isOpen = _ref9.isOpen;
          return _extends({
            isOpen: !isOpen
          }, isOpen && {
            highlightedIndex: _this.props.defaultHighlightedIndex
          }, otherStateToSet);
        }, function () {
          var _this$getState7 = _this.getState(),
            isOpen = _this$getState7.isOpen,
            highlightedIndex = _this$getState7.highlightedIndex;
          if (isOpen) {
            if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
              _this.setHighlightedIndex(highlightedIndex, otherStateToSet);
            }
          }
          cbToCb(cb)();
        });
      };
      _this.openMenu = function (cb) {
        _this.internalSetState({
          isOpen: true
        }, cb);
      };
      _this.closeMenu = function (cb) {
        _this.internalSetState({
          isOpen: false
        }, cb);
      };
      _this.updateStatus = debounce(function () {
        var _this$props;
        if (!((_this$props = _this.props) != null && (_this$props = _this$props.environment) != null && _this$props.document)) {
          return;
        }
        var state = _this.getState();
        var item = _this.items[state.highlightedIndex];
        var resultCount = _this.getItemCount();
        var status = _this.props.getA11yStatusMessage(_extends({
          itemToString: _this.props.itemToString,
          previousResultCount: _this.previousResultCount,
          resultCount: resultCount,
          highlightedItem: item
        }, state));
        _this.previousResultCount = resultCount;
        setStatus(status, _this.props.environment.document);
      }, 200);
      var _this$props2 = _this.props,
        defaultHighlightedIndex = _this$props2.defaultHighlightedIndex,
        _this$props2$initialH = _this$props2.initialHighlightedIndex,
        _highlightedIndex = _this$props2$initialH === void 0 ? defaultHighlightedIndex : _this$props2$initialH,
        defaultIsOpen = _this$props2.defaultIsOpen,
        _this$props2$initialI = _this$props2.initialIsOpen,
        _isOpen = _this$props2$initialI === void 0 ? defaultIsOpen : _this$props2$initialI,
        _this$props2$initialI2 = _this$props2.initialInputValue,
        _inputValue = _this$props2$initialI2 === void 0 ? '' : _this$props2$initialI2,
        _this$props2$initialS = _this$props2.initialSelectedItem,
        _selectedItem = _this$props2$initialS === void 0 ? null : _this$props2$initialS;
      var _state = _this.getState({
        highlightedIndex: _highlightedIndex,
        isOpen: _isOpen,
        inputValue: _inputValue,
        selectedItem: _selectedItem
      });
      if (_state.selectedItem != null && _this.props.initialInputValue === undefined) {
        _state.inputValue = _this.props.itemToString(_state.selectedItem);
      }
      _this.state = _state;
      return _this;
    }
    _inheritsLoose(Downshift, _Component);
    var _proto = Downshift.prototype;
    /**
     * Clear all running timeouts
     */
    _proto.internalClearTimeouts = function internalClearTimeouts() {
      this.timeoutIds.forEach(function (id) {
        clearTimeout(id);
      });
      this.timeoutIds = [];
    }

    /**
     * Gets the state based on internal state or props
     * If a state value is passed via props, then that
     * is the value given, otherwise it's retrieved from
     * stateToMerge
     *
     * @param {Object} stateToMerge defaults to this.state
     * @return {Object} the state
     */;
    _proto.getState = function getState$1(stateToMerge) {
      if (stateToMerge === void 0) {
        stateToMerge = this.state;
      }
      return getState(stateToMerge, this.props);
    };
    _proto.getItemCount = function getItemCount() {
      // things read better this way. They're in priority order:
      // 1. `this.itemCount`
      // 2. `this.props.itemCount`
      // 3. `this.items.length`
      var itemCount = this.items.length;
      if (this.itemCount != null) {
        itemCount = this.itemCount;
      } else if (this.props.itemCount !== undefined) {
        itemCount = this.props.itemCount;
      }
      return itemCount;
    };
    _proto.getItemNodeFromIndex = function getItemNodeFromIndex(index) {
      return this.props.environment ? this.props.environment.document.getElementById(this.getItemId(index)) : null;
    };
    _proto.scrollHighlightedItemIntoView = function scrollHighlightedItemIntoView() {
      /* istanbul ignore else (react-native) */
      {
        var node = this.getItemNodeFromIndex(this.getState().highlightedIndex);
        this.props.scrollIntoView(node, this._menuNode);
      }
    };
    _proto.moveHighlightedIndex = function moveHighlightedIndex(amount, otherStateToSet) {
      var itemCount = this.getItemCount();
      var _this$getState8 = this.getState(),
        highlightedIndex = _this$getState8.highlightedIndex;
      if (itemCount > 0) {
        var nextHighlightedIndex = getHighlightedIndex(highlightedIndex, amount, {
          length: itemCount
        }, this.isItemDisabled, true);
        this.setHighlightedIndex(nextHighlightedIndex, otherStateToSet);
      }
    };
    _proto.getStateAndHelpers = function getStateAndHelpers() {
      var _this$getState9 = this.getState(),
        highlightedIndex = _this$getState9.highlightedIndex,
        inputValue = _this$getState9.inputValue,
        selectedItem = _this$getState9.selectedItem,
        isOpen = _this$getState9.isOpen;
      var itemToString = this.props.itemToString;
      var id = this.id;
      var getRootProps = this.getRootProps,
        getToggleButtonProps = this.getToggleButtonProps,
        getLabelProps = this.getLabelProps,
        getMenuProps = this.getMenuProps,
        getInputProps = this.getInputProps,
        getItemProps = this.getItemProps,
        openMenu = this.openMenu,
        closeMenu = this.closeMenu,
        toggleMenu = this.toggleMenu,
        selectItem = this.selectItem,
        selectItemAtIndex = this.selectItemAtIndex,
        selectHighlightedItem = this.selectHighlightedItem,
        setHighlightedIndex = this.setHighlightedIndex,
        clearSelection = this.clearSelection,
        clearItems = this.clearItems,
        reset = this.reset,
        setItemCount = this.setItemCount,
        unsetItemCount = this.unsetItemCount,
        setState = this.internalSetState;
      return {
        // prop getters
        getRootProps: getRootProps,
        getToggleButtonProps: getToggleButtonProps,
        getLabelProps: getLabelProps,
        getMenuProps: getMenuProps,
        getInputProps: getInputProps,
        getItemProps: getItemProps,
        // actions
        reset: reset,
        openMenu: openMenu,
        closeMenu: closeMenu,
        toggleMenu: toggleMenu,
        selectItem: selectItem,
        selectItemAtIndex: selectItemAtIndex,
        selectHighlightedItem: selectHighlightedItem,
        setHighlightedIndex: setHighlightedIndex,
        clearSelection: clearSelection,
        clearItems: clearItems,
        setItemCount: setItemCount,
        unsetItemCount: unsetItemCount,
        setState: setState,
        // props
        itemToString: itemToString,
        // derived
        id: id,
        // state
        highlightedIndex: highlightedIndex,
        inputValue: inputValue,
        isOpen: isOpen,
        selectedItem: selectedItem
      };
    };
    _proto.componentDidMount = function componentDidMount() {
      var _this4 = this;
      /* istanbul ignore if (react-native) */
      if (process.env.NODE_ENV !== 'production' && true && this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
        validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
      }

      /* istanbul ignore if (react-native or SSR) */
      if (!this.props.environment) {
        this.cleanup = function () {
          _this4.internalClearTimeouts();
        };
      } else {
        // this.isMouseDown helps us track whether the mouse is currently held down.
        // This is useful when the user clicks on an item in the list, but holds the mouse
        // down long enough for the list to disappear (because the blur event fires on the input)
        // this.isMouseDown is used in the blur handler on the input to determine whether the blur event should
        // trigger hiding the menu.
        var onMouseDown = function onMouseDown() {
          _this4.isMouseDown = true;
        };
        var onMouseUp = function onMouseUp(event) {
          _this4.isMouseDown = false;
          // if the target element or the activeElement is within a downshift node
          // then we don't want to reset downshift
          var contextWithinDownshift = targetWithinDownshift(event.target, [_this4._rootNode, _this4._menuNode], _this4.props.environment);
          if (!contextWithinDownshift && _this4.getState().isOpen) {
            _this4.reset({
              type: mouseUp
            }, function () {
              return _this4.props.onOuterClick(_this4.getStateAndHelpers());
            });
          }
        };
        // Touching an element in iOS gives focus and hover states, but touching out of
        // the element will remove hover, and persist the focus state, resulting in the
        // blur event not being triggered.
        // this.isTouchMove helps us track whether the user is tapping or swiping on a touch screen.
        // If the user taps outside of Downshift, the component should be reset,
        // but not if the user is swiping
        var onTouchStart = function onTouchStart() {
          _this4.isTouchMove = false;
        };
        var onTouchMove = function onTouchMove() {
          _this4.isTouchMove = true;
        };
        var onTouchEnd = function onTouchEnd(event) {
          var contextWithinDownshift = targetWithinDownshift(event.target, [_this4._rootNode, _this4._menuNode], _this4.props.environment, false);
          if (!_this4.isTouchMove && !contextWithinDownshift && _this4.getState().isOpen) {
            _this4.reset({
              type: touchEnd
            }, function () {
              return _this4.props.onOuterClick(_this4.getStateAndHelpers());
            });
          }
        };
        var environment = this.props.environment;
        environment.addEventListener('mousedown', onMouseDown);
        environment.addEventListener('mouseup', onMouseUp);
        environment.addEventListener('touchstart', onTouchStart);
        environment.addEventListener('touchmove', onTouchMove);
        environment.addEventListener('touchend', onTouchEnd);
        this.cleanup = function () {
          _this4.internalClearTimeouts();
          _this4.updateStatus.cancel();
          environment.removeEventListener('mousedown', onMouseDown);
          environment.removeEventListener('mouseup', onMouseUp);
          environment.removeEventListener('touchstart', onTouchStart);
          environment.removeEventListener('touchmove', onTouchMove);
          environment.removeEventListener('touchend', onTouchEnd);
        };
      }
    };
    _proto.shouldScroll = function shouldScroll(prevState, prevProps) {
      var _ref0 = this.props.highlightedIndex === undefined ? this.getState() : this.props,
        currentHighlightedIndex = _ref0.highlightedIndex;
      var _ref1 = prevProps.highlightedIndex === undefined ? prevState : prevProps,
        prevHighlightedIndex = _ref1.highlightedIndex;
      var scrollWhenOpen = currentHighlightedIndex && this.getState().isOpen && !prevState.isOpen;
      var scrollWhenNavigating = currentHighlightedIndex !== prevHighlightedIndex;
      return scrollWhenOpen || scrollWhenNavigating;
    };
    _proto.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
      if (process.env.NODE_ENV !== 'production') {
        validateControlledUnchanged(this.state, prevProps, this.props);
        /* istanbul ignore if (react-native) */
        if (this.getMenuProps.called && !this.getMenuProps.suppressRefError) {
          validateGetMenuPropsCalledCorrectly(this._menuNode, this.getMenuProps);
        }
      }
      if (isControlledProp(this.props, 'selectedItem') && this.props.selectedItemChanged(prevProps.selectedItem, this.props.selectedItem)) {
        this.internalSetState({
          type: controlledPropUpdatedSelectedItem,
          inputValue: this.props.itemToString(this.props.selectedItem)
        });
      }
      if (!this.avoidScrolling && this.shouldScroll(prevState, prevProps)) {
        this.scrollHighlightedItemIntoView();
      }

      /* istanbul ignore else (react-native) */
      {
        this.updateStatus();
      }
    };
    _proto.componentWillUnmount = function componentWillUnmount() {
      this.cleanup(); // avoids memory leak
    };
    _proto.render = function render() {
      var children = unwrapArray(this.props.children, noop);
      // because the items are rerendered every time we call the children
      // we clear this out each render and it will be populated again as
      // getItemProps is called.
      this.clearItems();
      // we reset this so we know whether the user calls getRootProps during
      // this render. If they do then we don't need to do anything,
      // if they don't then we need to clone the element they return and
      // apply the props for them.
      this.getRootProps.called = false;
      this.getRootProps.refKey = undefined;
      this.getRootProps.suppressRefError = undefined;
      // we do something similar for getMenuProps
      this.getMenuProps.called = false;
      this.getMenuProps.refKey = undefined;
      this.getMenuProps.suppressRefError = undefined;
      // we do something similar for getLabelProps
      this.getLabelProps.called = false;
      // and something similar for getInputProps
      this.getInputProps.called = false;
      var element = unwrapArray(children(this.getStateAndHelpers()));
      if (!element) {
        return null;
      }
      if (this.getRootProps.called || this.props.suppressRefError) {
        if (process.env.NODE_ENV !== 'production' && !this.getRootProps.suppressRefError && !this.props.suppressRefError) {
          validateGetRootPropsCalledCorrectly(element, this.getRootProps);
        }
        return element;
      } else if (isDOMElement(element)) {
        // they didn't apply the root props, but we can clone
        // this and apply the props ourselves
        return /*#__PURE__*/cloneElement(element, this.getRootProps(getElementProps(element)));
      }

      /* istanbul ignore else */
      if (process.env.NODE_ENV !== 'production') {
        // they didn't apply the root props, but they need to
        // otherwise we can't query around the autocomplete

        throw new Error('downshift: If you return a non-DOM element, you must apply the getRootProps function');
      }

      /* istanbul ignore next */
      return undefined;
    };
    return Downshift;
  }(Component);
  Downshift.defaultProps = {
    defaultHighlightedIndex: null,
    defaultIsOpen: false,
    getA11yStatusMessage: getA11yStatusMessage,
    itemToString: function itemToString(i) {
      if (i == null) {
        return '';
      }
      if (process.env.NODE_ENV !== 'production' && isPlainObject(i) && !i.hasOwnProperty('toString')) {
        // eslint-disable-next-line no-console
        console.warn('downshift: An object was passed to the default implementation of `itemToString`. You should probably provide your own `itemToString` implementation. Please refer to the `itemToString` API documentation.', 'The object that was passed:', i);
      }
      return String(i);
    },
    onStateChange: noop,
    onInputValueChange: noop,
    onUserAction: noop,
    onChange: noop,
    onSelect: noop,
    onOuterClick: noop,
    selectedItemChanged: function selectedItemChanged(prevItem, item) {
      return prevItem !== item;
    },
    environment: /* istanbul ignore next (ssr) */
    typeof window === 'undefined' || false ? undefined : window,
    stateReducer: function stateReducer(state, stateToSet) {
      return stateToSet;
    },
    suppressRefError: false,
    scrollIntoView: scrollIntoView
  };
  Downshift.stateChangeTypes = stateChangeTypes$4;
  return Downshift;
}();
process.env.NODE_ENV !== "production" ? Downshift.propTypes = {
  children: PropTypes.func,
  defaultHighlightedIndex: PropTypes.number,
  defaultIsOpen: PropTypes.bool,
  initialHighlightedIndex: PropTypes.number,
  initialSelectedItem: PropTypes.any,
  initialInputValue: PropTypes.string,
  initialIsOpen: PropTypes.bool,
  getA11yStatusMessage: PropTypes.func,
  itemToString: PropTypes.func,
  onChange: PropTypes.func,
  onSelect: PropTypes.func,
  onStateChange: PropTypes.func,
  onInputValueChange: PropTypes.func,
  onUserAction: PropTypes.func,
  onOuterClick: PropTypes.func,
  selectedItemChanged: PropTypes.func,
  stateReducer: PropTypes.func,
  itemCount: PropTypes.number,
  id: PropTypes.string,
  environment: PropTypes.shape({
    addEventListener: PropTypes.func.isRequired,
    removeEventListener: PropTypes.func.isRequired,
    document: PropTypes.shape({
      createElement: PropTypes.func.isRequired,
      getElementById: PropTypes.func.isRequired,
      activeElement: PropTypes.any.isRequired,
      body: PropTypes.any.isRequired
    }).isRequired,
    Node: PropTypes.func.isRequired
  }),
  suppressRefError: PropTypes.bool,
  scrollIntoView: PropTypes.func,
  // things we keep in state for uncontrolled components
  // but can accept as props for controlled components
  /* eslint-disable react/no-unused-prop-types */
  selectedItem: PropTypes.any,
  isOpen: PropTypes.bool,
  inputValue: PropTypes.string,
  highlightedIndex: PropTypes.number,
  labelId: PropTypes.string,
  inputId: PropTypes.string,
  menuId: PropTypes.string,
  getItemId: PropTypes.func
  /* eslint-enable react/no-unused-prop-types */
} : void 0;
function validateGetMenuPropsCalledCorrectly(node, _ref10) {
  var refKey = _ref10.refKey;
  if (!node) {
    // eslint-disable-next-line no-console
    console.error("downshift: The ref prop \"" + refKey + "\" from getMenuProps was not applied correctly on your menu element.");
  }
}
function validateGetRootPropsCalledCorrectly(element, _ref11) {
  var refKey = _ref11.refKey;
  var refKeySpecified = refKey !== 'ref';
  var isComposite = !isDOMElement(element);
  if (isComposite && !refKeySpecified && !isForwardRef(element)) {
    // eslint-disable-next-line no-console
    console.error('downshift: You returned a non-DOM element. You must specify a refKey in getRootProps');
  } else if (!isComposite && refKeySpecified) {
    // eslint-disable-next-line no-console
    console.error("downshift: You returned a DOM element. You should not specify a refKey in getRootProps. You specified \"" + refKey + "\"");
  }
  if (!isForwardRef(element) && !getElementProps(element)[refKey]) {
    // eslint-disable-next-line no-console
    console.error("downshift: You must apply the ref prop \"" + refKey + "\" from getRootProps onto your root element.");
  }
}

function capitalizeString(string) {
  return "" + string.slice(0, 1).toUpperCase() + string.slice(1);
}

function callOnChangeProps(action, props, state, newState) {
  var type = action.type;
  var changes = {};
  var keys = Object.keys(state);
  for (var _i = 0, _keys = keys; _i < _keys.length; _i++) {
    var key = _keys[_i];
    invokeOnChangeHandler(key, action, props, state, newState);
    if (newState[key] !== state[key]) {
      changes[key] = newState[key];
    }
  }
  if (props.onStateChange && Object.keys(changes).length) {
    props.onStateChange(_extends({
      type: type
    }, changes));
  }
}
function invokeOnChangeHandler(key, action, props, state, newState) {
  if (newState[key] === state[key]) {
    return;
  }
  var handlerKey = "on" + capitalizeString(key) + "Change";
  var handler = props[handlerKey];
  if (typeof handler !== 'function') {
    return;
  }
  var type = action.type;
  handler(_extends({
    type: type
  }, newState));
}

/**
 * Computes the controlled state using a the previous state, props,
 * two reducers, one from downshift and an optional one from the user.
 * Also calls the onChange handlers for state values that have changed.
 *
 * @param {Function} reducer Reducer function from downshift.
 * @param {Object} props The hook props, also passed to createInitialState.
 * @param {Function} createInitialState Function that returns the initial state.
 * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
 * @returns {Array} An array with the state and an action dispatcher.
 */
function useEnhancedReducer(reducer, props, createInitialState, isStateEqual) {
  var prevStateRef = React.useRef(null);
  var actionRef = React.useRef(undefined);
  var propsRef = useLatestRef(props);
  var enhancedReducer = React.useCallback(function (state, action) {
    actionRef.current = action;
    state = getState(state, propsRef.current);
    var changes = reducer(state, propsRef.current, action);
    var newState = propsRef.current.stateReducer(state, _extends({}, action, {
      changes: changes
    }));
    return _extends({}, state, newState);
  }, [propsRef, reducer]);
  var _React$useReducer = React.useReducer(enhancedReducer, props, createInitialState),
    state = _React$useReducer[0],
    dispatch = _React$useReducer[1];
  var action = actionRef.current;
  React.useEffect(function () {
    var _prevStateRef$current;
    var prevState = getState((_prevStateRef$current = prevStateRef.current) != null ? _prevStateRef$current : {}, propsRef.current);
    var shouldCallOnChangeProps = action && prevStateRef.current && !isStateEqual(prevState, state);
    if (shouldCallOnChangeProps) {
      callOnChangeProps(action, propsRef.current, prevState, state);
    }
    prevStateRef.current = state;
  }, [state, action, isStateEqual, propsRef]);
  return [state, dispatch];
}

/**
 * Wraps the useEnhancedReducer and applies the controlled prop values before
 * returning the new state.
 *
 * @param {Function} reducer Reducer function from downshift.
 * @param {Object} props The hook props, also passed to createInitialState.
 * @param {Function} createInitialState Function that returns the initial state.
 * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
 * @returns {Array} An array with the state and an action dispatcher.
 */
function useControlledReducer$1(reducer, props, createInitialState, isStateEqual) {
  var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
    state = _useEnhancedReducer[0],
    dispatch = _useEnhancedReducer[1];
  return [getState(state, props), dispatch];
}

/**
 * Returns both the item and index when both or either is passed.
 *
 * @param itemProp The item which could be undefined.
 * @param indexProp The index which could be undefined.
 * @param items The array of items to get the item based on index.
 * @param errorMessage The error to be thrown if index and item could not be returned for any reason.
 * @returns An array with item and index.
 */
function getItemAndIndex(itemProp, indexProp, items, errorMessage) {
  if (itemProp !== undefined && indexProp !== undefined) {
    return [itemProp, indexProp];
  }
  if (itemProp !== undefined) {
    var index = items.indexOf(itemProp);
    if (index < 0) {
      throw new Error(errorMessage);
    }
    return [itemProp, items.indexOf(itemProp)];
  }
  if (indexProp !== undefined) {
    var item = items[indexProp];
    if (item === undefined) {
      throw new Error(errorMessage);
    }
    return [item, indexProp];
  }
  throw new Error(errorMessage);
}

/**
 * Tracks if it's the first render.
 */
function useIsInitialMount() {
  var isInitialMountRef = React.useRef(true);
  React.useEffect(function () {
    isInitialMountRef.current = false;
    return function () {
      isInitialMountRef.current = true;
    };
  }, []);
  return isInitialMountRef.current;
}

/**
 * Default state reducer that returns the changes.
 *
 */
function stateReducer(_s, a) {
  return a.changes;
}

// Shared between all exports.
var propTypes$5 = {
  environment: PropTypes.shape({
    addEventListener: PropTypes.func.isRequired,
    removeEventListener: PropTypes.func.isRequired,
    document: PropTypes.shape({
      createElement: PropTypes.func.isRequired,
      getElementById: PropTypes.func.isRequired,
      activeElement: PropTypes.any.isRequired,
      body: PropTypes.any.isRequired
    }).isRequired,
    Node: PropTypes.func.isRequired
  }),
  itemToKey: PropTypes.func,
  stateReducer: PropTypes.func
};

function getDefaultValue$1(props, propKey, defaultStateValues) {
  var defaultValue = props["default" + capitalizeString(propKey)];
  if (defaultValue !== undefined) {
    return defaultValue;
  }
  return defaultStateValues[propKey];
}

function getInitialValue$1(props, propKey, defaultStateValues) {
  var value = props[propKey];
  if (value !== undefined) {
    return value;
  }
  var initialValue = props["initial" + capitalizeString(propKey)];
  if (initialValue !== undefined) {
    return initialValue;
  }
  return getDefaultValue$1(props, propKey, defaultStateValues);
}

/**
 * Debounced call for updating the a11y message.
 */
var updateA11yStatus = debounce$1(function (status, document) {
  setStatus(status, document);
}, 200);

/**
 * Adds an a11y aria live status message if getA11yStatusMessage is passed.
 * @param getA11yStatusMessage The function that builds the status message.
 * @param options The options to be passed to getA11yStatusMessage if called.
 * @param dependencyArray The dependency array that triggers the status message setter via useEffect.
 * @param environment The environment object containing the document.
 */
function useA11yMessageStatus(getA11yStatusMessage, options, dependencyArray, environment) {
  var document = environment == null ? void 0 : environment.document;
  var isInitialMount = useIsInitialMount();

  // Adds an a11y aria live status message if getA11yStatusMessage is passed.
  React.useEffect(function () {
    if (!getA11yStatusMessage || isInitialMount || false || !document) {
      return;
    }
    var status = getA11yStatusMessage(options);
    updateA11yStatus(status, document);

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, dependencyArray);

  // Cleanup the status message container.
  React.useEffect(function () {
    return function () {
      updateA11yStatus.cancel();
      cleanupStatusDiv(document);
    };
  }, [document]);
}

// Shared between useSelect, useCombobox, Downshift.
var propTypes$4 = _extends({}, propTypes$5, {
  getA11yStatusMessage: PropTypes.func,
  highlightedIndex: PropTypes.number,
  defaultHighlightedIndex: PropTypes.number,
  initialHighlightedIndex: PropTypes.number,
  isOpen: PropTypes.bool,
  defaultIsOpen: PropTypes.bool,
  initialIsOpen: PropTypes.bool,
  selectedItem: PropTypes.any,
  initialSelectedItem: PropTypes.any,
  defaultSelectedItem: PropTypes.any,
  id: PropTypes.string,
  labelId: PropTypes.string,
  menuId: PropTypes.string,
  getItemId: PropTypes.func,
  toggleButtonId: PropTypes.string,
  onSelectedItemChange: PropTypes.func,
  onHighlightedIndexChange: PropTypes.func,
  onStateChange: PropTypes.func,
  onIsOpenChange: PropTypes.func,
  scrollIntoView: PropTypes.func
});

var defaultProps$3 = {
  itemToString: function itemToString(item) {
    return item ? String(item) : '';
  },
  itemToKey: function itemToKey(item) {
    return item;
  },
  stateReducer: stateReducer,
  scrollIntoView: scrollIntoView,
  environment: /* istanbul ignore next (ssr) */
  typeof window === 'undefined' || false ? undefined : window
};

var defaultStateValues$1 = {
  highlightedIndex: -1,
  isOpen: false,
  selectedItem: null,
  inputValue: ''
};

// istanbul ignore next
var useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? React.useLayoutEffect : React.useEffect;
function isAcceptedCharacterKey(key) {
  return /^\S{1}$/.test(key);
}
function getInitialState$3(props) {
  var selectedItem = getInitialValue$1(props, 'selectedItem', defaultStateValues$1);
  var isOpen = getInitialValue$1(props, 'isOpen', defaultStateValues$1);
  var highlightedIndex = getInitialHighlightedIndex(props);
  var inputValue = getInitialValue$1(props, 'inputValue', defaultStateValues$1);
  return {
    highlightedIndex: highlightedIndex < 0 && selectedItem && isOpen ? props.items.findIndex(function (item) {
      return props.itemToKey(item) === props.itemToKey(selectedItem);
    }) : highlightedIndex,
    isOpen: isOpen,
    selectedItem: selectedItem,
    inputValue: inputValue
  };
}
function getHighlightedIndexOnOpen(props, state, offset) {
  var items = props.items,
    initialHighlightedIndex = props.initialHighlightedIndex,
    defaultHighlightedIndex = props.defaultHighlightedIndex,
    isItemDisabled = props.isItemDisabled,
    itemToKey = props.itemToKey;
  var selectedItem = state.selectedItem,
    highlightedIndex = state.highlightedIndex;
  if (items.length === 0) {
    return -1;
  }

  // initialHighlightedIndex will give value to highlightedIndex on initial state only.
  if (initialHighlightedIndex !== undefined && highlightedIndex === initialHighlightedIndex && !isItemDisabled(items[initialHighlightedIndex], initialHighlightedIndex)) {
    return initialHighlightedIndex;
  }
  if (defaultHighlightedIndex !== undefined && !isItemDisabled(items[defaultHighlightedIndex], defaultHighlightedIndex)) {
    return defaultHighlightedIndex;
  }
  if (selectedItem) {
    return items.findIndex(function (item) {
      return itemToKey(selectedItem) === itemToKey(item);
    });
  }
  if (offset < 0 && !isItemDisabled(items[items.length - 1], items.length - 1)) {
    return items.length - 1;
  }
  if (offset > 0 && !isItemDisabled(items[0], 0)) {
    return 0;
  }
  return -1;
}
/**
 * Tracks mouse and touch events, such as mouseDown, touchMove and touchEnd.
 *
 * @param {Window} environment The environment to add the event listeners to, for instance window.
 * @param {() => void} handleBlur The function that is called if mouseDown or touchEnd occured outside the downshiftElements.
 * @param {Array<{current: HTMLElement}>} downshiftElementsRefs The refs for the elements that should not trigger a blur action from mouseDown or touchEnd.
 * @returns {{isMouseDown: boolean, isTouchMove: boolean, isTouchEnd: boolean}} The mouse and touch events information, if any of are happening.
 */
function useMouseAndTouchTracker(environment, handleBlur, downshiftRefs) {
  var mouseAndTouchTrackersRef = React.useRef({
    isMouseDown: false,
    isTouchMove: false,
    isTouchEnd: false
  });
  var getDownshiftElements = React.useCallback(function () {
    return downshiftRefs.map(function (ref) {
      return ref.current;
    });
  }, [downshiftRefs]);
  React.useEffect(function () {
    if (!environment) {
      return noop;
    }
    function onMouseDown() {
      mouseAndTouchTrackersRef.current.isTouchEnd = false; // reset this one.
      mouseAndTouchTrackersRef.current.isMouseDown = true;
    }
    function onMouseUp(event) {
      mouseAndTouchTrackersRef.current.isMouseDown = false;
      if (!targetWithinDownshift(event.target, getDownshiftElements(), environment)) {
        handleBlur();
      }
    }
    function onTouchStart() {
      mouseAndTouchTrackersRef.current.isTouchEnd = false;
      mouseAndTouchTrackersRef.current.isTouchMove = false;
    }
    function onTouchMove() {
      mouseAndTouchTrackersRef.current.isTouchMove = true;
    }
    function onTouchEnd(event) {
      mouseAndTouchTrackersRef.current.isTouchEnd = true;
      if (!mouseAndTouchTrackersRef.current.isTouchMove && !targetWithinDownshift(event.target, getDownshiftElements(), environment, false)) {
        handleBlur();
      }
    }
    environment.addEventListener('mousedown', onMouseDown);
    environment.addEventListener('mouseup', onMouseUp);
    environment.addEventListener('touchstart', onTouchStart);
    environment.addEventListener('touchmove', onTouchMove);
    environment.addEventListener('touchend', onTouchEnd);
    return function cleanup() {
      environment.removeEventListener('mousedown', onMouseDown);
      environment.removeEventListener('mouseup', onMouseUp);
      environment.removeEventListener('touchstart', onTouchStart);
      environment.removeEventListener('touchmove', onTouchMove);
      environment.removeEventListener('touchend', onTouchEnd);
    };
  }, [environment, getDownshiftElements, handleBlur]);
  return mouseAndTouchTrackersRef.current;
}

/* istanbul ignore next */
// eslint-disable-next-line import/no-mutable-exports
var useGetterPropsCalledChecker = function useGetterPropsCalledChecker() {
  return noop;
};
/**
 * Custom hook that checks if getter props are called correctly.
 *
 * @param  {...any} propKeys Getter prop names to be handled.
 * @returns {Function} Setter function called inside getter props to set call information.
 */
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'production') {
  useGetterPropsCalledChecker = function useGetterPropsCalledChecker() {
    for (var _len = arguments.length, propKeys = new Array(_len), _key = 0; _key < _len; _key++) {
      propKeys[_key] = arguments[_key];
    }
    var getterPropsCalledRef = React.useRef(propKeys.reduce(function (acc, propKey) {
      acc[propKey] = {};
      return acc;
    }, {}));
    React.useEffect(function () {
      Object.keys(getterPropsCalledRef.current).forEach(function (propKey) {
        var propCallInfo = getterPropsCalledRef.current[propKey];
        if (!Object.keys(propCallInfo).length) {
          // eslint-disable-next-line no-console
          console.error("downshift: You forgot to call the " + propKey + " getter function on your component / element.");
          return;
        }
        var suppressRefError = propCallInfo.suppressRefError,
          refKey = propCallInfo.refKey,
          elementRef = propCallInfo.elementRef;
        if (suppressRefError) {
          return;
        }
        if (!(elementRef != null && elementRef.current)) {
          // eslint-disable-next-line no-console
          console.error("downshift: The ref prop \"" + refKey + "\" from " + propKey + " was not applied correctly on your element.");
        }
      });
    }, []);
    var setGetterPropCallInfo = React.useCallback(function (propKey, suppressRefError, refKey, elementRef) {
      getterPropsCalledRef.current[propKey] = {
        suppressRefError: suppressRefError,
        refKey: refKey,
        elementRef: elementRef
      };
    }, []);
    return setGetterPropCallInfo;
  };
}
function useScrollIntoView(_ref) {
  var highlightedIndex = _ref.highlightedIndex,
    isOpen = _ref.isOpen,
    itemRefs = _ref.itemRefs,
    getItemNodeFromIndex = _ref.getItemNodeFromIndex,
    menuElement = _ref.menuElement,
    scrollIntoViewProp = _ref.scrollIntoView;
  // used not to scroll on highlight by mouse.
  var shouldScrollRef = React.useRef(true);
  // Scroll on highlighted item if change comes from keyboard.
  useIsomorphicLayoutEffect(function () {
    if (highlightedIndex < 0 || !isOpen || !Object.keys(itemRefs.current).length) {
      return;
    }
    if (shouldScrollRef.current === false) {
      shouldScrollRef.current = true;
    } else {
      scrollIntoViewProp(getItemNodeFromIndex(highlightedIndex), menuElement);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [highlightedIndex]);
  return shouldScrollRef;
}

// eslint-disable-next-line import/no-mutable-exports
var useControlPropsValidator = noop;
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'production') {
  useControlPropsValidator = function useControlPropsValidator(_ref2) {
    var props = _ref2.props,
      state = _ref2.state;
    // used for checking when props are moving from controlled to uncontrolled.
    var prevPropsRef = React.useRef(props);
    var isInitialMount = useIsInitialMount();
    React.useEffect(function () {
      if (isInitialMount) {
        return;
      }
      validateControlledUnchanged(state, prevPropsRef.current, props);
      prevPropsRef.current = props;
    }, [state, props, isInitialMount]);
  };
}

/**
 * Handles selection on Enter / Alt + ArrowUp. Closes the menu and resets the highlighted index, unless there is a highlighted.
 * In that case, selects the item and resets to defaults for open state and highlighted idex.
 * @param {Object} props The useCombobox props.
 * @param {number} highlightedIndex The index from the state.
 * @param {boolean} inputValue Also return the input value for state.
 * @returns The changes for the state.
 */
function getChangesOnSelection(props, highlightedIndex, inputValue) {
  var _props$items;
  if (inputValue === void 0) {
    inputValue = true;
  }
  var shouldSelect = ((_props$items = props.items) == null ? void 0 : _props$items.length) && highlightedIndex >= 0;
  return _extends({
    isOpen: false,
    highlightedIndex: -1
  }, shouldSelect && _extends({
    selectedItem: props.items[highlightedIndex],
    isOpen: getDefaultValue$1(props, 'isOpen', defaultStateValues$1),
    highlightedIndex: getDefaultValue$1(props, 'highlightedIndex', defaultStateValues$1)
  }, inputValue && {
    inputValue: props.itemToString(props.items[highlightedIndex])
  }));
}

/**
 * Check if a state is equal for dropdowns, by comparing isOpen, inputValue, highlightedIndex and selected item.
 * Used by useSelect and useCombobox.
 *
 * @param {Object} prevState
 * @param {Object} newState
 * @returns {boolean} Wheather the states are deeply equal.
 */
function isDropdownsStateEqual(prevState, newState) {
  return prevState.isOpen === newState.isOpen && prevState.inputValue === newState.inputValue && prevState.highlightedIndex === newState.highlightedIndex && prevState.selectedItem === newState.selectedItem;
}

/**
 * Returns the new highlightedIndex based on the defaultHighlightedIndex prop, if it's not disabled.
 *
 * @param {Object} props Props from useCombobox or useSelect.
 * @returns {number} The highlighted index.
 */
function getDefaultHighlightedIndex(props) {
  var highlightedIndex = getDefaultValue$1(props, 'highlightedIndex', defaultStateValues$1);
  if (highlightedIndex > -1 && props.isItemDisabled(props.items[highlightedIndex], highlightedIndex)) {
    return -1;
  }
  return highlightedIndex;
}

/**
 * Returns the new highlightedIndex based on the initialHighlightedIndex prop, if not disabled.
 *
 * @param {Object} props Props from useCombobox or useSelect.
 * @returns {number} The highlighted index.
 */
function getInitialHighlightedIndex(props) {
  var highlightedIndex = getInitialValue$1(props, 'highlightedIndex', defaultStateValues$1);
  if (highlightedIndex > -1 && props.isItemDisabled(props.items[highlightedIndex], highlightedIndex)) {
    return -1;
  }
  return highlightedIndex;
}

function downshiftCommonReducer(state, props, action, stateChangeTypes) {
  var type = action.type;
  var changes;
  switch (type) {
    case stateChangeTypes.ItemMouseMove:
      changes = {
        highlightedIndex: action.disabled ? -1 : action.index
      };
      break;
    case stateChangeTypes.MenuMouseLeave:
      changes = {
        highlightedIndex: -1
      };
      break;
    case stateChangeTypes.ToggleButtonClick:
    case stateChangeTypes.FunctionToggleMenu:
      changes = {
        isOpen: !state.isOpen,
        highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
      };
      break;
    case stateChangeTypes.FunctionOpenMenu:
      changes = {
        isOpen: true,
        highlightedIndex: getHighlightedIndexOnOpen(props, state, 0)
      };
      break;
    case stateChangeTypes.FunctionCloseMenu:
      changes = {
        isOpen: false
      };
      break;
    case stateChangeTypes.FunctionSetHighlightedIndex:
      changes = {
        highlightedIndex: props.isItemDisabled(props.items[action.highlightedIndex], action.highlightedIndex) ? -1 : action.highlightedIndex
      };
      break;
    case stateChangeTypes.FunctionSetInputValue:
      changes = {
        inputValue: action.inputValue
      };
      break;
    case stateChangeTypes.FunctionReset:
      changes = {
        highlightedIndex: getDefaultHighlightedIndex(props),
        isOpen: getDefaultValue$1(props, 'isOpen', defaultStateValues$1),
        selectedItem: getDefaultValue$1(props, 'selectedItem', defaultStateValues$1),
        inputValue: getDefaultValue$1(props, 'inputValue', defaultStateValues$1)
      };
      break;
    default:
      throw new Error('Reducer called without proper action type.');
  }
  return _extends({}, state, changes);
}
/* eslint-enable complexity */

var propTypes$3 = _extends({}, propTypes$4, {
  items: PropTypes.array.isRequired,
  isItemDisabled: PropTypes.func
});

var defaultProps$2 = _extends({}, defaultProps$3, {
  isItemDisabled: function isItemDisabled() {
    return false;
  }
});

function getItemIndexByCharacterKey(_ref) {
  var keysSoFar = _ref.keysSoFar,
    highlightedIndex = _ref.highlightedIndex,
    items = _ref.items,
    itemToString = _ref.itemToString,
    isItemDisabled = _ref.isItemDisabled;
  var lowerCasedKeysSoFar = keysSoFar.toLowerCase();
  for (var _index = 0; _index < items.length; _index++) {
    // if we already have a search query in progress, we also consider the current highlighted item.
    var offsetIndex = (_index + highlightedIndex + (keysSoFar.length < 2 ? 1 : 0)) % items.length;
    var _item = items[offsetIndex];
    if (_item !== undefined && itemToString(_item).toLowerCase().startsWith(lowerCasedKeysSoFar) && !isItemDisabled(_item, offsetIndex)) {
      return offsetIndex;
    }
  }
  return highlightedIndex;
}

var ToggleButtonClick$1 = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 0;
var ToggleButtonKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_arrow_down__' : 1;
var ToggleButtonKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_arrow_up__' : 2;
var ToggleButtonKeyDownCharacter = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_character__' : 3;
var ToggleButtonKeyDownEscape = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_escape__' : 4;
var ToggleButtonKeyDownHome = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_home__' : 5;
var ToggleButtonKeyDownEnd = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_end__' : 6;
var ToggleButtonKeyDownEnter = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_enter__' : 7;
var ToggleButtonKeyDownSpaceButton = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_space_button__' : 8;
var ToggleButtonKeyDownPageUp = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_page_up__' : 9;
var ToggleButtonKeyDownPageDown = process.env.NODE_ENV !== "production" ? '__togglebutton_keydown_page_down__' : 10;
var ToggleButtonBlur = process.env.NODE_ENV !== "production" ? '__togglebutton_blur__' : 11;
var MenuMouseLeave$1 = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 12;
var ItemMouseMove$1 = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 13;
var ItemClick$1 = process.env.NODE_ENV !== "production" ? '__item_click__' : 14;
var FunctionToggleMenu$1 = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 15;
var FunctionOpenMenu$1 = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 16;
var FunctionCloseMenu$1 = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 17;
var FunctionSetHighlightedIndex$1 = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 18;
var FunctionSelectItem$1 = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 19;
var FunctionSetInputValue$1 = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 20;
var FunctionReset$2 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 21;

var stateChangeTypes$3 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  FunctionCloseMenu: FunctionCloseMenu$1,
  FunctionOpenMenu: FunctionOpenMenu$1,
  FunctionReset: FunctionReset$2,
  FunctionSelectItem: FunctionSelectItem$1,
  FunctionSetHighlightedIndex: FunctionSetHighlightedIndex$1,
  FunctionSetInputValue: FunctionSetInputValue$1,
  FunctionToggleMenu: FunctionToggleMenu$1,
  ItemClick: ItemClick$1,
  ItemMouseMove: ItemMouseMove$1,
  MenuMouseLeave: MenuMouseLeave$1,
  ToggleButtonBlur: ToggleButtonBlur,
  ToggleButtonClick: ToggleButtonClick$1,
  ToggleButtonKeyDownArrowDown: ToggleButtonKeyDownArrowDown,
  ToggleButtonKeyDownArrowUp: ToggleButtonKeyDownArrowUp,
  ToggleButtonKeyDownCharacter: ToggleButtonKeyDownCharacter,
  ToggleButtonKeyDownEnd: ToggleButtonKeyDownEnd,
  ToggleButtonKeyDownEnter: ToggleButtonKeyDownEnter,
  ToggleButtonKeyDownEscape: ToggleButtonKeyDownEscape,
  ToggleButtonKeyDownHome: ToggleButtonKeyDownHome,
  ToggleButtonKeyDownPageDown: ToggleButtonKeyDownPageDown,
  ToggleButtonKeyDownPageUp: ToggleButtonKeyDownPageUp,
  ToggleButtonKeyDownSpaceButton: ToggleButtonKeyDownSpaceButton
});

/* eslint-disable complexity */
function downshiftSelectReducer(state, props, action) {
  var _props$items;
  var type = action.type,
    altKey = action.altKey;
  var changes;
  switch (type) {
    case ItemClick$1:
      changes = {
        isOpen: getDefaultValue$1(props, 'isOpen', defaultStateValues$1),
        highlightedIndex: getDefaultHighlightedIndex(props),
        selectedItem: props.items[action.index]
      };
      break;
    case ToggleButtonKeyDownCharacter:
      {
        var lowercasedKey = action.key;
        var inputValue = "" + state.inputValue + lowercasedKey;
        var prevHighlightedIndex = !state.isOpen && state.selectedItem ? props.items.findIndex(function (item) {
          return props.itemToKey(item) === props.itemToKey(state.selectedItem);
        }) : state.highlightedIndex;
        var highlightedIndex = getItemIndexByCharacterKey({
          keysSoFar: inputValue,
          highlightedIndex: prevHighlightedIndex,
          items: props.items,
          itemToString: props.itemToString,
          isItemDisabled: props.isItemDisabled
        });
        changes = {
          inputValue: inputValue,
          highlightedIndex: highlightedIndex,
          isOpen: true
        };
      }
      break;
    case ToggleButtonKeyDownArrowDown:
      {
        var _highlightedIndex = state.isOpen ? getHighlightedIndex(state.highlightedIndex, 1, props.items, props.isItemDisabled) : altKey && state.selectedItem == null ? -1 : getHighlightedIndexOnOpen(props, state, 1);
        changes = {
          highlightedIndex: _highlightedIndex,
          isOpen: true
        };
      }
      break;
    case ToggleButtonKeyDownArrowUp:
      if (state.isOpen && altKey) {
        changes = getChangesOnSelection(props, state.highlightedIndex, false);
      } else {
        var _highlightedIndex2 = state.isOpen ? getHighlightedIndex(state.highlightedIndex, -1, props.items, props.isItemDisabled) : getHighlightedIndexOnOpen(props, state, -1);
        changes = {
          highlightedIndex: _highlightedIndex2,
          isOpen: true
        };
      }
      break;
    // only triggered when menu is open.
    case ToggleButtonKeyDownEnter:
    case ToggleButtonKeyDownSpaceButton:
      changes = getChangesOnSelection(props, state.highlightedIndex, false);
      break;
    case ToggleButtonKeyDownHome:
      changes = {
        highlightedIndex: getNonDisabledIndex(0, false, props.items, props.isItemDisabled),
        isOpen: true
      };
      break;
    case ToggleButtonKeyDownEnd:
      changes = {
        highlightedIndex: getNonDisabledIndex(props.items.length - 1, true, props.items, props.isItemDisabled),
        isOpen: true
      };
      break;
    case ToggleButtonKeyDownPageUp:
      changes = {
        highlightedIndex: getHighlightedIndex(state.highlightedIndex, -10, props.items, props.isItemDisabled)
      };
      break;
    case ToggleButtonKeyDownPageDown:
      changes = {
        highlightedIndex: getHighlightedIndex(state.highlightedIndex, 10, props.items, props.isItemDisabled)
      };
      break;
    case ToggleButtonKeyDownEscape:
      changes = {
        isOpen: false,
        highlightedIndex: -1
      };
      break;
    case ToggleButtonBlur:
      changes = _extends({
        isOpen: false,
        highlightedIndex: -1
      }, state.highlightedIndex >= 0 && ((_props$items = props.items) == null ? void 0 : _props$items.length) && {
        selectedItem: props.items[state.highlightedIndex]
      });
      break;
    case FunctionSelectItem$1:
      changes = {
        selectedItem: action.selectedItem
      };
      break;
    default:
      return downshiftCommonReducer(state, props, action, stateChangeTypes$3);
  }
  return _extends({}, state, changes);
}
/* eslint-enable complexity */

// https://github.com/downshift-js/downshift/issues/1674#issuecomment-3924320872
var SafeReact$1 = _extends({}, React);
var reactUseId$1 = SafeReact$1.useId;
var useElementIds$1 = typeof reactUseId$1 === 'function' ? useElementIdsR18$1 : useElementIdsLegacy$1;
function useElementIdsR18$1(_ref) {
  var id = _ref.id,
    labelId = _ref.labelId,
    menuId = _ref.menuId,
    getItemId = _ref.getItemId,
    toggleButtonId = _ref.toggleButtonId,
    inputId = _ref.inputId;
  var reactId = "downshift-" + reactUseId$1();
  if (!id) {
    id = reactId;
  }
  var elementIds = React.useMemo(function () {
    return {
      labelId: labelId != null ? labelId : id + "-label",
      menuId: menuId != null ? menuId : id + "-menu",
      getItemId: getItemId != null ? getItemId : function (index) {
        return id + "-item-" + index;
      },
      toggleButtonId: toggleButtonId != null ? toggleButtonId : id + "-toggle-button",
      inputId: inputId != null ? inputId : id + "-input"
    };
  }, [getItemId, id, inputId, labelId, menuId, toggleButtonId]);
  return elementIds;
}
function useElementIdsLegacy$1(_ref2) {
  var id = _ref2.id,
    labelId = _ref2.labelId,
    menuId = _ref2.menuId,
    getItemId = _ref2.getItemId,
    toggleButtonId = _ref2.toggleButtonId,
    inputId = _ref2.inputId;
  var baseIdRef = React.useRef(id != null ? id : "downshift-" + generateId());
  var baseId = baseIdRef.current;
  var elementIds = React.useMemo(function () {
    return {
      labelId: labelId != null ? labelId : baseId + "-label",
      menuId: menuId != null ? menuId : baseId + "-menu",
      getItemId: getItemId != null ? getItemId : function (index) {
        return baseId + "-item-" + index;
      },
      toggleButtonId: toggleButtonId != null ? toggleButtonId : baseId + "-toggle-button",
      inputId: inputId != null ? inputId : baseId + "-input"
    };
  }, [getItemId, inputId, labelId, menuId, toggleButtonId, baseId]);
  return elementIds;
}

var _excluded$3 = ["onClick"],
  _excluded2$3 = ["onMouseLeave", "refKey", "ref"],
  _excluded3$2 = ["onBlur", "onClick", "onPress", "onKeyDown", "refKey", "ref"],
  _excluded4$1 = ["item", "index", "onMouseMove", "onClick", "onMouseDown", "onPress", "refKey", "disabled", "ref"];
useSelect.stateChangeTypes = stateChangeTypes$3;
function useSelect(userProps) {
  if (userProps === void 0) {
    userProps = {};
  }
  validatePropTypes$1(userProps, useSelect, propTypes$3);
  // Props defaults and destructuring.
  var props = _extends({}, defaultProps$2, userProps);
  var scrollIntoView = props.scrollIntoView,
    environment = props.environment,
    getA11yStatusMessage = props.getA11yStatusMessage;
  // Initial state depending on controlled props.
  var _useControlledReducer = useControlledReducer$1(downshiftSelectReducer, props, getInitialState$3, isDropdownsStateEqual),
    state = _useControlledReducer[0],
    dispatch = _useControlledReducer[1];
  var isOpen = state.isOpen,
    highlightedIndex = state.highlightedIndex,
    selectedItem = state.selectedItem,
    inputValue = state.inputValue;
  // Element efs.
  var toggleButtonRef = useRef(null);
  var menuRef = useRef(null);
  var itemRefs = useRef({});

  // used to keep the inputValue clearTimeout object between renders.
  var clearTimeoutRef = useRef(null);
  // prevent id re-generation between renders.
  var elementIds = useElementIds$1(props);
  // utility callback to get item element.
  var latest = useLatestRef({
    state: state,
    props: props
  });

  // Some utils.
  var getItemNodeFromIndex = useCallback(function (index) {
    return itemRefs.current[elementIds.getItemId(index)];
  }, [elementIds]);

  // Effects.
  // Adds an a11y aria live status message if getA11yStatusMessage is passed.
  useA11yMessageStatus(getA11yStatusMessage, state, [isOpen, highlightedIndex, selectedItem, inputValue], environment);
  // Scroll on highlighted item if change comes from keyboard.
  var shouldScrollRef = useScrollIntoView({
    menuElement: menuRef.current,
    highlightedIndex: highlightedIndex,
    isOpen: isOpen,
    itemRefs: itemRefs,
    scrollIntoView: scrollIntoView,
    getItemNodeFromIndex: getItemNodeFromIndex
  });
  // Sets cleanup for the keysSoFar callback, debounded after 500ms.
  useEffect(function () {
    // init the clean function here as we need access to dispatch.
    clearTimeoutRef.current = debounce(function (outerDispatch) {
      outerDispatch({
        type: FunctionSetInputValue$1,
        inputValue: ''
      });
    }, 500);

    // Cancel any pending debounced calls on mount
    return function () {
      clearTimeoutRef.current.cancel();
    };
  }, []);
  // Invokes the keysSoFar callback set up above.
  useEffect(function () {
    if (!inputValue) {
      return;
    }
    clearTimeoutRef.current(dispatch);
  }, [dispatch, inputValue]);
  useControlPropsValidator({
    props: props,
    state: state
  });
  // Focus the toggle button on first render if required.
  useEffect(function () {
    var focusOnOpen = getInitialValue$1(props, 'isOpen', defaultStateValues$1);
    if (focusOnOpen && toggleButtonRef.current) {
      toggleButtonRef.current.focus();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  var handleBlurInTracker = useCallback(function handleBlur() {
    if (latest.current.state.isOpen) {
      dispatch({
        type: ToggleButtonBlur
      });
    }
  }, [dispatch, latest]);
  var downshiftRefs = useMemo(function () {
    return [menuRef, toggleButtonRef];
  }, []);
  var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, handleBlurInTracker, downshiftRefs);
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getMenuProps', 'getToggleButtonProps');
  // Reset itemRefs on close.
  useEffect(function () {
    if (!isOpen) {
      itemRefs.current = {};
    }
  }, [isOpen]);

  // Event handler functions.
  var toggleButtonKeyDownHandlers = useMemo(function () {
    return {
      ArrowDown: function ArrowDown(event) {
        event.preventDefault();
        dispatch({
          type: ToggleButtonKeyDownArrowDown,
          altKey: event.altKey
        });
      },
      ArrowUp: function ArrowUp(event) {
        event.preventDefault();
        dispatch({
          type: ToggleButtonKeyDownArrowUp,
          altKey: event.altKey
        });
      },
      Home: function Home(event) {
        event.preventDefault();
        dispatch({
          type: ToggleButtonKeyDownHome
        });
      },
      End: function End(event) {
        event.preventDefault();
        dispatch({
          type: ToggleButtonKeyDownEnd
        });
      },
      Escape: function Escape() {
        if (latest.current.state.isOpen) {
          dispatch({
            type: ToggleButtonKeyDownEscape
          });
        }
      },
      Enter: function Enter(event) {
        event.preventDefault();
        dispatch({
          type: latest.current.state.isOpen ? ToggleButtonKeyDownEnter : ToggleButtonClick$1
        });
      },
      PageUp: function PageUp(event) {
        if (latest.current.state.isOpen) {
          event.preventDefault();
          dispatch({
            type: ToggleButtonKeyDownPageUp
          });
        }
      },
      PageDown: function PageDown(event) {
        if (latest.current.state.isOpen) {
          event.preventDefault();
          dispatch({
            type: ToggleButtonKeyDownPageDown
          });
        }
      },
      ' ': function _(event) {
        event.preventDefault();
        var currentState = latest.current.state;
        if (!currentState.isOpen) {
          dispatch({
            type: ToggleButtonClick$1
          });
          return;
        }
        if (currentState.inputValue) {
          dispatch({
            type: ToggleButtonKeyDownCharacter,
            key: ' '
          });
        } else {
          dispatch({
            type: ToggleButtonKeyDownSpaceButton
          });
        }
      }
    };
  }, [dispatch, latest]);

  // Action functions.
  var toggleMenu = useCallback(function () {
    dispatch({
      type: FunctionToggleMenu$1
    });
  }, [dispatch]);
  var closeMenu = useCallback(function () {
    dispatch({
      type: FunctionCloseMenu$1
    });
  }, [dispatch]);
  var openMenu = useCallback(function () {
    dispatch({
      type: FunctionOpenMenu$1
    });
  }, [dispatch]);
  var setHighlightedIndex = useCallback(function (newHighlightedIndex) {
    dispatch({
      type: FunctionSetHighlightedIndex$1,
      highlightedIndex: newHighlightedIndex
    });
  }, [dispatch]);
  var selectItem = useCallback(function (newSelectedItem) {
    dispatch({
      type: FunctionSelectItem$1,
      selectedItem: newSelectedItem
    });
  }, [dispatch]);
  var reset = useCallback(function () {
    dispatch({
      type: FunctionReset$2
    });
  }, [dispatch]);
  var setInputValue = useCallback(function (newInputValue) {
    dispatch({
      type: FunctionSetInputValue$1,
      inputValue: newInputValue
    });
  }, [dispatch]);
  // Getter functions.
  var getLabelProps = useCallback(function (_temp) {
    var _ref = _temp === void 0 ? {} : _temp,
      onClick = _ref.onClick,
      labelProps = _objectWithoutPropertiesLoose(_ref, _excluded$3);
    var labelHandleClick = function labelHandleClick() {
      var _toggleButtonRef$curr;
      (_toggleButtonRef$curr = toggleButtonRef.current) == null || _toggleButtonRef$curr.focus();
    };
    return _extends({
      id: elementIds.labelId,
      htmlFor: elementIds.toggleButtonId,
      onClick: callAllEventHandlers(onClick, labelHandleClick)
    }, labelProps);
  }, [elementIds]);
  var getMenuProps = useCallback(function (_temp2, _temp3) {
    var _extends2;
    var _ref2 = _temp2 === void 0 ? {} : _temp2,
      onMouseLeave = _ref2.onMouseLeave,
      _ref2$refKey = _ref2.refKey,
      refKey = _ref2$refKey === void 0 ? 'ref' : _ref2$refKey,
      ref = _ref2.ref,
      rest = _objectWithoutPropertiesLoose(_ref2, _excluded2$3);
    var _ref3 = _temp3 === void 0 ? {} : _temp3,
      _ref3$suppressRefErro = _ref3.suppressRefError,
      suppressRefError = _ref3$suppressRefErro === void 0 ? false : _ref3$suppressRefErro;
    var menuHandleMouseLeave = function menuHandleMouseLeave() {
      dispatch({
        type: MenuMouseLeave$1
      });
    };
    setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
    return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
      menuRef.current = menuNode;
    }), _extends2.id = elementIds.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = rest && rest['aria-label'] ? undefined : "" + elementIds.labelId, _extends2.onMouseLeave = callAllEventHandlers(onMouseLeave, menuHandleMouseLeave), _extends2), rest);
  }, [dispatch, setGetterPropCallInfo, elementIds]);
  var getToggleButtonProps = useCallback(function (_temp4, _temp5) {
    var _extends3;
    var _ref4 = _temp4 === void 0 ? {} : _temp4,
      onBlur = _ref4.onBlur,
      onClick = _ref4.onClick;
      _ref4.onPress;
      var onKeyDown = _ref4.onKeyDown,
      _ref4$refKey = _ref4.refKey,
      refKey = _ref4$refKey === void 0 ? 'ref' : _ref4$refKey,
      ref = _ref4.ref,
      rest = _objectWithoutPropertiesLoose(_ref4, _excluded3$2);
    var _ref5 = _temp5 === void 0 ? {} : _temp5,
      _ref5$suppressRefErro = _ref5.suppressRefError,
      suppressRefError = _ref5$suppressRefErro === void 0 ? false : _ref5$suppressRefErro;
    var latestState = latest.current.state;
    var toggleButtonHandleClick = function toggleButtonHandleClick() {
      dispatch({
        type: ToggleButtonClick$1
      });
    };
    var toggleButtonHandleBlur = function toggleButtonHandleBlur() {
      if (latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
        dispatch({
          type: ToggleButtonBlur
        });
      }
    };
    var toggleButtonHandleKeyDown = function toggleButtonHandleKeyDown(event) {
      var key = normalizeArrowKey(event);
      if (key && toggleButtonKeyDownHandlers[key]) {
        toggleButtonKeyDownHandlers[key](event);
      } else if (isAcceptedCharacterKey(key)) {
        dispatch({
          type: ToggleButtonKeyDownCharacter,
          key: key
        });
      }
    };
    var toggleProps = _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (toggleButtonNode) {
      toggleButtonRef.current = toggleButtonNode;
    }), _extends3['aria-activedescendant'] = latestState.isOpen && latestState.highlightedIndex > -1 ? elementIds.getItemId(latestState.highlightedIndex) : '', _extends3['aria-controls'] = elementIds.menuId, _extends3['aria-expanded'] = latest.current.state.isOpen, _extends3['aria-haspopup'] = 'listbox', _extends3['aria-labelledby'] = rest && rest['aria-label'] ? undefined : "" + elementIds.labelId, _extends3.id = elementIds.toggleButtonId, _extends3.role = 'combobox', _extends3.tabIndex = 0, _extends3.onBlur = callAllEventHandlers(onBlur, toggleButtonHandleBlur), _extends3), rest);
    if (!rest.disabled) {
      /* istanbul ignore if (react-native) */
      {
        toggleProps.onClick = callAllEventHandlers(onClick, toggleButtonHandleClick);
        toggleProps.onKeyDown = callAllEventHandlers(onKeyDown, toggleButtonHandleKeyDown);
      }
    }
    setGetterPropCallInfo('getToggleButtonProps', suppressRefError, refKey, toggleButtonRef);
    return toggleProps;
  }, [dispatch, elementIds, latest, mouseAndTouchTrackers, setGetterPropCallInfo, toggleButtonKeyDownHandlers]);
  var getItemProps = useCallback(function (_temp6) {
    var _extends4;
    var _ref6 = _temp6 === void 0 ? {} : _temp6,
      itemProp = _ref6.item,
      indexProp = _ref6.index,
      onMouseMove = _ref6.onMouseMove,
      onClick = _ref6.onClick,
      onMouseDown = _ref6.onMouseDown;
      _ref6.onPress;
      var _ref6$refKey = _ref6.refKey,
      refKey = _ref6$refKey === void 0 ? 'ref' : _ref6$refKey,
      disabledProp = _ref6.disabled,
      ref = _ref6.ref,
      rest = _objectWithoutPropertiesLoose(_ref6, _excluded4$1);
    if (disabledProp !== undefined) {
      console.warn('Passing "disabled" as an argument to getItemProps is not supported anymore. Please use the isItemDisabled prop from useSelect.');
    }
    var _latest$current = latest.current,
      latestState = _latest$current.state,
      latestProps = _latest$current.props;
    var _getItemAndIndex = getItemAndIndex(itemProp, indexProp, latestProps.items, 'Pass either item or index to getItemProps!'),
      item = _getItemAndIndex[0],
      index = _getItemAndIndex[1];
    var disabled = latestProps.isItemDisabled(item, index);
    var itemHandleMouseMove = function itemHandleMouseMove() {
      if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
        return;
      }
      shouldScrollRef.current = false;
      dispatch({
        type: ItemMouseMove$1,
        index: index,
        disabled: disabled
      });
    };
    var itemHandleClick = function itemHandleClick() {
      dispatch({
        type: ItemClick$1,
        index: index
      });
    };
    var itemHandleMouseDown = function itemHandleMouseDown(e) {
      return e.preventDefault();
    }; // keep focus on the toggle after item click select.

    var itemProps = _extends((_extends4 = {}, _extends4[refKey] = handleRefs(ref, function (itemNode) {
      if (itemNode) {
        itemRefs.current[elementIds.getItemId(index)] = itemNode;
      }
    }), _extends4['aria-disabled'] = disabled, _extends4['aria-selected'] = item === latestState.selectedItem, _extends4.id = elementIds.getItemId(index), _extends4.role = 'option', _extends4), rest);
    if (!disabled) {
      /* istanbul ignore next (react-native) */
      {
        itemProps.onClick = callAllEventHandlers(onClick, itemHandleClick);
      }
    }
    itemProps.onMouseMove = callAllEventHandlers(onMouseMove, itemHandleMouseMove);
    itemProps.onMouseDown = callAllEventHandlers(onMouseDown, itemHandleMouseDown);
    return itemProps;
  }, [latest, elementIds, mouseAndTouchTrackers, shouldScrollRef, dispatch]);
  return {
    // prop getters.
    getToggleButtonProps: getToggleButtonProps,
    getLabelProps: getLabelProps,
    getMenuProps: getMenuProps,
    getItemProps: getItemProps,
    // actions.
    toggleMenu: toggleMenu,
    openMenu: openMenu,
    closeMenu: closeMenu,
    setHighlightedIndex: setHighlightedIndex,
    selectItem: selectItem,
    reset: reset,
    setInputValue: setInputValue,
    // state.
    highlightedIndex: highlightedIndex,
    isOpen: isOpen,
    selectedItem: selectedItem,
    inputValue: inputValue
  };
}

var InputKeyDownArrowDown = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_down__' : 0;
var InputKeyDownArrowUp = process.env.NODE_ENV !== "production" ? '__input_keydown_arrow_up__' : 1;
var InputKeyDownEscape = process.env.NODE_ENV !== "production" ? '__input_keydown_escape__' : 2;
var InputKeyDownHome = process.env.NODE_ENV !== "production" ? '__input_keydown_home__' : 3;
var InputKeyDownEnd = process.env.NODE_ENV !== "production" ? '__input_keydown_end__' : 4;
var InputKeyDownPageUp = process.env.NODE_ENV !== "production" ? '__input_keydown_page_up__' : 5;
var InputKeyDownPageDown = process.env.NODE_ENV !== "production" ? '__input_keydown_page_down__' : 6;
var InputKeyDownEnter = process.env.NODE_ENV !== "production" ? '__input_keydown_enter__' : 7;
var InputChange = process.env.NODE_ENV !== "production" ? '__input_change__' : 8;
var InputBlur = process.env.NODE_ENV !== "production" ? '__input_blur__' : 9;
var InputClick = process.env.NODE_ENV !== "production" ? '__input_click__' : 10;
var MenuMouseLeave = process.env.NODE_ENV !== "production" ? '__menu_mouse_leave__' : 11;
var ItemMouseMove = process.env.NODE_ENV !== "production" ? '__item_mouse_move__' : 12;
var ItemClick = process.env.NODE_ENV !== "production" ? '__item_click__' : 13;
var ToggleButtonClick = process.env.NODE_ENV !== "production" ? '__togglebutton_click__' : 14;
var FunctionToggleMenu = process.env.NODE_ENV !== "production" ? '__function_toggle_menu__' : 15;
var FunctionOpenMenu = process.env.NODE_ENV !== "production" ? '__function_open_menu__' : 16;
var FunctionCloseMenu = process.env.NODE_ENV !== "production" ? '__function_close_menu__' : 17;
var FunctionSetHighlightedIndex = process.env.NODE_ENV !== "production" ? '__function_set_highlighted_index__' : 18;
var FunctionSelectItem = process.env.NODE_ENV !== "production" ? '__function_select_item__' : 19;
var FunctionSetInputValue = process.env.NODE_ENV !== "production" ? '__function_set_input_value__' : 20;
var FunctionReset$1 = process.env.NODE_ENV !== "production" ? '__function_reset__' : 21;
var ControlledPropUpdatedSelectedItem = process.env.NODE_ENV !== "production" ? '__controlled_prop_updated_selected_item__' : 22;

var stateChangeTypes$2 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  ControlledPropUpdatedSelectedItem: ControlledPropUpdatedSelectedItem,
  FunctionCloseMenu: FunctionCloseMenu,
  FunctionOpenMenu: FunctionOpenMenu,
  FunctionReset: FunctionReset$1,
  FunctionSelectItem: FunctionSelectItem,
  FunctionSetHighlightedIndex: FunctionSetHighlightedIndex,
  FunctionSetInputValue: FunctionSetInputValue,
  FunctionToggleMenu: FunctionToggleMenu,
  InputBlur: InputBlur,
  InputChange: InputChange,
  InputClick: InputClick,
  InputKeyDownArrowDown: InputKeyDownArrowDown,
  InputKeyDownArrowUp: InputKeyDownArrowUp,
  InputKeyDownEnd: InputKeyDownEnd,
  InputKeyDownEnter: InputKeyDownEnter,
  InputKeyDownEscape: InputKeyDownEscape,
  InputKeyDownHome: InputKeyDownHome,
  InputKeyDownPageDown: InputKeyDownPageDown,
  InputKeyDownPageUp: InputKeyDownPageUp,
  ItemClick: ItemClick,
  ItemMouseMove: ItemMouseMove,
  MenuMouseLeave: MenuMouseLeave,
  ToggleButtonClick: ToggleButtonClick
});

function getInitialState$2(props) {
  var initialState = getInitialState$3(props);
  var selectedItem = initialState.selectedItem;
  var inputValue = initialState.inputValue;
  if (inputValue === '' && selectedItem && props.defaultInputValue === undefined && props.initialInputValue === undefined && props.inputValue === undefined) {
    inputValue = props.itemToString(selectedItem);
  }
  return _extends({}, initialState, {
    inputValue: inputValue
  });
}
var propTypes$2 = _extends({}, propTypes$4, {
  items: PropTypes.array.isRequired,
  isItemDisabled: PropTypes.func,
  inputValue: PropTypes.string,
  defaultInputValue: PropTypes.string,
  initialInputValue: PropTypes.string,
  inputId: PropTypes.string,
  onInputValueChange: PropTypes.func
});

/**
 * The useCombobox version of useControlledReducer, which also
 * checks if the controlled prop selectedItem changed between
 * renders. If so, it will also update inputValue with its
 * string equivalent. It uses the common useEnhancedReducer to
 * compute the rest of the state.
 *
 * @param {Function} reducer Reducer function from downshift.
 * @param {Object} props The hook props, also passed to createInitialState.
 * @param {Function} createInitialState Function that returns the initial state.
 * @param {Function} isStateEqual Function that checks if a previous state is equal to the next.
 * @returns {Array} An array with the state and an action dispatcher.
 */
function useControlledReducer(reducer, props, createInitialState, isStateEqual) {
  var previousSelectedItemRef = useRef();
  var _useEnhancedReducer = useEnhancedReducer(reducer, props, createInitialState, isStateEqual),
    state = _useEnhancedReducer[0],
    dispatch = _useEnhancedReducer[1];
  var isInitialMount = useIsInitialMount();
  useEffect(function () {
    if (!isControlledProp(props, 'selectedItem')) {
      return;
    }
    if (!isInitialMount // on first mount we already have the proper inputValue for a initial selected item.
    ) {
      var shouldCallDispatch = props.itemToKey(props.selectedItem) !== props.itemToKey(previousSelectedItemRef.current);
      if (shouldCallDispatch) {
        dispatch({
          type: ControlledPropUpdatedSelectedItem,
          inputValue: props.itemToString(props.selectedItem)
        });
      }
    }
    previousSelectedItemRef.current = state.selectedItem === previousSelectedItemRef.current ? props.selectedItem : state.selectedItem;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.selectedItem, props.selectedItem]);
  return [getState(state, props), dispatch];
}
var defaultProps$1 = _extends({}, defaultProps$3, {
  isItemDisabled: function isItemDisabled() {
    return false;
  }
});

/* eslint-disable complexity */
function downshiftUseComboboxReducer(state, props, action) {
  var _props$items;
  var type = action.type,
    altKey = action.altKey;
  var changes;
  switch (type) {
    case ItemClick:
      changes = {
        isOpen: getDefaultValue$1(props, 'isOpen', defaultStateValues$1),
        highlightedIndex: getDefaultHighlightedIndex(props),
        selectedItem: props.items[action.index],
        inputValue: props.itemToString(props.items[action.index])
      };
      break;
    case InputKeyDownArrowDown:
      if (state.isOpen) {
        changes = {
          highlightedIndex: getHighlightedIndex(state.highlightedIndex, 1, props.items, props.isItemDisabled, true)
        };
      } else {
        changes = {
          highlightedIndex: altKey && state.selectedItem == null ? -1 : getHighlightedIndexOnOpen(props, state, 1),
          isOpen: props.items.length >= 0
        };
      }
      break;
    case InputKeyDownArrowUp:
      if (state.isOpen) {
        if (altKey) {
          changes = getChangesOnSelection(props, state.highlightedIndex);
        } else {
          changes = {
            highlightedIndex: getHighlightedIndex(state.highlightedIndex, -1, props.items, props.isItemDisabled, true)
          };
        }
      } else {
        changes = {
          highlightedIndex: getHighlightedIndexOnOpen(props, state, -1),
          isOpen: props.items.length >= 0
        };
      }
      break;
    case InputKeyDownEnter:
      changes = getChangesOnSelection(props, state.highlightedIndex);
      break;
    case InputKeyDownEscape:
      changes = _extends({
        isOpen: false,
        highlightedIndex: -1
      }, !state.isOpen && {
        selectedItem: null,
        inputValue: ''
      });
      break;
    case InputKeyDownPageUp:
      changes = {
        highlightedIndex: getHighlightedIndex(state.highlightedIndex, -10, props.items, props.isItemDisabled, true)
      };
      break;
    case InputKeyDownPageDown:
      changes = {
        highlightedIndex: getHighlightedIndex(state.highlightedIndex, 10, props.items, props.isItemDisabled, true)
      };
      break;
    case InputKeyDownHome:
      changes = {
        highlightedIndex: getNonDisabledIndex(0, false, props.items, props.isItemDisabled)
      };
      break;
    case InputKeyDownEnd:
      changes = {
        highlightedIndex: getNonDisabledIndex(props.items.length - 1, true, props.items, props.isItemDisabled)
      };
      break;
    case InputBlur:
      changes = _extends({
        isOpen: false,
        highlightedIndex: -1
      }, state.highlightedIndex >= 0 && ((_props$items = props.items) == null ? void 0 : _props$items.length) && action.selectItem && {
        selectedItem: props.items[state.highlightedIndex],
        inputValue: props.itemToString(props.items[state.highlightedIndex])
      });
      break;
    case InputChange:
      changes = {
        isOpen: true,
        highlightedIndex: getDefaultHighlightedIndex(props),
        inputValue: action.inputValue
      };
      break;
    case InputClick:
      changes = {
        isOpen: !state.isOpen,
        highlightedIndex: state.isOpen ? -1 : getHighlightedIndexOnOpen(props, state, 0)
      };
      break;
    case FunctionSelectItem:
      changes = {
        selectedItem: action.selectedItem,
        inputValue: props.itemToString(action.selectedItem)
      };
      break;
    case ControlledPropUpdatedSelectedItem:
      changes = {
        inputValue: action.inputValue
      };
      break;
    default:
      return downshiftCommonReducer(state, props, action, stateChangeTypes$2);
  }
  return _extends({}, state, changes);
}
/* eslint-enable complexity */

var _excluded$2 = ["onMouseLeave", "refKey", "ref"],
  _excluded2$2 = ["item", "index", "refKey", "ref", "onMouseMove", "onMouseDown", "onClick", "onPress", "disabled"],
  _excluded3$1 = ["onClick", "onPress", "refKey", "ref"],
  _excluded4 = ["onKeyDown", "onChange", "onInput", "onBlur", "onChangeText", "onClick", "refKey", "ref"];
useCombobox.stateChangeTypes = stateChangeTypes$2;
function useCombobox(userProps) {
  if (userProps === void 0) {
    userProps = {};
  }
  validatePropTypes$1(userProps, useCombobox, propTypes$2);
  // Props defaults and destructuring.
  var props = _extends({}, defaultProps$1, userProps);
  var items = props.items,
    scrollIntoView = props.scrollIntoView,
    environment = props.environment,
    getA11yStatusMessage = props.getA11yStatusMessage;
  // Initial state depending on controlled props.
  var _useControlledReducer = useControlledReducer(downshiftUseComboboxReducer, props, getInitialState$2, isDropdownsStateEqual),
    state = _useControlledReducer[0],
    dispatch = _useControlledReducer[1];
  var isOpen = state.isOpen,
    highlightedIndex = state.highlightedIndex,
    selectedItem = state.selectedItem,
    inputValue = state.inputValue;

  // Element refs.
  var menuRef = useRef(null);
  var itemRefs = useRef({});
  var inputRef = useRef(null);
  var toggleButtonRef = useRef(null);
  var isInitialMount = useIsInitialMount();

  // prevent id re-generation between renders.
  var elementIds = useElementIds$1(props);
  // used to keep track of how many items we had on previous cycle.
  var previousResultCountRef = useRef();
  // utility callback to get item element.
  var latest = useLatestRef({
    state: state,
    props: props
  });
  var getItemNodeFromIndex = useCallback(function (index) {
    return itemRefs.current[elementIds.getItemId(index)];
  }, [elementIds]);

  // Effects.
  // Adds an a11y aria live status message if getA11yStatusMessage is passed.
  useA11yMessageStatus(getA11yStatusMessage, state, [isOpen, highlightedIndex, selectedItem, inputValue], environment);
  // Scroll on highlighted item if change comes from keyboard.
  var shouldScrollRef = useScrollIntoView({
    menuElement: menuRef.current,
    highlightedIndex: highlightedIndex,
    isOpen: isOpen,
    itemRefs: itemRefs,
    scrollIntoView: scrollIntoView,
    getItemNodeFromIndex: getItemNodeFromIndex
  });
  useControlPropsValidator({
    props: props,
    state: state
  });
  // Focus the input on first render if required.
  useEffect(function () {
    var focusOnOpen = getInitialValue$1(props, 'isOpen', defaultStateValues$1);
    if (focusOnOpen && inputRef.current) {
      inputRef.current.focus();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  useEffect(function () {
    if (!isInitialMount) {
      previousResultCountRef.current = items.length;
    }
  });
  var handleBlurInTracker = useCallback(function handleBlur() {
    if (latest.current.state.isOpen) {
      dispatch({
        type: InputBlur
      });
    }
  }, [dispatch, latest]);
  var downshiftRefs = useMemo(function () {
    return [menuRef, toggleButtonRef, inputRef];
  }, []);
  var mouseAndTouchTrackers = useMouseAndTouchTracker(environment, handleBlurInTracker, downshiftRefs);
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getMenuProps');
  // Reset itemRefs on close.
  useEffect(function () {
    if (!isOpen) {
      itemRefs.current = {};
    }
  }, [isOpen]);
  // Reset itemRefs on close.
  useEffect(function () {
    var _inputRef$current;
    if (!isOpen || !(environment != null && environment.document) || !(inputRef != null && (_inputRef$current = inputRef.current) != null && _inputRef$current.focus)) {
      return;
    }
    if (environment.document.activeElement !== inputRef.current) {
      inputRef.current.focus();
    }
  }, [isOpen, environment]);

  /* Event handler functions */
  var inputKeyDownHandlers = useMemo(function () {
    return {
      ArrowDown: function ArrowDown(event) {
        event.preventDefault();
        dispatch({
          type: InputKeyDownArrowDown,
          altKey: event.altKey
        });
      },
      ArrowUp: function ArrowUp(event) {
        event.preventDefault();
        dispatch({
          type: InputKeyDownArrowUp,
          altKey: event.altKey
        });
      },
      Home: function Home(event) {
        if (!latest.current.state.isOpen) {
          return;
        }
        event.preventDefault();
        dispatch({
          type: InputKeyDownHome
        });
      },
      End: function End(event) {
        if (!latest.current.state.isOpen) {
          return;
        }
        event.preventDefault();
        dispatch({
          type: InputKeyDownEnd
        });
      },
      Escape: function Escape(event) {
        var latestState = latest.current.state;
        if (latestState.isOpen || latestState.inputValue || latestState.selectedItem || latestState.highlightedIndex > -1) {
          event.preventDefault();
          dispatch({
            type: InputKeyDownEscape
          });
        }
      },
      Enter: function Enter(event) {
        var latestState = latest.current.state;
        // if closed or no highlighted index, do nothing.
        if (!latestState.isOpen || event.which === 229 // if IME composing, wait for next Enter keydown event.
        ) {
          return;
        }
        event.preventDefault();
        dispatch({
          type: InputKeyDownEnter
        });
      },
      PageUp: function PageUp(event) {
        if (latest.current.state.isOpen) {
          event.preventDefault();
          dispatch({
            type: InputKeyDownPageUp
          });
        }
      },
      PageDown: function PageDown(event) {
        if (latest.current.state.isOpen) {
          event.preventDefault();
          dispatch({
            type: InputKeyDownPageDown
          });
        }
      }
    };
  }, [dispatch, latest]);

  // Getter props.
  var getLabelProps = useCallback(function (labelProps) {
    return _extends({
      id: elementIds.labelId,
      htmlFor: elementIds.inputId
    }, labelProps);
  }, [elementIds]);
  var getMenuProps = useCallback(function (_temp, _temp2) {
    var _extends2;
    var _ref = _temp === void 0 ? {} : _temp,
      onMouseLeave = _ref.onMouseLeave,
      _ref$refKey = _ref.refKey,
      refKey = _ref$refKey === void 0 ? 'ref' : _ref$refKey,
      ref = _ref.ref,
      rest = _objectWithoutPropertiesLoose(_ref, _excluded$2);
    var _ref2 = _temp2 === void 0 ? {} : _temp2,
      _ref2$suppressRefErro = _ref2.suppressRefError,
      suppressRefError = _ref2$suppressRefErro === void 0 ? false : _ref2$suppressRefErro;
    setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
    return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (menuNode) {
      menuRef.current = menuNode;
    }), _extends2.id = elementIds.menuId, _extends2.role = 'listbox', _extends2['aria-labelledby'] = rest && rest['aria-label'] ? undefined : "" + elementIds.labelId, _extends2.onMouseLeave = callAllEventHandlers(onMouseLeave, function () {
      dispatch({
        type: MenuMouseLeave
      });
    }), _extends2), rest);
  }, [dispatch, setGetterPropCallInfo, elementIds]);
  var getItemProps = useCallback(function (_temp3) {
    var _extends3, _ref4;
    var _ref3 = _temp3 === void 0 ? {} : _temp3,
      itemProp = _ref3.item,
      indexProp = _ref3.index,
      _ref3$refKey = _ref3.refKey,
      refKey = _ref3$refKey === void 0 ? 'ref' : _ref3$refKey,
      ref = _ref3.ref,
      onMouseMove = _ref3.onMouseMove,
      onMouseDown = _ref3.onMouseDown,
      onClick = _ref3.onClick;
      _ref3.onPress;
      var disabledProp = _ref3.disabled,
      rest = _objectWithoutPropertiesLoose(_ref3, _excluded2$2);
    if (disabledProp !== undefined) {
      console.warn('Passing "disabled" as an argument to getItemProps is not supported anymore. Please use the isItemDisabled prop from useCombobox.');
    }
    var _latest$current = latest.current,
      latestProps = _latest$current.props,
      latestState = _latest$current.state;
    var _getItemAndIndex = getItemAndIndex(itemProp, indexProp, latestProps.items, 'Pass either item or index to getItemProps!'),
      item = _getItemAndIndex[0],
      index = _getItemAndIndex[1];
    var disabled = latestProps.isItemDisabled(item, index);
    var onSelectKey = 'onClick';
    var customClickHandler = onClick;
    var itemHandleMouseMove = function itemHandleMouseMove() {
      if (mouseAndTouchTrackers.isTouchEnd || index === latestState.highlightedIndex) {
        return;
      }
      shouldScrollRef.current = false;
      dispatch({
        type: ItemMouseMove,
        index: index,
        disabled: disabled
      });
    };
    var itemHandleClick = function itemHandleClick() {
      dispatch({
        type: ItemClick,
        index: index
      });
    };
    var itemHandleMouseDown = function itemHandleMouseDown(e) {
      return e.preventDefault();
    }; // keep focus on the input after item click select.

    return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (itemNode) {
      if (itemNode) {
        itemRefs.current[elementIds.getItemId(index)] = itemNode;
      }
    }), _extends3['aria-disabled'] = disabled, _extends3['aria-selected'] = index === latestState.highlightedIndex, _extends3.id = elementIds.getItemId(index), _extends3.role = 'option', _extends3), !disabled && (_ref4 = {}, _ref4[onSelectKey] = callAllEventHandlers(customClickHandler, itemHandleClick), _ref4), {
      onMouseMove: callAllEventHandlers(onMouseMove, itemHandleMouseMove),
      onMouseDown: callAllEventHandlers(onMouseDown, itemHandleMouseDown)
    }, rest);
  }, [dispatch, elementIds, latest, mouseAndTouchTrackers, shouldScrollRef]);
  var getToggleButtonProps = useCallback(function (_temp4) {
    var _extends4;
    var _ref5 = _temp4 === void 0 ? {} : _temp4,
      onClick = _ref5.onClick;
      _ref5.onPress;
      var _ref5$refKey = _ref5.refKey,
      refKey = _ref5$refKey === void 0 ? 'ref' : _ref5$refKey,
      ref = _ref5.ref,
      rest = _objectWithoutPropertiesLoose(_ref5, _excluded3$1);
    var latestState = latest.current.state;
    var toggleButtonHandleClick = function toggleButtonHandleClick() {
      dispatch({
        type: ToggleButtonClick
      });
    };
    return _extends((_extends4 = {}, _extends4[refKey] = handleRefs(ref, function (toggleButtonNode) {
      toggleButtonRef.current = toggleButtonNode;
    }), _extends4['aria-controls'] = elementIds.menuId, _extends4['aria-expanded'] = latestState.isOpen, _extends4.id = elementIds.toggleButtonId, _extends4.tabIndex = -1, _extends4), !rest.disabled && _extends({}, {
      onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
    }), rest);
  }, [dispatch, latest, elementIds]);
  var getInputProps = useCallback(function (_temp5, _temp6) {
    var _extends5;
    var _ref6 = _temp5 === void 0 ? {} : _temp5,
      onKeyDown = _ref6.onKeyDown,
      onChange = _ref6.onChange,
      onInput = _ref6.onInput,
      onBlur = _ref6.onBlur;
      _ref6.onChangeText;
      var onClick = _ref6.onClick,
      _ref6$refKey = _ref6.refKey,
      refKey = _ref6$refKey === void 0 ? 'ref' : _ref6$refKey,
      ref = _ref6.ref,
      rest = _objectWithoutPropertiesLoose(_ref6, _excluded4);
    var _ref7 = _temp6 === void 0 ? {} : _temp6,
      _ref7$suppressRefErro = _ref7.suppressRefError,
      suppressRefError = _ref7$suppressRefErro === void 0 ? false : _ref7$suppressRefErro;
    setGetterPropCallInfo('getInputProps', suppressRefError, refKey, inputRef);
    var latestState = latest.current.state;
    var inputHandleKeyDown = function inputHandleKeyDown(event) {
      var key = normalizeArrowKey(event);
      if (key && inputKeyDownHandlers[key]) {
        inputKeyDownHandlers[key](event);
      }
    };
    var inputHandleChange = function inputHandleChange(event) {
      dispatch({
        type: InputChange,
        inputValue: event.target.value
      });
    };
    var inputHandleBlur = function inputHandleBlur(event) {
      /* istanbul ignore else */
      if (environment != null && environment.document && latestState.isOpen && !mouseAndTouchTrackers.isMouseDown) {
        var isBlurByTabChange = event.relatedTarget === null && environment.document.activeElement !== environment.document.body;
        dispatch({
          type: InputBlur,
          selectItem: !isBlurByTabChange
        });
      }
    };
    var inputHandleClick = function inputHandleClick() {
      dispatch({
        type: InputClick
      });
    };

    /* istanbul ignore next (preact) */
    var onChangeKey = 'onChange';
    var eventHandlers = {};
    if (!rest.disabled) {
      var _eventHandlers;
      eventHandlers = (_eventHandlers = {}, _eventHandlers[onChangeKey] = callAllEventHandlers(onChange, onInput, inputHandleChange), _eventHandlers.onKeyDown = callAllEventHandlers(onKeyDown, inputHandleKeyDown), _eventHandlers.onBlur = callAllEventHandlers(onBlur, inputHandleBlur), _eventHandlers.onClick = callAllEventHandlers(onClick, inputHandleClick), _eventHandlers);
    }
    return _extends((_extends5 = {}, _extends5[refKey] = handleRefs(ref, function (inputNode) {
      inputRef.current = inputNode;
    }), _extends5['aria-activedescendant'] = latestState.isOpen && latestState.highlightedIndex > -1 ? elementIds.getItemId(latestState.highlightedIndex) : '', _extends5['aria-autocomplete'] = 'list', _extends5['aria-controls'] = elementIds.menuId, _extends5['aria-expanded'] = latestState.isOpen, _extends5['aria-labelledby'] = rest && rest['aria-label'] ? undefined : elementIds.labelId, _extends5.autoComplete = 'off', _extends5.id = elementIds.inputId, _extends5.role = 'combobox', _extends5.value = latestState.inputValue, _extends5), eventHandlers, rest);
  }, [dispatch, elementIds, environment, inputKeyDownHandlers, latest, mouseAndTouchTrackers, setGetterPropCallInfo]);

  // returns
  var toggleMenu = useCallback(function () {
    dispatch({
      type: FunctionToggleMenu
    });
  }, [dispatch]);
  var closeMenu = useCallback(function () {
    dispatch({
      type: FunctionCloseMenu
    });
  }, [dispatch]);
  var openMenu = useCallback(function () {
    dispatch({
      type: FunctionOpenMenu
    });
  }, [dispatch]);
  var setHighlightedIndex = useCallback(function (newHighlightedIndex) {
    dispatch({
      type: FunctionSetHighlightedIndex,
      highlightedIndex: newHighlightedIndex
    });
  }, [dispatch]);
  var selectItem = useCallback(function (newSelectedItem) {
    dispatch({
      type: FunctionSelectItem,
      selectedItem: newSelectedItem
    });
  }, [dispatch]);
  var setInputValue = useCallback(function (newInputValue) {
    dispatch({
      type: FunctionSetInputValue,
      inputValue: newInputValue
    });
  }, [dispatch]);
  var reset = useCallback(function () {
    dispatch({
      type: FunctionReset$1
    });
  }, [dispatch]);
  return {
    // prop getters.
    getItemProps: getItemProps,
    getLabelProps: getLabelProps,
    getMenuProps: getMenuProps,
    getInputProps: getInputProps,
    getToggleButtonProps: getToggleButtonProps,
    // actions.
    toggleMenu: toggleMenu,
    openMenu: openMenu,
    closeMenu: closeMenu,
    setHighlightedIndex: setHighlightedIndex,
    setInputValue: setInputValue,
    selectItem: selectItem,
    reset: reset,
    // state.
    highlightedIndex: highlightedIndex,
    isOpen: isOpen,
    selectedItem: selectedItem,
    inputValue: inputValue
  };
}

var defaultStateValues = {
  activeIndex: -1,
  selectedItems: []
};

/**
 * Returns the initial value for a state key in the following order:
 * 1. controlled prop, 2. initial prop, 3. default prop, 4. default
 * value from Downshift.
 *
 * @param {Object} props Props passed to the hook.
 * @param {string} propKey Props key to generate the value for.
 * @returns {any} The initial value for that prop.
 */
function getInitialValue(props, propKey) {
  return getInitialValue$1(props, propKey, defaultStateValues);
}

/**
 * Returns the default value for a state key in the following order:
 * 1. controlled prop, 2. default prop, 3. default value from Downshift.
 *
 * @param {Object} props Props passed to the hook.
 * @param {string} propKey Props key to generate the value for.
 * @returns {any} The initial value for that prop.
 */
function getDefaultValue(props, propKey) {
  return getDefaultValue$1(props, propKey, defaultStateValues);
}

/**
 * Gets the initial state based on the provided props. It uses initial, default
 * and controlled props related to state in order to compute the initial value.
 *
 * @param {Object} props Props passed to the hook.
 * @returns {Object} The initial state.
 */
function getInitialState$1(props) {
  var activeIndex = getInitialValue(props, 'activeIndex');
  var selectedItems = getInitialValue(props, 'selectedItems');
  return {
    activeIndex: activeIndex,
    selectedItems: selectedItems
  };
}

/**
 * Returns true if dropdown keydown operation is permitted. Should not be
 * allowed on keydown with modifier keys (ctrl, alt, shift, meta), on
 * input element with text content that is either highlighted or selection
 * cursor is not at the starting position.
 *
 * @param {KeyboardEvent} event The event from keydown.
 * @returns {boolean} Whether the operation is allowed.
 */
function isKeyDownOperationPermitted(event) {
  if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey) {
    return false;
  }
  var element = event.target;
  if (element instanceof HTMLInputElement &&
  // if element is a text input
  element.value !== '' && (
  // and we have text in it
  // and cursor is either not at the start or is currently highlighting text.
  element.selectionStart !== 0 || element.selectionEnd !== 0)) {
    return false;
  }
  return true;
}

/**
 * Check if a state is equal for taglist, by comparing active index and selected items.
 * Used by useSelect and useCombobox.
 *
 * @param {Object} prevState
 * @param {Object} newState
 * @returns {boolean} Wheather the states are deeply equal.
 */
function isStateEqual$1(prevState, newState) {
  return prevState.selectedItems === newState.selectedItems && prevState.activeIndex === newState.activeIndex;
}
var propTypes$1 = {
  stateReducer: propTypes$4.stateReducer,
  itemToKey: propTypes$4.itemToKey,
  environment: propTypes$4.environment,
  selectedItems: PropTypes.array,
  initialSelectedItems: PropTypes.array,
  defaultSelectedItems: PropTypes.array,
  getA11yStatusMessage: PropTypes.func,
  activeIndex: PropTypes.number,
  initialActiveIndex: PropTypes.number,
  defaultActiveIndex: PropTypes.number,
  onActiveIndexChange: PropTypes.func,
  onSelectedItemsChange: PropTypes.func,
  keyNavigationNext: PropTypes.string,
  keyNavigationPrevious: PropTypes.string
};
var defaultProps = {
  itemToKey: defaultProps$3.itemToKey,
  stateReducer: defaultProps$3.stateReducer,
  environment: defaultProps$3.environment,
  keyNavigationNext: 'ArrowRight',
  keyNavigationPrevious: 'ArrowLeft'
};

// eslint-disable-next-line import/no-mutable-exports
var validatePropTypes = noop;
/* istanbul ignore next */
if (process.env.NODE_ENV !== 'production') {
  validatePropTypes = function validatePropTypes(options, caller) {
    PropTypes.checkPropTypes(propTypes$1, options, 'prop', caller.name);
  };
}

var SelectedItemClick = process.env.NODE_ENV !== "production" ? '__selected_item_click__' : 0;
var SelectedItemKeyDownDelete = process.env.NODE_ENV !== "production" ? '__selected_item_keydown_delete__' : 1;
var SelectedItemKeyDownBackspace = process.env.NODE_ENV !== "production" ? '__selected_item_keydown_backspace__' : 2;
var SelectedItemKeyDownNavigationNext = process.env.NODE_ENV !== "production" ? '__selected_item_keydown_navigation_next__' : 3;
var SelectedItemKeyDownNavigationPrevious = process.env.NODE_ENV !== "production" ? '__selected_item_keydown_navigation_previous__' : 4;
var DropdownKeyDownNavigationPrevious = process.env.NODE_ENV !== "production" ? '__dropdown_keydown_navigation_previous__' : 5;
var DropdownKeyDownBackspace = process.env.NODE_ENV !== "production" ? '__dropdown_keydown_backspace__' : 6;
var DropdownClick = process.env.NODE_ENV !== "production" ? '__dropdown_click__' : 7;
var FunctionAddSelectedItem = process.env.NODE_ENV !== "production" ? '__function_add_selected_item__' : 8;
var FunctionRemoveSelectedItem = process.env.NODE_ENV !== "production" ? '__function_remove_selected_item__' : 9;
var FunctionSetSelectedItems = process.env.NODE_ENV !== "production" ? '__function_set_selected_items__' : 10;
var FunctionSetActiveIndex = process.env.NODE_ENV !== "production" ? '__function_set_active_index__' : 11;
var FunctionReset = process.env.NODE_ENV !== "production" ? '__function_reset__' : 12;

var stateChangeTypes$1 = /*#__PURE__*/Object.freeze({
  __proto__: null,
  DropdownClick: DropdownClick,
  DropdownKeyDownBackspace: DropdownKeyDownBackspace,
  DropdownKeyDownNavigationPrevious: DropdownKeyDownNavigationPrevious,
  FunctionAddSelectedItem: FunctionAddSelectedItem,
  FunctionRemoveSelectedItem: FunctionRemoveSelectedItem,
  FunctionReset: FunctionReset,
  FunctionSetActiveIndex: FunctionSetActiveIndex,
  FunctionSetSelectedItems: FunctionSetSelectedItems,
  SelectedItemClick: SelectedItemClick,
  SelectedItemKeyDownBackspace: SelectedItemKeyDownBackspace,
  SelectedItemKeyDownDelete: SelectedItemKeyDownDelete,
  SelectedItemKeyDownNavigationNext: SelectedItemKeyDownNavigationNext,
  SelectedItemKeyDownNavigationPrevious: SelectedItemKeyDownNavigationPrevious
});

/* eslint-disable complexity */
function downshiftMultipleSelectionReducer(state, props, action) {
  var type = action.type,
    index = action.index,
    selectedItem = action.selectedItem;
  var activeIndex = state.activeIndex,
    selectedItems = state.selectedItems;
  var changes;
  switch (type) {
    case SelectedItemClick:
      changes = {
        activeIndex: index
      };
      break;
    case SelectedItemKeyDownNavigationPrevious:
      changes = {
        activeIndex: activeIndex - 1 < 0 ? 0 : activeIndex - 1
      };
      break;
    case SelectedItemKeyDownNavigationNext:
      changes = {
        activeIndex: activeIndex + 1 >= selectedItems.length ? -1 : activeIndex + 1
      };
      break;
    case SelectedItemKeyDownBackspace:
    case SelectedItemKeyDownDelete:
      {
        if (activeIndex < 0) {
          break;
        }
        var newActiveIndex = activeIndex;
        if (selectedItems.length === 1) {
          newActiveIndex = -1;
        } else if (activeIndex === selectedItems.length - 1) {
          newActiveIndex = selectedItems.length - 2;
        }
        changes = _extends({
          selectedItems: [].concat(selectedItems.slice(0, activeIndex), selectedItems.slice(activeIndex + 1))
        }, {
          activeIndex: newActiveIndex
        });
        break;
      }
    case DropdownKeyDownNavigationPrevious:
      changes = {
        activeIndex: selectedItems.length - 1
      };
      break;
    case DropdownKeyDownBackspace:
      changes = {
        selectedItems: selectedItems.slice(0, selectedItems.length - 1)
      };
      break;
    case FunctionAddSelectedItem:
      changes = {
        selectedItems: [].concat(selectedItems, [selectedItem])
      };
      break;
    case DropdownClick:
      changes = {
        activeIndex: -1
      };
      break;
    case FunctionRemoveSelectedItem:
      {
        var _newActiveIndex = activeIndex;
        var selectedItemIndex = selectedItems.findIndex(function (item) {
          return props.itemToKey(item) === props.itemToKey(selectedItem);
        });
        if (selectedItemIndex < 0) {
          break;
        }
        if (selectedItems.length === 1) {
          _newActiveIndex = -1;
        } else if (selectedItemIndex === selectedItems.length - 1) {
          _newActiveIndex = selectedItems.length - 2;
        }
        changes = {
          selectedItems: [].concat(selectedItems.slice(0, selectedItemIndex), selectedItems.slice(selectedItemIndex + 1)),
          activeIndex: _newActiveIndex
        };
        break;
      }
    case FunctionSetSelectedItems:
      {
        var newSelectedItems = action.selectedItems;
        changes = {
          selectedItems: newSelectedItems
        };
        break;
      }
    case FunctionSetActiveIndex:
      {
        var _newActiveIndex2 = action.activeIndex;
        changes = {
          activeIndex: _newActiveIndex2
        };
        break;
      }
    case FunctionReset:
      changes = {
        activeIndex: getDefaultValue(props, 'activeIndex'),
        selectedItems: getDefaultValue(props, 'selectedItems')
      };
      break;
    default:
      throw new Error('Reducer called without proper action type.');
  }
  return _extends({}, state, changes);
}

var _excluded$1 = ["refKey", "ref", "onClick", "onKeyDown", "selectedItem", "index"],
  _excluded2$1 = ["refKey", "ref", "onKeyDown", "onClick", "preventKeyAction"];
useMultipleSelection.stateChangeTypes = stateChangeTypes$1;
function useMultipleSelection(userProps) {
  if (userProps === void 0) {
    userProps = {};
  }
  validatePropTypes(userProps, useMultipleSelection);
  // Props defaults and destructuring.
  var props = _extends({}, defaultProps, userProps);
  var getA11yStatusMessage = props.getA11yStatusMessage,
    environment = props.environment,
    keyNavigationNext = props.keyNavigationNext,
    keyNavigationPrevious = props.keyNavigationPrevious;

  // Reducer init.
  var _useControlledReducer = useControlledReducer$1(downshiftMultipleSelectionReducer, props, getInitialState$1, isStateEqual$1),
    state = _useControlledReducer[0],
    dispatch = _useControlledReducer[1];
  var activeIndex = state.activeIndex,
    selectedItems = state.selectedItems;

  // Refs.
  var isInitialMount = useIsInitialMount();
  var dropdownRef = useRef(null);
  var selectedItemRefs = useRef();
  selectedItemRefs.current = [];
  var latest = useLatestRef({
    state: state,
    props: props
  });

  // Effects.
  // Adds an a11y aria live status message if getA11yStatusMessage is passed.
  useA11yMessageStatus(getA11yStatusMessage, state, [activeIndex, selectedItems], environment);
  // Sets focus on active item.
  useEffect(function () {
    if (isInitialMount) {
      return;
    }
    if (activeIndex === -1 && dropdownRef.current) {
      dropdownRef.current.focus();
    } else if (selectedItemRefs.current[activeIndex]) {
      selectedItemRefs.current[activeIndex].focus();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeIndex]);
  useControlPropsValidator({
    props: props,
    state: state
  });
  var setGetterPropCallInfo = useGetterPropsCalledChecker('getDropdownProps');

  // Event handler functions.
  var selectedItemKeyDownHandlers = useMemo(function () {
    var _ref;
    return _ref = {}, _ref[keyNavigationPrevious] = function () {
      dispatch({
        type: SelectedItemKeyDownNavigationPrevious
      });
    }, _ref[keyNavigationNext] = function () {
      dispatch({
        type: SelectedItemKeyDownNavigationNext
      });
    }, _ref.Delete = function Delete() {
      dispatch({
        type: SelectedItemKeyDownDelete
      });
    }, _ref.Backspace = function Backspace() {
      dispatch({
        type: SelectedItemKeyDownBackspace
      });
    }, _ref;
  }, [dispatch, keyNavigationNext, keyNavigationPrevious]);
  var dropdownKeyDownHandlers = useMemo(function () {
    var _ref2;
    return _ref2 = {}, _ref2[keyNavigationPrevious] = function (event) {
      if (isKeyDownOperationPermitted(event)) {
        dispatch({
          type: DropdownKeyDownNavigationPrevious
        });
      }
    }, _ref2.Backspace = function Backspace(event) {
      if (isKeyDownOperationPermitted(event)) {
        dispatch({
          type: DropdownKeyDownBackspace
        });
      }
    }, _ref2;
  }, [dispatch, keyNavigationPrevious]);

  // Getter props.
  var getSelectedItemProps = useCallback(function (_temp) {
    var _extends2;
    var _ref3 = _temp === void 0 ? {} : _temp,
      _ref3$refKey = _ref3.refKey,
      refKey = _ref3$refKey === void 0 ? 'ref' : _ref3$refKey,
      ref = _ref3.ref,
      onClick = _ref3.onClick,
      onKeyDown = _ref3.onKeyDown,
      selectedItemProp = _ref3.selectedItem,
      indexProp = _ref3.index,
      rest = _objectWithoutPropertiesLoose(_ref3, _excluded$1);
    var latestState = latest.current.state;
    var _getItemAndIndex = getItemAndIndex(selectedItemProp, indexProp, latestState.selectedItems, 'Pass either item or index to getSelectedItemProps!'),
      index = _getItemAndIndex[1];
    var isFocusable = index > -1 && index === latestState.activeIndex;
    var selectedItemHandleClick = function selectedItemHandleClick() {
      dispatch({
        type: SelectedItemClick,
        index: index
      });
    };
    var selectedItemHandleKeyDown = function selectedItemHandleKeyDown(event) {
      var key = normalizeArrowKey(event);
      if (key && selectedItemKeyDownHandlers[key]) {
        selectedItemKeyDownHandlers[key](event);
      }
    };
    return _extends((_extends2 = {}, _extends2[refKey] = handleRefs(ref, function (selectedItemNode) {
      if (selectedItemNode) {
        selectedItemRefs.current.push(selectedItemNode);
      }
    }), _extends2.tabIndex = isFocusable ? 0 : -1, _extends2.onClick = callAllEventHandlers(onClick, selectedItemHandleClick), _extends2.onKeyDown = callAllEventHandlers(onKeyDown, selectedItemHandleKeyDown), _extends2), rest);
  }, [dispatch, latest, selectedItemKeyDownHandlers]);
  var getDropdownProps = useCallback(function (_temp2, _temp3) {
    var _extends3;
    var _ref4 = _temp2 === void 0 ? {} : _temp2,
      _ref4$refKey = _ref4.refKey,
      refKey = _ref4$refKey === void 0 ? 'ref' : _ref4$refKey,
      ref = _ref4.ref,
      onKeyDown = _ref4.onKeyDown,
      onClick = _ref4.onClick,
      _ref4$preventKeyActio = _ref4.preventKeyAction,
      preventKeyAction = _ref4$preventKeyActio === void 0 ? false : _ref4$preventKeyActio,
      rest = _objectWithoutPropertiesLoose(_ref4, _excluded2$1);
    var _ref5 = _temp3 === void 0 ? {} : _temp3,
      _ref5$suppressRefErro = _ref5.suppressRefError,
      suppressRefError = _ref5$suppressRefErro === void 0 ? false : _ref5$suppressRefErro;
    setGetterPropCallInfo('getDropdownProps', suppressRefError, refKey, dropdownRef);
    var dropdownHandleKeyDown = function dropdownHandleKeyDown(event) {
      var key = normalizeArrowKey(event);
      if (key && dropdownKeyDownHandlers[key]) {
        dropdownKeyDownHandlers[key](event);
      }
    };
    var dropdownHandleClick = function dropdownHandleClick() {
      dispatch({
        type: DropdownClick
      });
    };
    return _extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, function (dropdownNode) {
      if (dropdownNode) {
        dropdownRef.current = dropdownNode;
      }
    }), _extends3), !preventKeyAction && {
      onKeyDown: callAllEventHandlers(onKeyDown, dropdownHandleKeyDown),
      onClick: callAllEventHandlers(onClick, dropdownHandleClick)
    }, rest);
  }, [dispatch, dropdownKeyDownHandlers, setGetterPropCallInfo]);

  // returns
  var addSelectedItem = useCallback(function (selectedItem) {
    dispatch({
      type: FunctionAddSelectedItem,
      selectedItem: selectedItem
    });
  }, [dispatch]);
  var removeSelectedItem = useCallback(function (selectedItem) {
    dispatch({
      type: FunctionRemoveSelectedItem,
      selectedItem: selectedItem
    });
  }, [dispatch]);
  var setSelectedItems = useCallback(function (newSelectedItems) {
    dispatch({
      type: FunctionSetSelectedItems,
      selectedItems: newSelectedItems
    });
  }, [dispatch]);
  var setActiveIndex = useCallback(function (newActiveIndex) {
    dispatch({
      type: FunctionSetActiveIndex,
      activeIndex: newActiveIndex
    });
  }, [dispatch]);
  var reset = useCallback(function () {
    dispatch({
      type: FunctionReset
    });
  }, [dispatch]);
  return {
    getSelectedItemProps: getSelectedItemProps,
    getDropdownProps: getDropdownProps,
    addSelectedItem: addSelectedItem,
    removeSelectedItem: removeSelectedItem,
    setSelectedItems: setSelectedItems,
    setActiveIndex: setActiveIndex,
    reset: reset,
    selectedItems: selectedItems,
    activeIndex: activeIndex
  };
}

var TagClick = process.env.NODE_ENV !== "production" ? '__tag_click__' : 0;
var TagGroupKeyDownArrowLeft = process.env.NODE_ENV !== "production" ? '__taggroup_keydown_arrowleft__' : 1;
var TagGroupKeyDownArrowRight = process.env.NODE_ENV !== "production" ? '__taggroup_keydown_arrowright__' : 2;
var TagGroupKeyDownDelete = process.env.NODE_ENV !== "production" ? '__taggroup_keydown_delete__' : 3;
var TagGroupKeyDownBackspace = process.env.NODE_ENV !== "production" ? '__taggroup_keydown_backspace__' : 4;
var TagRemoveClick = process.env.NODE_ENV !== "production" ? '__tagremove_click__' : 5;
var FunctionAddItem = process.env.NODE_ENV !== "production" ? '__function_add_item__' : 6;

var stateChangeTypes = /*#__PURE__*/Object.freeze({
  __proto__: null,
  FunctionAddItem: FunctionAddItem,
  TagClick: TagClick,
  TagGroupKeyDownArrowLeft: TagGroupKeyDownArrowLeft,
  TagGroupKeyDownArrowRight: TagGroupKeyDownArrowRight,
  TagGroupKeyDownBackspace: TagGroupKeyDownBackspace,
  TagGroupKeyDownDelete: TagGroupKeyDownDelete,
  TagRemoveClick: TagRemoveClick
});

function useTagGroupReducer(state, _props, action) {
  var type = action.type;
  var changes;
  switch (type) {
    case TagClick:
      changes = {
        activeIndex: action.index
      };
      break;
    case TagGroupKeyDownArrowLeft:
      changes = {
        activeIndex: state.activeIndex === 0 ? state.items.length - 1 : state.activeIndex - 1
      };
      break;
    case TagGroupKeyDownArrowRight:
      changes = {
        activeIndex: state.activeIndex === state.items.length - 1 ? 0 : state.activeIndex + 1
      };
      break;
    case TagGroupKeyDownBackspace:
    case TagGroupKeyDownDelete:
      {
        var newItems = [].concat(state.items.slice(0, state.activeIndex), state.items.slice(state.activeIndex + 1));
        var newActiveIndex = newItems.length === 0 ? -1 : newItems.length === state.activeIndex ? state.activeIndex - 1 : state.activeIndex;
        changes = {
          items: [].concat(state.items.slice(0, state.activeIndex), state.items.slice(state.activeIndex + 1)),
          activeIndex: newActiveIndex
        };
        break;
      }
    case TagRemoveClick:
      {
        var _newItems = [].concat(state.items.slice(0, action.index), state.items.slice(action.index + 1));
        var _newActiveIndex = _newItems.length === 0 ? -1 : _newItems.length === action.index ? action.index - 1 : action.index;
        changes = {
          items: _newItems,
          activeIndex: _newActiveIndex
        };
      }
      break;
    case FunctionAddItem:
      {
        var _newItems2 = [];
        if (action.index === undefined) {
          _newItems2 = [].concat(state.items, [action.item]);
        } else {
          _newItems2 = [].concat(state.items.slice(0, action.index), [action.item], state.items.slice(action.index));
        }
        var _newActiveIndex2 = state.activeIndex === -1 ? _newItems2.length - 1 : state.activeIndex;
        changes = {
          items: _newItems2,
          activeIndex: _newActiveIndex2
        };
        break;
      }
    default:
      throw new Error('Invalid useTagGroup reducer action.');
  }
  return _extends({}, state, changes);
}

// https://github.com/downshift-js/downshift/issues/1674#issuecomment-3924320872
var SafeReact = _extends({}, React);
var reactUseId = SafeReact.useId;

// istanbul ignore next
var useElementIds = typeof reactUseId === 'function' ? useElementIdsR18 : useElementIdsLegacy;
function useElementIdsR18(_ref) {
  var id = _ref.id,
    tagGroupId = _ref.tagGroupId,
    getTagId = _ref.getTagId;
  var reactId = "downshift-" + reactUseId();
  if (!id) {
    id = reactId;
  }
  var elementIds = React.useMemo(function () {
    return {
      tagGroupId: tagGroupId != null ? tagGroupId : id + "-tag-group",
      getTagId: getTagId != null ? getTagId : function (index) {
        return id + "-tag-" + index;
      }
    };
  }, [getTagId, id, tagGroupId]);
  return elementIds;
}
function useElementIdsLegacy(_ref2) {
  var id = _ref2.id,
    getTagId = _ref2.getTagId,
    tagGroupId = _ref2.tagGroupId;
  var baseIdRef = React.useRef(id != null ? id : "downshift-" + generateId());
  var baseId = baseIdRef.current;
  var elementIds = React.useMemo(function () {
    return {
      tagGroupId: tagGroupId != null ? tagGroupId : baseId + "-tag-group",
      getTagId: getTagId != null ? getTagId : function (index) {
        return baseId + "-tag-" + index;
      }
    };
  }, [getTagId, baseId, tagGroupId]);
  return elementIds;
}

function getInitialState(props) {
  var _ref, _props$items, _ref2, _props$activeIndex;
  var items = (_ref = (_props$items = props.items) != null ? _props$items : props.initialItems) != null ? _ref : [];
  var activeIndex = (_ref2 = (_props$activeIndex = props.activeIndex) != null ? _props$activeIndex : props.initialActiveIndex) != null ? _ref2 : items.length === 0 ? -1 : 0;
  return {
    activeIndex: activeIndex,
    items: items
  };
}

function isStateEqual(oldState, newState) {
  return oldState.activeIndex === newState.activeIndex && oldState.items === newState.items;
}

var A11Y_DESCRIPTION_ELEMENT_ID = 'tag-group-a11y-description';
function useAccessibleDescription(document, description) {
  React.useEffect(function () {
    if (!document) {
      return;
    }
    var accessibleDescriptionElement = document.createElement('div');
    accessibleDescriptionElement.setAttribute('id', A11Y_DESCRIPTION_ELEMENT_ID);
    accessibleDescriptionElement.style.display = 'none';
    accessibleDescriptionElement.textContent = description;
    document.body.appendChild(accessibleDescriptionElement);
    return function () {
      accessibleDescriptionElement.remove();
    };
  }, [description, document]);
}

function getMergedProps(userProps) {
  return _extends({
    stateReducer: function stateReducer(_s, _ref) {
      var changes = _ref.changes;
      return changes;
    },
    environment: /* istanbul ignore next (ssr) */
    typeof window === 'undefined' || false ? undefined : window,
    removeElementDescription: 'Press Delete or Backspace to remove tag.'
  }, userProps);
}

/**
 * Focuses the tag at activeIndex when it changes or when an item is removed.
 */
function useRovingTagFocus(activeIndex, itemsLength, getTagId) {
  var itemRefs = React.useRef({});
  var previousActiveIndexRef = React.useRef(activeIndex);
  var previousItemsLengthRef = React.useRef(itemsLength);
  React.useEffect(function () {
    if (activeIndex !== -1 && previousActiveIndexRef.current !== -1 && activeIndex !== previousActiveIndexRef.current || previousItemsLengthRef.current === itemsLength + 1) {
      var _itemRefs$current$get;
      (_itemRefs$current$get = itemRefs.current[getTagId(activeIndex)]) == null || _itemRefs$current$get.focus();
    }
    previousActiveIndexRef.current = activeIndex;
    previousItemsLengthRef.current = itemsLength;
  }, [activeIndex, getTagId, itemsLength]);
  return itemRefs;
}

var propTypes = {
  isItemDisabled: PropTypes.func
};

var _excluded = ["onKeyDown"],
  _excluded2 = ["index", "refKey", "ref", "onClick"],
  _excluded3 = ["index", "onClick"];
var _useTagGroup = function useTagGroup(userProps) {
  var _props$environment;
  if (userProps === void 0) {
    userProps = {};
  }
  /* State and Props */

  validatePropTypes$1(userProps, _useTagGroup, propTypes);
  var props = getMergedProps(userProps);
  var _useControlledReducer = useControlledReducer$1(useTagGroupReducer, props, getInitialState, isStateEqual),
    state = _useControlledReducer[0],
    dispatch = _useControlledReducer[1];
  var activeIndex = state.activeIndex,
    items = state.items;

  /* Refs */

  var latest = useLatestRef({
    state: state,
    props: props
  });
  var elementIds = useElementIds({
    getTagId: props.getTagId,
    id: props.id,
    tagGroupId: props.tagGroupId
  });

  /* Effects */

  useAccessibleDescription((_props$environment = props.environment) == null ? void 0 : _props$environment.document, props.removeElementDescription);
  var itemRefs = useRovingTagFocus(activeIndex, items.length, elementIds.getTagId);

  /* Getter functions */

  var getTagGroupProps = useCallback(function (options) {
    var _ref = options != null ? options : {},
      onKeyDown = _ref.onKeyDown,
      rest = _objectWithoutPropertiesLoose(_ref, _excluded);
    var handleKeyDown = function handleKeyDown(e) {
      switch (e.key) {
        case 'ArrowLeft':
          dispatch({
            type: TagGroupKeyDownArrowLeft
          });
          break;
        case 'ArrowRight':
          dispatch({
            type: TagGroupKeyDownArrowRight
          });
          break;
        case 'Delete':
          dispatch({
            type: TagGroupKeyDownDelete
          });
          break;
        case 'Backspace':
          dispatch({
            type: TagGroupKeyDownBackspace
          });
          break;
      }
    };
    var tagGroupProps = _extends({
      id: elementIds.tagGroupId,
      'aria-live': 'polite',
      'aria-atomic': 'false',
      'aria-relevant': 'additions',
      role: 'listbox',
      onKeyDown: callAllEventHandlers$1(onKeyDown, handleKeyDown)
    }, rest);
    return tagGroupProps;
  }, [dispatch, elementIds.tagGroupId]);
  var getTagProps = useCallback(function (options) {
    var _extends2;
    var index = options.index,
      _options$refKey = options.refKey,
      refKey = _options$refKey === void 0 ? 'ref' : _options$refKey,
      ref = options.ref,
      onClick = options.onClick,
      rest = _objectWithoutPropertiesLoose(options, _excluded2);
    if (!Number.isInteger(index) || index < 0) {
      throw new Error('Pass correct item index to getTagProps!');
    }
    var latestState = latest.current.state;
    var handleClick = function handleClick() {
      dispatch({
        type: TagClick,
        index: index
      });
    };
    var tagId = elementIds.getTagId(index);
    return _extends((_extends2 = {
      'aria-describedby': A11Y_DESCRIPTION_ELEMENT_ID
    }, _extends2[refKey] = handleRefs$1(ref, function (itemNode) {
      if (itemNode) {
        itemRefs.current[tagId] = itemNode;
      }
    }), _extends2['aria-labelledby'] = tagId, _extends2.role = 'option', _extends2.id = tagId, _extends2.onClick = callAllEventHandlers$1(onClick, handleClick), _extends2.tabIndex = latestState.activeIndex === index ? 0 : -1, _extends2), rest);
  }, [dispatch, elementIds, latest, itemRefs]);
  var getTagRemoveProps = useCallback(function (options) {
    var index = options.index,
      onClick = options.onClick,
      rest = _objectWithoutPropertiesLoose(options, _excluded3);
    if (!Number.isInteger(index) || index < 0) {
      throw new Error('Pass correct item index to getTagRemoveProps!');
    }
    var handleClick = function handleClick(event) {
      event.stopPropagation();
      dispatch({
        type: TagRemoveClick,
        index: index
      });
    };
    var tagId = elementIds.getTagId(index);
    var tagRemoveId = tagId + "-remove";
    return _extends({
      id: tagRemoveId,
      tabIndex: -1,
      'aria-labelledby': tagRemoveId + " " + tagId,
      onClick: callAllEventHandlers$1(onClick, handleClick)
    }, rest);
  }, [elementIds, dispatch]);

  /* Imperative Functions */

  var addItem = useCallback(function (item, index) {
    dispatch({
      type: FunctionAddItem,
      item: item,
      index: index
    });
  }, [dispatch]);
  return {
    activeIndex: activeIndex,
    addItem: addItem,
    getTagGroupProps: getTagGroupProps,
    getTagProps: getTagProps,
    getTagRemoveProps: getTagRemoveProps,
    items: items
  };
};
_useTagGroup.stateChangeTypes = stateChangeTypes;

export { Downshift as default, resetIdCounter, useCombobox, useMultipleSelection, useSelect, _useTagGroup as useTagGroup };
