import React, { InputHTMLAttributes, MouseEventHandler } from 'react'; import { MessageDescriptor } from 'react-intl'; import ClickAwayListener from 'react-click-away-listener'; import clsx from 'clsx'; import { COLOR_GREEN, Color } from 'app/components/ui'; import styles from './dropdown.scss'; import FormInputComponent from './FormInputComponent'; type I18nString = string | MessageDescriptor; type ItemLabel = I18nString | React.ReactElement; interface Props extends InputHTMLAttributes { label: I18nString; items: Record; block?: boolean; color: Color; } interface OptionItem { label: ItemLabel; value: string; } interface State { isActive: boolean; activeItem: OptionItem | null; } export default class Dropdown extends FormInputComponent { static defaultProps: Partial = { color: COLOR_GREEN, }; state: State = { isActive: false, activeItem: null, }; render() { const { color, block, items, ...restProps } = this.props; const { isActive } = this.state; delete restProps.label; const activeItem = this.getActiveItem(); const label = React.isValidElement(activeItem.label) ? activeItem.label : this.formatMessage(activeItem.label); return ( {label} {Object.entries(items).map(([value, label]) => ( {label} ))} {this.renderError()} ); } toggle() { this.setState({ isActive: !this.state.isActive, }); } onSelectItem(item: OptionItem): MouseEventHandler { return (event) => { event.preventDefault(); this.setState({ activeItem: item, }); }; } getActiveItem(): OptionItem { const { items } = this.props; let { activeItem } = this.state; if (!activeItem) { activeItem = { label: this.props.label, value: '', }; if (!activeItem.label) { const [[value, label]] = Object.entries(items); activeItem = { label, value, }; } } return activeItem; } getValue() { return this.getActiveItem()?.value; } onToggle = (event: React.MouseEvent) => { event.preventDefault(); this.toggle(); }; onCloseClick = () => { if (this.state.isActive) { this.toggle(); } }; }