import React, { Component, ReactNode } from "react"; import styled from "styled-components"; import { MenuItem, Menu, ControlGroup, InputGroup, IMenuProps, } from "@blueprintjs/core"; import { BaseButton } from "components/designSystems/blueprint/ButtonComponent"; import { ItemRenderer, Select, ItemListRenderer, IItemListRendererProps, } from "@blueprintjs/select"; import { DropdownOption } from "widgets/DropdownWidget"; import { WrappedFieldInputProps } from "redux-form"; interface ButtonWrapperProps { width?: string; } interface MenuProps { width?: string; } type MenuComponentProps = IMenuProps & MenuProps; const Dropdown = Select.ofType(); const StyledDropdown = styled(Dropdown)``; const StyledButtonWrapper = styled.div` width: ${(props) => props.width || "100%"}; `; const StyledMenu = styled(Menu)` min-width: ${(props) => props.width || "100%"}; border-radius: 0; `; const StyledMenuItem = styled(MenuItem)` border-radius: 0; &&&.bp3-active { background: ${(props) => props.theme.colors.propertyPane.activeButtonText}; } `; class DropdownComponent extends Component { componentDidMount() { const { input, options } = this.props; // set selected option to first option by default if (input && !input.value) { input.onChange(options[0].value); } } private newItemTextInput: HTMLInputElement | null = null; private setNewItemTextInput = (element: HTMLInputElement | null) => { this.newItemTextInput = element; }; public state = { isEditing: false, }; showTextBox = (): void => { this.setState({ isEditing: true, }); }; handleAddItem = (): void => { this.props.addItem && this.newItemTextInput && this.props.addItem.addItemHandler(this.newItemTextInput.value); this.setState({ isEditing: false, }); }; renderItemList: ItemListRenderer = ( props: IItemListRendererProps, ) => { const { items, renderItem } = props; const { addItem, width } = this.props; const renderItems = items.map(renderItem).filter(Boolean); const displayMode = ( ); const editMode = ( ); return ( {renderItems} {addItem && (!this.state.isEditing ? displayMode : editMode)} ); }; searchItem = (query: string, option: DropdownOption): boolean => { return ( option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 || option.value.toLowerCase().indexOf(query.toLowerCase()) > -1 || (!!option.label && option.label.toLowerCase().indexOf(query.toLowerCase()) > -1) ); }; onItemSelect = (item: DropdownOption): void => { const { input, selectHandler } = this.props; input && input.onChange(item.value); selectHandler && selectHandler(item.value); }; renderItem: ItemRenderer = ( option: DropdownOption, { handleClick, modifiers }, ) => { if (!modifiers.matchesPredicate) { return null; } return ( ); }; getDropdownOption = (value: string): DropdownOption | undefined => { return this.props.options.find((option) => option.value === value); }; getSelectedDisplayText = () => { const { input, selected } = this.props; if (input) { const item = this.getDropdownOption(input.value); return item && item.label; } if (selected) { const item = this.getDropdownOption(selected.value); return item && item.label; } return ""; }; getActiveOption = (): DropdownOption => { const { input, options, selected } = this.props; const defaultActiveOption = options[0]; if (input) { return this.getDropdownOption(input.value) || defaultActiveOption; } else { return selected || defaultActiveOption; } }; render() { const { autocomplete, input, options, width } = this.props; return ( } onItemSelect={this.onItemSelect} popoverProps={{ minimal: true }} {...input} > {this.props.toggle || ( )} ); } } export interface DropdownComponentProps { hasLabel?: boolean; options: DropdownOption[]; selectHandler?: (selectedValue: string) => void; selected?: DropdownOption; multiselectDisplayType?: "TAGS" | "CHECKBOXES"; checked?: boolean; multi?: boolean; autocomplete?: boolean; addItem?: { displayText: string; addItemHandler: (name: string) => void; }; toggle?: ReactNode; input?: WrappedFieldInputProps; width?: string; } export default DropdownComponent;