react-bootstrap-typeahead
Version:
React typeahead with Bootstrap styling
86 lines (85 loc) • 2.36 kB
JavaScript
import React, { useEffect, useRef } from 'react';
import { TypeaheadContext } from './Context';
import { defaultSelectHint, getHintText, getInputProps, getInputText, getIsOnlyResult, isFunction, pick, } from '../utils';
const inputPropKeys = [
'activeIndex',
'disabled',
'id',
'inputRef',
'isFocused',
'isMenuShown',
'multiple',
'onBlur',
'onChange',
'onClick',
'onFocus',
'onKeyDown',
'placeholder',
];
const propKeys = [
'activeIndex',
'hideMenu',
'isMenuShown',
'labelKey',
'onClear',
'onHide',
'onRemove',
'results',
'selected',
'text',
'toggleMenu',
];
const contextKeys = [
'activeIndex',
'id',
'initialItem',
'inputNode',
'onActiveItemChange',
'onAdd',
'onInitialItemChange',
'onMenuItemClick',
'setItem',
];
const TypeaheadManager = (props) => {
const { allowNew, children, initialItem, isMenuShown, onAdd, onInitialItemChange, onKeyDown, onMenuToggle, results, selectHint, } = props;
const hintText = getHintText(props);
useEffect(() => {
if (!(allowNew || results.length)) {
onInitialItemChange();
}
});
const isInitialRender = useRef(true);
useEffect(() => {
if (isInitialRender.current) {
isInitialRender.current = false;
return;
}
onMenuToggle(isMenuShown);
}, [isMenuShown, onMenuToggle]);
const handleKeyDown = (e) => {
onKeyDown(e);
if (!initialItem) {
return;
}
const addOnlyResult = e.key === 'Enter' && getIsOnlyResult(props);
const shouldSelectHint = hintText && defaultSelectHint(e, selectHint);
if (addOnlyResult || shouldSelectHint) {
onAdd(initialItem);
}
};
const childProps = {
...pick(props, propKeys),
getInputProps: getInputProps({
...pick(props, inputPropKeys),
onKeyDown: handleKeyDown,
value: getInputText(props),
}),
};
const contextValue = {
...pick(props, contextKeys),
hintText,
isOnlyResult: getIsOnlyResult(props),
};
return (React.createElement(TypeaheadContext.Provider, { value: contextValue }, isFunction(children) ? children(childProps) : children));
};
export default TypeaheadManager;