import React, { Component } from "react"; import PropTypes from "prop-types"; import classnames from "classnames"; import { noop, pick } from "lodash"; import Select from "react-select"; import dropdownOptionInterface from "interfaces/dropdownOption"; import FormField from "components/forms/FormField"; import Icon from "components/Icon"; import DropdownOptionTooltipWrapper from "./DropdownOptionTooltipWrapper"; const baseClass = "dropdown"; class Dropdown extends Component { static propTypes = { className: PropTypes.string, clearable: PropTypes.bool, searchable: PropTypes.bool, disabled: PropTypes.bool, error: PropTypes.string, label: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), labelClassName: PropTypes.string, multi: PropTypes.bool, name: PropTypes.string, onChange: PropTypes.func, onOpen: PropTypes.func, onClose: PropTypes.func, options: PropTypes.arrayOf(dropdownOptionInterface).isRequired, placeholder: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), /** value must correspond to the value of a dropdown option to render e.g. with options: [ { label: "Display name", value: 1, <– the id of the thing } ] set value to 1, not "Display name" */ value: PropTypes.oneOfType([ PropTypes.array, PropTypes.string, PropTypes.number, ]), wrapperClassName: PropTypes.string, parseTarget: PropTypes.bool, tooltip: PropTypes.string, autoFocus: PropTypes.bool, /** Includes styled icon */ iconName: PropTypes.string, helpText: PropTypes.oneOfType([ PropTypes.string, PropTypes.arrayOf(PropTypes.string), PropTypes.object, ]), }; static defaultProps = { onChange: noop, onOpen: noop, onClose: noop, clearable: false, searchable: true, disabled: false, multi: false, name: "targets", placeholder: "Select one...", // if value undefined parseTarget: false, tooltip: "", autoFocus: false, iconName: "", }; onMenuOpen = () => { const { onOpen } = this.props; onOpen(); }; onMenuClose = () => { const { onClose } = this.props; onClose(); }; handleChange = (selected) => { const { multi, onChange, clearable, name, parseTarget } = this.props; if (parseTarget) { // Returns both name of the Dropdown and value of the selected option return onChange({ value: selected.value, name }); } if (clearable && selected === null) { return onChange(null); } if (multi) { return onChange(selected.map((obj) => obj.value).join(",")); } return onChange(selected.value); }; renderLabel = () => { const { error, label, labelClassName, name } = this.props; const labelWrapperClasses = classnames( `${baseClass}__label`, labelClassName, { [`${baseClass}__label--error`]: error } ); if (!label) { return false; } return ( ); }; renderOption = (option) => { if (option.tooltipContent) { return (
{option.label} {option.helpText && ( {option.helpText} )}
); } return (
{option.label} {option.helpText && ( {option.helpText} )}
); }; renderCustomDropdownArrow = () => { return (
); }; // Adds styled icon to dropdown renderWithIcon = () => { const { options, value, iconName } = this.props; const customLabel = options .filter((option) => option.value === value) .map((option) => option.label); return (
{customLabel}
); }; render() { const { handleChange, renderOption, onMenuOpen, onMenuClose, renderCustomDropdownArrow, renderWithIcon, } = this; const { error, className, clearable, disabled, multi, name, options, placeholder, value, wrapperClassName, searchable, autoFocus, iconName, } = this.props; const formFieldProps = pick(this.props, [ "helpText", "label", "error", "name", "tooltip", "disabled", ]); const selectClasses = classnames(className, `${baseClass}__select`, { [`${baseClass}__select--error`]: error, [`${baseClass}__select--disabled`]: disabled, }); return (