} // get next non-disabled starting upwards from last index if that's disabled.
var newHighlightedIndex = getNextNonDisabledIndex(-1, itemCount - 1, itemCount, function (index) {
return _this5.getItemNodeFromIndex(index);
this.setHighlightedIndex(newHighlightedIndex, {
_this.getToggleButtonProps = function (_temp3) {
var _ref3 = _temp3 === void 0 ? {} : _temp3,
var onKeyDown = _ref3.onKeyDown,
rest = objectWithoutPropertiesLoose_objectWithoutPropertiesLoose(_ref3, _excluded2$3);
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;
'aria-label': isOpen ? 'close menu' : 'open menu',
_this.buttonHandleKeyUp = function (event) {
// Prevent click event from emitting in Firefox
_this.buttonHandleKeyDown = function (event) {
var key = normalizeArrowKey(event);
if (_this.buttonKeyDownHandlers[key]) {
_this.buttonKeyDownHandlers[key].call(assertThisInitialized_assertThisInitialized(_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.document.activeElement === _this.props.environment.document.body) {
} // 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.
// Ensure that toggle of menu occurs after the potential blur event in iOS
_this.internalSetTimeout(function () {
return _this.toggleMenu({
_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.document.activeElement == null || _this.props.environment.document.activeElement.id !== _this.inputId) && _this.props.environment.document.activeElement !== blurTarget // Do nothing if we refocus the same element again (to solve issue in Safari on iOS)
_this.getLabelProps = function (props) {
_this.getInputProps = function (_temp4) {
var _ref4 = _temp4 === void 0 ? {} : _temp4,
onKeyDown = _ref4.onKeyDown,
onChange = _ref4.onChange,
var rest = objectWithoutPropertiesLoose_objectWithoutPropertiesLoose(_ref4, _excluded3$2);
/* istanbul ignore next (preact) */
onChangeKey = 'onChange';
var _this$getState6 = _this.getState(),
inputValue = _this$getState6.inputValue,
isOpen = _this$getState6.isOpen,
highlightedIndex = _this$getState6.highlightedIndex;
eventHandlers = (_eventHandlers = {}, _eventHandlers[onChangeKey] = callAllEventHandlers(onChange, onInput, _this.inputHandleChange), _eventHandlers.onKeyDown = callAllEventHandlers(onKeyDown, _this.inputHandleKeyDown), _eventHandlers.onBlur = callAllEventHandlers(onBlur, _this.inputHandleBlur), _eventHandlers);
'aria-autocomplete': 'list',
'aria-activedescendant': isOpen && typeof highlightedIndex === 'number' && highlightedIndex >= 0 ? _this.getItemId(highlightedIndex) : null,
'aria-controls': isOpen ? _this.menuId : null,
'aria-labelledby': _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
_this.inputHandleKeyDown = function (event) {
var key = normalizeArrowKey(event);
if (key && _this.inputKeyDownHandlers[key]) {
_this.inputKeyDownHandlers[key].call(assertThisInitialized_assertThisInitialized(_this), event);
_this.inputHandleChange = function (event) {
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 downshiftButtonIsActive = _this.props.environment.document && !!_this.props.environment.document.activeElement && !!_this.props.environment.document.activeElement.dataset && _this.props.environment.document.activeElement.dataset.toggle && _this._rootNode && _this._rootNode.contains(_this.props.environment.document.activeElement);
if (!_this.isMouseDown && !downshiftButtonIsActive) {
_this.menuRef = function (node) {
_this.getMenuProps = function (_temp5, _temp6) {
var _ref5 = _temp5 === void 0 ? {} : _temp5,
_ref5$refKey = _ref5.refKey,
refKey = _ref5$refKey === void 0 ? 'ref' : _ref5$refKey,
props = objectWithoutPropertiesLoose_objectWithoutPropertiesLoose(_ref5, _excluded4$1);
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_extends((_extends3 = {}, _extends3[refKey] = handleRefs(ref, _this.menuRef), _extends3.role = 'listbox', _extends3['aria-labelledby'] = props && props['aria-label'] ? null : _this.labelId, _extends3.id = _this.menuId, _extends3), props);
_this.getItemProps = function (_temp7) {
var _enabledEventHandlers;
var _ref7 = _temp7 === void 0 ? {} : _temp7,
onMouseMove = _ref7.onMouseMove,
onMouseDown = _ref7.onMouseDown,
item = _ref7$item === void 0 ? true ?
/* istanbul ignore next */
undefined : undefined : _ref7$item,
rest = objectWithoutPropertiesLoose_objectWithoutPropertiesLoose(_ref7, _excluded5$1);
if (index === undefined) {
index = _this.items.indexOf(item);
_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) {
_this.setHighlightedIndex(index, {
}); // 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
_this.avoidScrolling = true;
_this.internalSetTimeout(function () {
return _this.avoidScrolling = false;
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.
}, _enabledEventHandlers[onSelectKey] = callAllEventHandlers(customClickHandler, function () {
_this.selectItemAtIndex(index, {
}), _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;
id: _this.getItemId(index),
'aria-selected': _this.getState().highlightedIndex === index
_this.clearItems = function () {
_this.reset = function (otherStateToSet, cb) {
if (otherStateToSet === void 0) {
otherStateToSet = pickState(otherStateToSet);
_this.internalSetState(function (_ref8) {
var selectedItem = _ref8.selectedItem;
isOpen: _this.props.defaultIsOpen,
highlightedIndex: _this.props.defaultHighlightedIndex,
inputValue: _this.props.itemToString(selectedItem)
_this.toggleMenu = function (otherStateToSet, cb) {
if (otherStateToSet === void 0) {
otherStateToSet = pickState(otherStateToSet);
_this.internalSetState(function (_ref9) {
var isOpen = _ref9.isOpen;
highlightedIndex: _this.props.defaultHighlightedIndex
var _this$getState7 = _this.getState(),
isOpen = _this$getState7.isOpen,
highlightedIndex = _this$getState7.highlightedIndex;
if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
_this.setHighlightedIndex(highlightedIndex, otherStateToSet);
_this.openMenu = function (cb) {
_this.closeMenu = function (cb) {
_this.updateStatus = debounce(function () {
var state = _this.getState();
var item = _this.items[state.highlightedIndex];
var resultCount = _this.getItemCount();
var status = _this.props.getA11yStatusMessage(extends_extends({
itemToString: _this.props.itemToString,
previousResultCount: _this.previousResultCount,
resultCount: resultCount,
_this.previousResultCount = resultCount;
setStatus(status, _this.props.environment.document);
var _this$props = _this.props,
defaultHighlightedIndex = _this$props.defaultHighlightedIndex,
_this$props$initialHi = _this$props.initialHighlightedIndex,
_highlightedIndex = _this$props$initialHi === void 0 ? defaultHighlightedIndex : _this$props$initialHi,
defaultIsOpen = _this$props.defaultIsOpen,
_this$props$initialIs = _this$props.initialIsOpen,
_isOpen = _this$props$initialIs === void 0 ? defaultIsOpen : _this$props$initialIs,
_this$props$initialIn = _this$props.initialInputValue,
_inputValue = _this$props$initialIn === void 0 ? '' : _this$props$initialIn,
_this$props$initialSe = _this$props.initialSelectedItem,
_selectedItem = _this$props$initialSe === void 0 ? null : _this$props$initialSe;
var _state = _this.getState({
highlightedIndex: _highlightedIndex,
selectedItem: _selectedItem
if (_state.selectedItem != null && _this.props.initialInputValue === undefined) {
_state.inputValue = _this.props.itemToString(_state.selectedItem);
var _proto = Downshift.prototype;
* Clear all running timeouts
_proto.internalClearTimeouts = function internalClearTimeouts() {
this.timeoutIds.forEach(function (id) {
* 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
* @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:
// 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;
_proto.getItemNodeFromIndex = function getItemNodeFromIndex(index) {
return this.props.environment.document.getElementById(this.getItemId(index));
_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;
var nextHighlightedIndex = getNextWrappingIndex(amount, highlightedIndex, itemCount, function (index) {
return _this6.getItemNodeFromIndex(index);
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 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,
setItemCount = this.setItemCount,
unsetItemCount = this.unsetItemCount,
setState = this.internalSetState;
getRootProps: getRootProps,
getToggleButtonProps: getToggleButtonProps,
getLabelProps: getLabelProps,
getMenuProps: getMenuProps,
getInputProps: getInputProps,
getItemProps: getItemProps,
selectItemAtIndex: selectItemAtIndex,
selectHighlightedItem: selectHighlightedItem,
setHighlightedIndex: setHighlightedIndex,
clearSelection: clearSelection,
setItemCount: setItemCount,
unsetItemCount: unsetItemCount,
itemToString: itemToString,
highlightedIndex: highlightedIndex,