import Downshift, { ControllerStateAndHelpers, DownshiftProps } from 'downshift'; import React from 'react'; import styled from 'styled-components'; import { colors } from '../../../constants'; import ErrorMessage from '../../atoms/ErrorMessage/ErrorMessage'; import InputLabel from '../../atoms/InputLabel/InputLabel'; import SizedContainer from '../../layout/SizedContainer/SizedContainer'; import Icon from '../../atoms/Icon/Icon'; import { faSort } from '@fortawesome/free-solid-svg-icons'; import unbrandedChevron from '../../../content/images/unbranded-chevron.svg'; import { FieldProps, InputProps } from '../../types'; import { useThemeContext } from '../../styles/Theme'; import Option from './Option'; import Options, { OptionsListProps } from './Options'; import { SearchInputProps, SearchInput } from './SearchInput'; export interface DropdownItem { value: string; } export interface DropdownFilteredProps extends DownshiftProps, SearchInputProps, OptionsListProps, Omit, FieldProps { /** * Native props for the native label element. */ labelProps?: React.LabelHTMLAttributes; /** * Items for the options */ items: DropdownItem[]; } const FieldError = styled(ErrorMessage)` margin-top: 5px; `; export const SearchInputWrap = styled.div` position: relative; `; export const CustomIcon = styled.div<{ isOpen: boolean }>` background: transparent url(${unbrandedChevron}) no-repeat center; background-size: 60%; width: 100%; height: 100%; color: black; transform: ${({ isOpen }) => (isOpen ? 'rotate(180deg)' : 'none')}; `; const DropdownFiltered = (props: DropdownFilteredProps) => { const { errorMessage, items = [], label, optionsListMaxHeight, name, labelProps, isValid, disabled, onChange, onFocus, inputSize, ...rest } = props; const searchMatch = (itemValue: string, inputValue: string) => itemValue && itemValue.toLowerCase().includes(inputValue.toLowerCase()); const theme = useThemeContext(); return ( (item ? item.value : '')} {...props}> {({ clearSelection, getInputProps, getItemProps, getLabelProps, getMenuProps, highlightedIndex, inputValue, isOpen, openMenu, closeMenu, selectedItem, }: ControllerStateAndHelpers) => { const filteredResults = items.filter(({ value }) => searchMatch(value, inputValue || '')); const showError = errorMessage && !isOpen; return (
{label && ( {label} )} ) => { if (e.target.value === '') { clearSelection(); } }, onFocus: () => { openMenu(); }, ...rest, })} name={name} id={`text-id-${name}`} aria-describedby={`error-dropdown-filtered-${name}`} isValid={isValid} hasError={showError} isOpen={isOpen && !!filteredResults.length} disabled={disabled} theme={theme} endIcon={ theme.input.searchInput.customIcon ? ( { if (!disabled) { if (isOpen) { closeMenu(); } else { clearSelection(() => { openMenu(); }); } } }} aria-label={isOpen ? 'close.menu' : 'open.menu'} /> ) : ( { if (!disabled) { if (isOpen) { closeMenu(); } else { clearSelection(() => { openMenu(); }); } } }} aria-label={isOpen ? 'close.menu' : 'open.menu'} /> ) } /> {isOpen && !!filteredResults.length && ( {filteredResults.map((item, index) => ( ))} )} {showError && ( {errorMessage} )}
); }}
); }; export default DropdownFiltered;