: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
case InputKeyDownArrowUp:
highlightedIndex: getNextWrappingIndex(shiftKey ? -5 : -1, state.highlightedIndex, props.items.length, action.getItemNodeFromIndex, props.circularNavigation)
highlightedIndex: getHighlightedIndexOnOpen(props, state, -1, action.getItemNodeFromIndex),
isOpen: props.items.length >= 0
changes = { ...(state.isOpen && state.highlightedIndex >= 0 && {
selectedItem: props.items[state.highlightedIndex],
isOpen: getDefaultValue$1(props, 'isOpen'),
highlightedIndex: getDefaultValue$1(props, 'highlightedIndex'),
inputValue: props.itemToString(props.items[state.highlightedIndex])
highlightedIndex: getNextNonDisabledIndex(1, 0, props.items.length, action.getItemNodeFromIndex, false)
highlightedIndex: getNextNonDisabledIndex(-1, props.items.length - 1, props.items.length, action.getItemNodeFromIndex, false)
...(state.highlightedIndex >= 0 && action.selectItem && {
selectedItem: props.items[state.highlightedIndex],
inputValue: props.itemToString(props.items[state.highlightedIndex])
highlightedIndex: getDefaultValue$1(props, 'highlightedIndex'),
inputValue: action.inputValue
selectedItem: action.selectedItem,
inputValue: props.itemToString(action.selectedItem)
case ControlledPropUpdatedSelectedItem:
inputValue: action.inputValue
return downshiftCommonReducer(state, action, stateChangeTypes$1);
/* eslint-enable complexity */
/* eslint-disable max-statements */
useCombobox.stateChangeTypes = stateChangeTypes$1;
function useCombobox(userProps) {
if (userProps === void 0) {
validatePropTypes$1(userProps, useCombobox); // Props defaults and destructuring.
const props = { ...defaultProps$1,
} = props; // Initial state depending on controlled props.
const initialState = getInitialState$1(props);
const [state, dispatch] = useControlledReducer(downshiftUseComboboxReducer, initialState, props);
} = state; // Element refs.
const menuRef = (0,external_React_.useRef)(null);
const itemRefs = (0,external_React_.useRef)({});
const inputRef = (0,external_React_.useRef)(null);
const toggleButtonRef = (0,external_React_.useRef)(null);
const comboboxRef = (0,external_React_.useRef)(null);
const isInitialMountRef = (0,external_React_.useRef)(true); // prevent id re-generation between renders.
const elementIds = useElementIds(props); // used to keep track of how many items we had on previous cycle.
const previousResultCountRef = (0,external_React_.useRef)(); // utility callback to get item element.
const latest = downshift_esm_useLatestRef({
const getItemNodeFromIndex = (0,external_React_.useCallback)(index => itemRefs.current[elementIds.getItemId(index)], [elementIds]); // Effects.
// Sets a11y status message on changes in state.
useA11yMessageSetter(getA11yStatusMessage, [isOpen, highlightedIndex, inputValue, items], {
isInitialMount: isInitialMountRef.current,
previousResultCount: previousResultCountRef.current,
}); // Sets a11y status message on changes in selectedItem.
useA11yMessageSetter(getA11ySelectionMessage, [selectedItem], {
isInitialMount: isInitialMountRef.current,
previousResultCount: previousResultCountRef.current,
}); // Scroll on highlighted item if change comes from keyboard.
const shouldScrollRef = useScrollIntoView({
menuElement: menuRef.current,
useControlPropsValidator({
isInitialMount: isInitialMountRef.current,
}); // Focus the input on first render if required.
(0,external_React_.useEffect)(() => {
const focusOnOpen = initialIsOpen || defaultIsOpen || isOpen;
if (focusOnOpen && inputRef.current) {
inputRef.current.focus();
} // eslint-disable-next-line react-hooks/exhaustive-deps
(0,external_React_.useEffect)(() => {
if (isInitialMountRef.current) {
previousResultCountRef.current = items.length;
}); // Add mouse/touch events to document.
const mouseAndTouchTrackersRef = useMouseAndTouchTracker(isOpen, [comboboxRef, menuRef, toggleButtonRef], environment, () => {
const setGetterPropCallInfo = useGetterPropsCalledChecker('getInputProps', 'getComboboxProps', 'getMenuProps'); // Make initial ref false.
(0,external_React_.useEffect)(() => {
isInitialMountRef.current = false;
}, []); // Reset itemRefs on close.
(0,external_React_.useEffect)(() => {
/* Event handler functions */
const inputKeyDownHandlers = (0,external_React_.useMemo)(() => ({
type: InputKeyDownArrowDown,
shiftKey: event.shiftKey,
type: InputKeyDownArrowUp,
shiftKey: event.shiftKey,
if (!latest.current.state.isOpen) {
if (!latest.current.state.isOpen) {
const latestState = latest.current.state;
if (latestState.isOpen || latestState.inputValue || latestState.selectedItem || latestState.highlightedIndex > -1) {
const latestState = latest.current.state; // if closed or no highlighted index, do nothing.
if (!latestState.isOpen || latestState.highlightedIndex < 0 || event.which === 229 // if IME composing, wait for next Enter keydown event.
}), [dispatch, latest, getItemNodeFromIndex]); // Getter props.
const getLabelProps = (0,external_React_.useCallback)(labelProps => ({
htmlFor: elementIds.inputId,
const getMenuProps = (0,external_React_.useCallback)(function (_temp, _temp2) {
} = _temp === void 0 ? {} : _temp;
} = _temp2 === void 0 ? {} : _temp2;
setGetterPropCallInfo('getMenuProps', suppressRefError, refKey, menuRef);
[refKey]: handleRefs(ref, menuNode => {
menuRef.current = menuNode;
'aria-labelledby': elementIds.labelId,
onMouseLeave: callAllEventHandlers(onMouseLeave, () => {
}, [dispatch, setGetterPropCallInfo, elementIds]);
const getItemProps = (0,external_React_.useCallback)(function (_temp3) {
} = _temp3 === void 0 ? {} : _temp3;
const itemIndex = getItemIndex(index, item, latestProps.items);
throw new Error('Pass either item or item index in getItemProps!');
const onSelectKey = 'onClick';
const customClickHandler = onClick;
const itemHandleMouseMove = () => {
if (index === latestState.highlightedIndex) {
shouldScrollRef.current = false;
const itemHandleClick = () => {
const itemHandleMouseDown = e => e.preventDefault();
[refKey]: handleRefs(ref, itemNode => {
itemRefs.current[elementIds.getItemId(itemIndex)] = itemNode;
'aria-selected': `${itemIndex === latestState.highlightedIndex}`,
id: elementIds.getItemId(itemIndex),
[onSelectKey]: callAllEventHandlers(customClickHandler, itemHandleClick)
onMouseMove: callAllEventHandlers(onMouseMove, itemHandleMouseMove),
onMouseDown: callAllEventHandlers(onMouseDown, itemHandleMouseDown),
}, [dispatch, latest, shouldScrollRef, elementIds]);
const getToggleButtonProps = (0,external_React_.useCallback)(function (_temp4) {
} = _temp4 === void 0 ? {} : _temp4;
const toggleButtonHandleClick = () => {
if (!latest.current.state.isOpen && inputRef.current) {
inputRef.current.focus();
[refKey]: handleRefs(ref, toggleButtonNode => {
toggleButtonRef.current = toggleButtonNode;
id: elementIds.toggleButtonId,
...(!rest.disabled && { ...({
onClick: callAllEventHandlers(onClick, toggleButtonHandleClick)
}, [dispatch, latest, elementIds]);
const getInputProps = (0,external_React_.useCallback)(function (_temp5, _temp6) {
} = _temp5 === void 0 ? {} : _temp5;
} = _temp6 === void 0 ? {} : _temp6;
setGetterPropCallInfo('getInputProps', suppressRefError, refKey, inputRef);
const latestState = latest.current.state;
const inputHandleKeyDown = event => {
const key = normalizeArrowKey(event);
if (key && inputKeyDownHandlers[key]) {
inputKeyDownHandlers[key](event);
const inputHandleChange = event => {
inputValue: event.target.value
const inputHandleBlur = () => {
/* istanbul ignore else */
if (latestState.isOpen && !mouseAndTouchTrackersRef.current.isMouseDown) {
/* istanbul ignore next (preact) */
const onChangeKey = 'onChange';
[onChangeKey]: callAllEventHandlers(onChange, onInput, inputHandleChange),
onKeyDown: callAllEventHandlers(onKeyDown, inputHandleKeyDown),
onBlur: callAllEventHandlers(onBlur, inputHandleBlur)
[refKey]: handleRefs(ref, inputNode => {
inputRef.current = inputNode;
'aria-autocomplete': 'list',
'aria-controls': elementIds.menuId,
...(latestState.isOpen && latestState.highlightedIndex > -1 && {
'aria-activedescendant': elementIds.getItemId(latestState.highlightedIndex)
'aria-labelledby': elementIds.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
value: latestState.inputValue,
}, [dispatch, inputKeyDownHandlers, latest, mouseAndTouchTrackersRef, setGetterPropCallInfo, elementIds]);
const getComboboxProps = (0,external_React_.useCallback)(function (_temp7, _temp8) {
} = _temp7 === void 0 ? {} : _temp7;
} = _temp8 === void 0 ? {} : _temp8;
setGetterPropCallInfo('getComboboxProps', suppressRefError, refKey, comboboxRef);
[refKey]: handleRefs(ref, comboboxNode => {
comboboxRef.current = comboboxNode;