: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
this.getMenuProps = function (_temp5, _temp6) {
} = _temp5 === void 0 ? {} : _temp5;
} = _temp6 === void 0 ? {} : _temp6;
_this.getMenuProps.called = true;
_this.getMenuProps.refKey = refKey;
_this.getMenuProps.suppressRefError = suppressRefError;
[refKey]: handleRefs(ref, _this.menuRef),
'aria-labelledby': props && props['aria-label'] ? null : _this.labelId,
this.getItemProps = function (_temp7) {
/* istanbul ignore next */
} = _temp7 === void 0 ? {} : _temp7;
if (index === undefined) {
index = _this.items.indexOf(item);
_this.items[index] = item;
const onSelectKey = 'onClick';
const customClickHandler = onClick;
const 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, () => {
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(() => _this.avoidScrolling = false, 250);
onMouseDown: callAllEventHandlers(onMouseDown, 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.
[onSelectKey]: callAllEventHandlers(customClickHandler, () => {
_this.selectItemAtIndex(index, {
}; // Passing down the onMouseDown handler to prevent redirect
// of the activeElement if clicking on disabled items
const eventHandlers = rest.disabled ? {
onMouseDown: enabledEventHandlers.onMouseDown
} : enabledEventHandlers;
id: _this.getItemId(index),
'aria-selected': _this.getState().highlightedIndex === index,
this.clearItems = () => {
this.reset = function (otherStateToSet, cb) {
if (otherStateToSet === void 0) {
otherStateToSet = pickState(otherStateToSet);
_this.internalSetState(_ref => {
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(_ref2 => {
highlightedIndex: _this.props.defaultHighlightedIndex
if (_this.getItemCount() > 0 && typeof highlightedIndex === 'number') {
_this.setHighlightedIndex(highlightedIndex, otherStateToSet);
this.updateStatus = debounce(() => {
const state = this.getState();
const item = this.items[state.highlightedIndex];
const resultCount = this.getItemCount();
const status = this.props.getA11yStatusMessage({
itemToString: this.props.itemToString,
previousResultCount: this.previousResultCount,
this.previousResultCount = resultCount;
setStatus(status, this.props.environment.document);
// 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
initialHighlightedIndex: _highlightedIndex = defaultHighlightedIndex,
initialIsOpen: _isOpen = defaultIsOpen,
initialInputValue: _inputValue = '',
initialSelectedItem: _selectedItem = null
const _state = this.getState({
highlightedIndex: _highlightedIndex,
selectedItem: _selectedItem
if (_state.selectedItem != null && this.props.initialInputValue === undefined) {
_state.inputValue = this.props.itemToString(_state.selectedItem);
* Clear all running timeouts
internalClearTimeouts() {
this.timeoutIds.forEach(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
if (stateToMerge === void 0) {
stateToMerge = this.state;
return getState(stateToMerge, this.props);
// things read better this way. They're in priority order:
// 2. `this.props.itemCount`
// 3. `this.items.length`
let itemCount = this.items.length;
if (this.itemCount != null) {
itemCount = this.itemCount;
} else if (this.props.itemCount !== undefined) {
itemCount = this.props.itemCount;
getItemNodeFromIndex(index) {
return this.props.environment.document.getElementById(this.getItemId(index));
scrollHighlightedItemIntoView() {
/* istanbul ignore else (react-native) */
const node = this.getItemNodeFromIndex(this.getState().highlightedIndex);
this.props.scrollIntoView(node, this._menuNode);
moveHighlightedIndex(amount, otherStateToSet) {
const itemCount = this.getItemCount();
const nextHighlightedIndex = getNextWrappingIndex(amount, highlightedIndex, itemCount, index => this.getItemNodeFromIndex(index));
this.setHighlightedIndex(nextHighlightedIndex, otherStateToSet);
internalSetState: setState
} //////////////////////////// ROOT
/* istanbul ignore if (react-native) */
/* istanbul ignore if (react-native) */
// 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.
const onMouseDown = () => {
const onMouseUp = event => {
this.isMouseDown = false; // if the target element or the activeElement is within a downshift node
// then we don't want to reset downshift
const contextWithinDownshift = targetWithinDownshift(event.target, [this._rootNode, this._menuNode], this.props.environment);
if (!contextWithinDownshift && this.getState().isOpen) {
}, () => this.props.onOuterClick(this.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
const onTouchStart = () => {
this.isTouchMove = false;
const onTouchMove = () => {
const onTouchEnd = event => {
const contextWithinDownshift = targetWithinDownshift(event.target, [this._rootNode, this._menuNode], this.props.environment, false);
if (!this.isTouchMove && !contextWithinDownshift && this.getState().isOpen) {
}, () => this.props.onOuterClick(this.getStateAndHelpers()));
environment.addEventListener('mousedown', onMouseDown);
environment.addEventListener('mouseup', onMouseUp);
environment.addEventListener('touchstart', onTouchStart);
environment.addEventListener('touchmove', onTouchMove);
environment.addEventListener('touchend', onTouchEnd);
this.internalClearTimeouts();
this.updateStatus.cancel();
environment.removeEventListener('mousedown', onMouseDown);
environment.removeEventListener('mouseup', onMouseUp);
environment.removeEventListener('touchstart', onTouchStart);
environment.removeEventListener('touchmove', onTouchMove);
environment.removeEventListener('touchend', onTouchEnd);
shouldScroll(prevState, prevProps) {
highlightedIndex: currentHighlightedIndex
} = this.props.highlightedIndex === undefined ? this.getState() : this.props;
highlightedIndex: prevHighlightedIndex
} = prevProps.highlightedIndex === undefined ? prevState : prevProps;
const scrollWhenOpen = currentHighlightedIndex && this.getState().isOpen && !prevState.isOpen;
const scrollWhenNavigating = currentHighlightedIndex !== prevHighlightedIndex;
return scrollWhenOpen || scrollWhenNavigating;
componentDidUpdate(prevProps, prevState) {
if (isControlledProp(this.props, 'selectedItem') && this.props.selectedItemChanged(prevProps.selectedItem, this.props.selectedItem)) {
type: controlledPropUpdatedSelectedItem,
inputValue: this.props.itemToString(this.props.selectedItem)
if (!this.avoidScrolling && this.shouldScroll(prevState, prevProps)) {
this.scrollHighlightedItemIntoView();
/* istanbul ignore else (react-native) */
this.cleanup(); // avoids memory leak
const children = unwrapArray(this.props.children, downshift_esm_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;
const element = unwrapArray(children(this.getStateAndHelpers()));
if (this.getRootProps.called || this.props.suppressRefError) {
} 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 */
/* istanbul ignore next */