import React from 'react' import Downshift from 'downshift' import matchSorter from 'match-sorter' import VisuallyHidden from '@reach/visually-hidden' import { Down as ArrowDown } from './svg/Arrows' import CheckMark from './svg/Checkmark' import { COLORS } from '../lib/constants' class Dropdown extends React.PureComponent { state = { inputValue: this.props.selected.name, itemsToShow: this.props.list } onUserAction = changes => { this.setState(({ inputValue, itemsToShow }) => { if (Object.prototype.hasOwnProperty.call(changes, 'inputValue')) { if (changes.type === Downshift.stateChangeTypes.keyDownEscape) { inputValue = this.userInputtedValue } else if (changes.type === Downshift.stateChangeTypes.changeInput) { inputValue = changes.inputValue this.userInputtedValue = changes.inputValue } else { inputValue = changes.inputValue } } itemsToShow = this.userInputtedValue ? matchSorter(this.props.list, this.userInputtedValue, { keys: ['name'] }) : this.props.list if ( Object.prototype.hasOwnProperty.call(changes, 'highlightedIndex') && (changes.type === Downshift.stateChangeTypes.keyDownArrowUp || changes.type === Downshift.stateChangeTypes.keyDownArrowDown) ) { inputValue = itemsToShow[changes.highlightedIndex].name this.props.onChange(itemsToShow[changes.highlightedIndex]) } if (Object.prototype.hasOwnProperty.call(changes, 'isOpen')) { this.userInputtedValue = '' // clear on open if (changes.isOpen) { inputValue = '' this.props.onOpen && this.props.onOpen() } else if (changes.isOpen === false && !inputValue) { // set on close inputValue = this.props.selected.name } } return { inputValue, itemsToShow } }) } userInputtedValue = '' renderDropdown = ({ isOpen, highlightedIndex, selectedItem, getRootProps, getToggleButtonProps, getInputProps, getItemProps }) => { const { list, color, itemWrapper, icon, disableInput, title } = this.props const { itemsToShow } = this.state const minWidth = calcMinWidth(itemsToShow) const labelId = title ? `${title.toLowerCase()}-dropdown` : undefined return ( {title && {title}} {icon} {selectedItem.name} {isOpen ? ( {list.map((item, index) => ( {item.name} ))} ) : null} ) } render() { const { innerRef, selected, onChange, title } = this.props const { itemsToShow, inputValue } = this.state const labelId = title ? `${title.toLowerCase()}-dropdown` : undefined return ( it === selected)} itemToString={item => item.name} onChange={onChange} onUserAction={this.onUserAction} labelId={labelId} > {this.renderDropdown} ) } } const DropdownContainer = ({ children, innerRef, minWidth, ...rest }) => { return (
{children}
) } const DropdownIcon = ({ children, isOpen }) => { if (children) { return (
{children}
) } return null } const SelectedItem = ({ getToggleButtonProps, getInputProps, children, isOpen, color, hasIcon, disabled }) => { const itemColor = color || COLORS.SECONDARY return (
) } const List = ({ children, color }) => { return ( ) } const ListItem = ({ children, color, isHighlighted, isSelected, itemWrapper, item, ...rest }) => { const itemColor = color || COLORS.SECONDARY return (
  • {itemWrapper ? ( itemWrapper({ children, color: itemColor, item, isSelected }) ) : ( {children} )} {isSelected ? : null}
  • ) } function calcMinWidth(items) { return items.reduce((max, { name }) => { const wordSize = name.length * 10 + 32 return wordSize > max ? wordSize : max }, 0) } export default Dropdown