import CircularProgress from "@material-ui/core/CircularProgress"; import MenuItem from "@material-ui/core/MenuItem"; import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; import TextField from "@material-ui/core/TextField"; import ArrowBack from "@material-ui/icons/ArrowBack"; import Downshift from "downshift"; import React from "react"; import { FormattedMessage } from "react-intl"; import { buttonMessages } from "@saleor/intl"; import { getMenuItemByPath, IMenu, validateMenuOptions } from "../../utils/menu"; import Debounce, { DebounceProps } from "../Debounce"; export interface AutocompleteSelectMenuProps { disabled: boolean; displayValue: string; error: boolean; helperText: string; label: string; loading: boolean; name: string; options: IMenu; placeholder: string; onChange: (event: React.ChangeEvent) => void; onInputChange?: (value: string) => void; } const validationError: Error = new Error( "Values supplied to AutocompleteSelectMenu should be unique" ); const DebounceAutocomplete: React.ComponentType< DebounceProps > = Debounce; const useStyles = makeStyles( theme => ({ container: { flexGrow: 1, position: "relative" }, menuBack: { marginLeft: -theme.spacing(0.5), marginRight: theme.spacing(1) }, paper: { left: 0, marginTop: theme.spacing(), padding: theme.spacing(), position: "absolute", right: 0, zIndex: 2 }, root: {} }), { name: "AutocompleteSelectMenu" } ); const AutocompleteSelectMenu: React.FC = props => { const { disabled, displayValue, error, helperText, label, loading, name, options, placeholder, onChange, onInputChange } = props; const classes = useStyles(props); const [inputValue, setInputValue] = React.useState(displayValue || ""); const [menuPath, setMenuPath] = React.useState([]); const handleChange = (value: string) => onChange({ target: { name, value } } as any); // Validate if option values are duplicated React.useEffect(() => { if (!validateMenuOptions(options)) { throw validationError; } }, []); // Navigate back to main menu after input field change React.useEffect(() => setMenuPath([]), [options]); // Reset input value after displayValue change React.useEffect(() => setInputValue(displayValue), [displayValue]); return ( {debounceFn => ( (item ? item.label : "")} onSelect={handleChange} > {({ getItemProps, isOpen, openMenu, closeMenu, selectItem }) => (
, id: undefined, onBlur: () => { closeMenu(); setMenuPath([]); setInputValue(displayValue); }, onChange: event => { debounceFn(event.target.value); setInputValue(event.target.value); }, onFocus: () => openMenu(), placeholder }} disabled={disabled} error={error} helperText={helperText} label={label} fullWidth={true} value={inputValue} /> {isOpen && ( {options.length ? ( <> {menuPath.length > 0 && ( setMenuPath(menuPath.slice(0, menuPath.length - 2)) } > )} {(menuPath.length ? getMenuItemByPath(options, menuPath).children : options ).map((suggestion, index) => ( suggestion.value ? selectItem(suggestion.value) : setMenuPath([...menuPath, index]) } > {suggestion.label} ))} ) : ( )} )}
)}
)}
); }; AutocompleteSelectMenu.displayName = "AutocompleteSelectMenu"; export default AutocompleteSelectMenu;