Another attempt at fixing autosuggest behavior
This commit is contained in:
parent
e44f404e28
commit
75feeb2959
|
@ -1,83 +1,97 @@
|
||||||
import React, { useState } from 'react'
|
import React, { Component, createRef } from 'react'
|
||||||
import { useCombobox } from 'downshift'
|
import { useCombobox } from 'downshift'
|
||||||
|
|
||||||
const Autocomplete = props => {
|
export default class Autocomplete extends Component {
|
||||||
|
|
||||||
const [ inputItems, setInputItems ] = useState(props.vocabulary);
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
const onInputValueChange = ({ inputValue }) => {
|
|
||||||
if (inputValue.length > 0) {
|
|
||||||
const prefixMatches = props.vocabulary.filter(item => {
|
|
||||||
return item.toLowerCase().startsWith(inputValue.toLowerCase());
|
|
||||||
});
|
|
||||||
|
|
||||||
setInputItems(prefixMatches);
|
this.element = createRef();
|
||||||
} else {
|
|
||||||
// ...or none, if the input is empty
|
|
||||||
setInputItems([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
isOpen,
|
|
||||||
getMenuProps,
|
|
||||||
getInputProps,
|
|
||||||
getComboboxProps,
|
|
||||||
highlightedIndex,
|
|
||||||
getItemProps,
|
|
||||||
setInputValue
|
|
||||||
} = useCombobox({
|
|
||||||
items: inputItems,
|
|
||||||
onInputValueChange,
|
|
||||||
onSelectedItemChange: ({ inputValue }) => {
|
|
||||||
onSubmit(inputValue);
|
|
||||||
setInputValue('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmit = inputValue => {
|
this.state = {
|
||||||
setInputValue('');
|
inputItems: props.vocabulary || []
|
||||||
if (inputValue.trim().length > 0)
|
|
||||||
props.onSubmit(inputValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
const onKeyUp = evt => {
|
|
||||||
const { value } = evt.target;
|
|
||||||
|
|
||||||
if (evt.which == 13 && highlightedIndex == -1) {
|
|
||||||
onSubmit(value);
|
|
||||||
} else if (evt.which == 40 && value.length == 0) {
|
|
||||||
setInputItems(props.vocabulary); // Show all options on key down
|
|
||||||
} else if (evt.which == 27) {
|
|
||||||
props.onCancel && props.onCancel();
|
|
||||||
} else {
|
|
||||||
props.onChange && props.onChange(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
componentDidMount() {
|
||||||
<div className="r6o-autocomplete">
|
if (this.props.initialValue && this.element.current)
|
||||||
<div {...getComboboxProps()}>
|
this.element.current.querySelector('input').value = this.props.initialValue;
|
||||||
<input
|
}
|
||||||
{...getInputProps({ onKeyUp })}
|
|
||||||
placeholder={props.placeholder} />
|
onInputValueChange = ({ inputValue }) => {
|
||||||
|
if (inputValue.length > 0) {
|
||||||
|
const prefixMatches = this.props.vocabulary.filter(item => {
|
||||||
|
return item.toLowerCase().startsWith(inputValue.toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
this.setState({ inputItems: prefixMatches });
|
||||||
|
} else {
|
||||||
|
// ...or none, if the input is empty
|
||||||
|
this.setState({ inputItems: [] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
const {
|
||||||
|
isOpen,
|
||||||
|
getMenuProps,
|
||||||
|
getInputProps,
|
||||||
|
getComboboxProps,
|
||||||
|
highlightedIndex,
|
||||||
|
getItemProps,
|
||||||
|
setInputValue
|
||||||
|
} = useCombobox({
|
||||||
|
items: this.state.inputItems,
|
||||||
|
onInputValueChange: this.onInputValueChange,
|
||||||
|
onSelectedItemChange: ({ inputValue }) => {
|
||||||
|
onSubmit(inputValue);
|
||||||
|
setInputValue('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = inputValue => {
|
||||||
|
setInputValue('');
|
||||||
|
if (inputValue.trim().length > 0)
|
||||||
|
this.props.onSubmit(inputValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onKeyUp = evt => {
|
||||||
|
const { value } = evt.target;
|
||||||
|
|
||||||
|
if (evt.which == 13 && highlightedIndex == -1) {
|
||||||
|
onSubmit(value);
|
||||||
|
} else if (evt.which == 40 && value.length == 0) {
|
||||||
|
setInputItems(this.props.vocabulary); // Show all options on key down
|
||||||
|
} else if (evt.which == 27) {
|
||||||
|
this.props.onCancel && this.props.onCancel();
|
||||||
|
} else {
|
||||||
|
this.props.onChange && this.props.onChange(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="r6o-autocomplete" ref={this.element}>
|
||||||
|
<div {...getComboboxProps()}>
|
||||||
|
<input
|
||||||
|
{...getInputProps({ onKeyUp })}
|
||||||
|
placeholder={this.props.placeholder} />
|
||||||
|
</div>
|
||||||
|
<ul {...getMenuProps()}>
|
||||||
|
{isOpen && this.state.inputItems.map((item, index) => (
|
||||||
|
<li style={
|
||||||
|
highlightedIndex === index
|
||||||
|
? { backgroundColor: '#bde4ff' }
|
||||||
|
: {}
|
||||||
|
}
|
||||||
|
key={`${item}${index}`}
|
||||||
|
{...getItemProps({ item, index })}>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<ul {...getMenuProps()}>
|
)
|
||||||
{isOpen && inputItems.map((item, index) => (
|
}
|
||||||
<li style={
|
|
||||||
highlightedIndex === index
|
|
||||||
? { backgroundColor: '#bde4ff' }
|
|
||||||
: {}
|
|
||||||
}
|
|
||||||
key={`${item}${index}`}
|
|
||||||
{...getItemProps({ item, index })}>
|
|
||||||
{item}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Autocomplete;
|
|
Loading…
Reference in New Issue