This commit is contained in:
Rainer Simon 2021-08-03 10:01:01 +02:00
parent 8f0a78a7d4
commit fbdcdd18dd
1 changed files with 73 additions and 82 deletions

View File

@ -1,43 +1,33 @@
import React, { Component, createRef } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { useCombobox } from 'downshift'; import { useCombobox } from 'downshift';
export default class Autocomplete extends Component { const Autocomplete = props => {
constructor(props) { const element = useRef();
super(props);
this.element = createRef(); const [ inputItems, setInputItems ] = useState(props.vocabulary || []);
this.state = { useEffect(() => {
inputItems: props.vocabulary || [] if (props.initialValue)
} element.current.querySelector('input').value = props.initialValue;
}
componentDidMount() { if (props.focus)
if (this.element.current) { element.current.querySelector('input').focus({ preventScroll: true });
if (this.props.initialValue) }, [])
this.element.current.querySelector('input').value = this.props.initialValue;
if (this.props.focus) const onInputValueChange = ({ inputValue }) => {
this.element.current.querySelector('input').focus({ preventScroll: true });
}
}
onInputValueChange = ({ inputValue }) => {
if (inputValue.length > 0) { if (inputValue.length > 0) {
const prefixMatches = this.props.vocabulary.filter(item => { const prefixMatches = props.vocabulary.filter(item => {
return item.toLowerCase().startsWith(inputValue.toLowerCase()); return item.toLowerCase().startsWith(inputValue.toLowerCase());
}); });
this.setState({ inputItems: prefixMatches }); setInputItems(prefixMatches);
} else { } else {
// ...or none, if the input is empty // ...or none, if the input is empty
this.setState({ inputItems: [] }); setInputItems([]);
} }
} }
render() {
const { const {
isOpen, isOpen,
getMenuProps, getMenuProps,
@ -47,8 +37,8 @@ export default class Autocomplete extends Component {
getItemProps, getItemProps,
setInputValue setInputValue
} = useCombobox({ } = useCombobox({
items: this.state.inputItems, items: inputItems,
onInputValueChange: this.onInputValueChange, onInputValueChange: onInputValueChange,
onSelectedItemChange: ({ inputValue }) => { onSelectedItemChange: ({ inputValue }) => {
onSubmit(inputValue); onSubmit(inputValue);
setInputValue(''); setInputValue('');
@ -58,7 +48,7 @@ export default class Autocomplete extends Component {
const onSubmit = inputValue => { const onSubmit = inputValue => {
setInputValue(''); setInputValue('');
if (inputValue.trim().length > 0) if (inputValue.trim().length > 0)
this.props.onSubmit(inputValue); props.onSubmit(inputValue);
} }
const onKeyUp = evt => { const onKeyUp = evt => {
@ -67,23 +57,23 @@ export default class Autocomplete extends Component {
if (evt.which == 13 && highlightedIndex == -1) { if (evt.which == 13 && highlightedIndex == -1) {
onSubmit(value); onSubmit(value);
} else if (evt.which == 40 && value.length == 0) { } else if (evt.which == 40 && value.length == 0) {
this.setState({ inputItems: this.props.vocabulary }); // Show all options on key down setInputItems(props.vocabulary); // Show all options on key down
} else if (evt.which == 27) { } else if (evt.which == 27) {
this.props.onCancel && this.props.onCancel(); props.onCancel && props.onCancel();
} else { } else {
this.props.onChange && this.props.onChange(value); props.onChange && props.onChange(value);
} }
} }
return ( return (
<div className="r6o-autocomplete" ref={this.element}> <div className="r6o-autocomplete" ref={element}>
<div {...getComboboxProps()}> <div {...getComboboxProps()}>
<input <input
{...getInputProps({ onKeyUp })} {...getInputProps({ onKeyUp })}
placeholder={this.props.placeholder} /> placeholder={props.placeholder} />
</div> </div>
<ul {...getMenuProps()}> <ul {...getMenuProps()}>
{isOpen && this.state.inputItems.map((item, index) => ( {isOpen && inputItems.map((item, index) => (
<li style={ <li style={
highlightedIndex === index highlightedIndex === index
? { backgroundColor: '#bde4ff' } ? { backgroundColor: '#bde4ff' }
@ -97,6 +87,7 @@ export default class Autocomplete extends Component {
</ul> </ul>
</div> </div>
) )
}
} }
export default Autocomplete;