import PropTypes from 'prop-types'; import React, { Component } from 'react'; import Autosuggest from 'react-autosuggest'; import { Manager, Popper, Reference } from 'react-popper'; import classNames from 'classnames'; import Portal from 'Components/Portal'; import styles from './AutoSuggestInput.css'; class AutoSuggestInput extends Component { // // Lifecycle constructor(props, context) { super(props, context); this._scheduleUpdate = null; } componentDidUpdate(prevProps) { if ( this._scheduleUpdate && prevProps.suggestions !== this.props.suggestions ) { this._scheduleUpdate(); } } // // Control renderInputComponent = (inputProps) => { const { renderInputComponent } = this.props; return ( {({ ref }) => { if (renderInputComponent) { return renderInputComponent(inputProps, ref); } return (
); }}
); } renderSuggestionsContainer = ({ containerProps, children }) => { return ( {({ ref: popperRef, style, scheduleUpdate }) => { this._scheduleUpdate = scheduleUpdate; return (
{children}
); }}
); } // // Listeners onComputeMaxHeight = (data) => { const { top, bottom, width } = data.offsets.reference; const windowHeight = window.innerHeight; if ((/^botton/).test(data.placement)) { data.styles.maxHeight = windowHeight - bottom; } else { data.styles.maxHeight = top; } data.styles.width = width; return data; } onInputChange = (event, { newValue }) => { this.props.onChange({ name: this.props.name, value: newValue }); } onInputKeyDown = (event) => { const { name, value, suggestions, onChange } = this.props; if ( event.key === 'Tab' && suggestions.length && suggestions[0] !== this.props.value ) { event.preventDefault(); if (value) { onChange({ name, value: suggestions[0] }); } } } // // Render render() { const { forwardedRef, className, inputContainerClassName, name, value, placeholder, suggestions, hasError, hasWarning, getSuggestionValue, renderSuggestion, onInputChange, onInputKeyDown, onInputFocus, onInputBlur, onSuggestionsFetchRequested, onSuggestionsClearRequested, onSuggestionSelected, ...otherProps } = this.props; const inputProps = { className: classNames( className, hasError && styles.hasError, hasWarning && styles.hasWarning, ), name, value, placeholder, autoComplete: 'off', spellCheck: false, onChange: onInputChange || this.onInputChange, onKeyDown: onInputKeyDown || this.onInputKeyDown, onFocus: onInputFocus, onBlur: onInputBlur }; const theme = { container: inputContainerClassName, containerOpen: styles.suggestionsContainerOpen, suggestionsContainer: styles.suggestionsContainer, suggestionsList: styles.suggestionsList, suggestion: styles.suggestion, suggestionHighlighted: styles.suggestionHighlighted }; return ( ); } } AutoSuggestInput.propTypes = { forwardedRef: PropTypes.func, className: PropTypes.string.isRequired, inputContainerClassName: PropTypes.string.isRequired, name: PropTypes.string.isRequired, value: PropTypes.oneOfType([PropTypes.string, PropTypes.array]), placeholder: PropTypes.string, suggestions: PropTypes.array.isRequired, hasError: PropTypes.bool, hasWarning: PropTypes.bool, enforceMaxHeight: PropTypes.bool.isRequired, minHeight: PropTypes.number.isRequired, maxHeight: PropTypes.number.isRequired, getSuggestionValue: PropTypes.func.isRequired, renderInputComponent: PropTypes.func, renderSuggestion: PropTypes.func.isRequired, onInputChange: PropTypes.func, onInputKeyDown: PropTypes.func, onInputFocus: PropTypes.func, onInputBlur: PropTypes.func.isRequired, onSuggestionsFetchRequested: PropTypes.func.isRequired, onSuggestionsClearRequested: PropTypes.func.isRequired, onSuggestionSelected: PropTypes.func, onChange: PropTypes.func.isRequired }; AutoSuggestInput.defaultProps = { className: styles.input, inputContainerClassName: styles.inputContainer, enforceMaxHeight: true, minHeight: 50, maxHeight: 200 }; export default AutoSuggestInput;