2019-10-31 08:36:04 +00:00
|
|
|
import React, { Component } from "react";
|
|
|
|
|
import styled from "styled-components";
|
|
|
|
|
import { MenuItem, Menu, ControlGroup, InputGroup } from "@blueprintjs/core";
|
2019-11-05 05:09:50 +00:00
|
|
|
import { BaseButton } from "../designSystems/blueprint/ButtonComponent";
|
2019-10-31 08:36:04 +00:00
|
|
|
import {
|
|
|
|
|
ItemRenderer,
|
|
|
|
|
Select,
|
|
|
|
|
ItemListRenderer,
|
|
|
|
|
IItemListRendererProps,
|
|
|
|
|
} from "@blueprintjs/select";
|
2019-11-05 05:09:50 +00:00
|
|
|
import { DropdownOption } from "../../widgets/DropdownWidget";
|
2019-10-31 08:36:04 +00:00
|
|
|
|
|
|
|
|
const Dropdown = Select.ofType<DropdownOption>();
|
|
|
|
|
const StyledDropdown = styled(Dropdown)``;
|
|
|
|
|
|
|
|
|
|
class DropdownComponent extends Component<DropdownComponentProps> {
|
|
|
|
|
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<DropdownOption> = (
|
|
|
|
|
props: IItemListRendererProps<DropdownOption>,
|
|
|
|
|
) => {
|
|
|
|
|
if (this.props.addItem) {
|
|
|
|
|
const renderItems = props.items.map(props.renderItem).filter(Boolean);
|
|
|
|
|
const displayMode = (
|
|
|
|
|
<BaseButton
|
|
|
|
|
icon-right="plus"
|
|
|
|
|
styleName="primary"
|
|
|
|
|
filled={true}
|
|
|
|
|
text={this.props.addItem.displayText}
|
|
|
|
|
onClick={this.showTextBox}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
const editMode = (
|
|
|
|
|
<ControlGroup fill={true}>
|
|
|
|
|
<InputGroup inputRef={this.setNewItemTextInput} />
|
|
|
|
|
<BaseButton
|
|
|
|
|
filled={true}
|
|
|
|
|
text={this.props.addItem.displayText}
|
|
|
|
|
onClick={this.handleAddItem}
|
|
|
|
|
></BaseButton>
|
|
|
|
|
</ControlGroup>
|
|
|
|
|
);
|
|
|
|
|
return (
|
|
|
|
|
<Menu ulRef={props.itemsParentRef}>
|
|
|
|
|
{renderItems}
|
|
|
|
|
{!this.state.isEditing ? displayMode : editMode}
|
|
|
|
|
</Menu>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return <React.Fragment />;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
searchItem = (query: string, option: DropdownOption): boolean => {
|
|
|
|
|
return (
|
|
|
|
|
option.label.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
|
|
|
|
|
option.value.toLowerCase().indexOf(query.toLowerCase()) > -1 ||
|
2019-11-05 05:09:50 +00:00
|
|
|
(!!option.label &&
|
|
|
|
|
option.label.toLowerCase().indexOf(query.toLowerCase()) > -1)
|
2019-10-31 08:36:04 +00:00
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
onItemSelect = (item: DropdownOption): void => {
|
|
|
|
|
this.props.selectHandler(item.value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
renderItem: ItemRenderer<DropdownOption> = (
|
|
|
|
|
option: DropdownOption,
|
|
|
|
|
{ handleClick, modifiers },
|
|
|
|
|
) => {
|
|
|
|
|
if (!modifiers.matchesPredicate) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<MenuItem
|
|
|
|
|
active={modifiers.active}
|
|
|
|
|
key={option.value}
|
2019-11-05 05:09:50 +00:00
|
|
|
label={option.label ? option.label : ""}
|
2019-10-31 08:36:04 +00:00
|
|
|
onClick={handleClick}
|
|
|
|
|
shouldDismissPopover={false}
|
2019-11-05 05:09:50 +00:00
|
|
|
text={option.label || option.label}
|
2019-10-31 08:36:04 +00:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
getSelectedDisplayText = () => {
|
|
|
|
|
if (this.props.selected) {
|
|
|
|
|
const selectedValue = this.props.selected.value;
|
|
|
|
|
const item: DropdownOption | undefined = this.props.options.find(
|
|
|
|
|
option => option.value === selectedValue,
|
|
|
|
|
);
|
|
|
|
|
|
2019-11-05 05:09:50 +00:00
|
|
|
return item && (item.label || item.label);
|
2019-10-31 08:36:04 +00:00
|
|
|
}
|
|
|
|
|
return "";
|
|
|
|
|
};
|
|
|
|
|
render() {
|
|
|
|
|
return (
|
|
|
|
|
<StyledDropdown
|
|
|
|
|
items={this.props.options}
|
|
|
|
|
onItemSelect={this.onItemSelect}
|
|
|
|
|
itemRenderer={this.renderItem}
|
|
|
|
|
itemListRenderer={this.props.addItem && this.renderItemList}
|
|
|
|
|
filterable={!!this.props.autocomplete}
|
|
|
|
|
itemPredicate={this.searchItem}
|
|
|
|
|
itemsEqual="value"
|
|
|
|
|
popoverProps={{ minimal: true }}
|
|
|
|
|
activeItem={this.props.selected}
|
|
|
|
|
noResults={<MenuItem disabled={true} text="No results." />}
|
|
|
|
|
>
|
|
|
|
|
<BaseButton
|
|
|
|
|
styleName="secondary"
|
|
|
|
|
text={this.getSelectedDisplayText()}
|
|
|
|
|
rightIcon="chevron-down"
|
|
|
|
|
/>
|
|
|
|
|
</StyledDropdown>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface DropdownComponentProps {
|
|
|
|
|
options: DropdownOption[];
|
|
|
|
|
selectHandler: (selectedValue: string) => void;
|
|
|
|
|
selected?: DropdownOption;
|
|
|
|
|
multiselectDisplayType?: "TAGS" | "CHECKBOXES";
|
|
|
|
|
checked?: boolean;
|
|
|
|
|
multi?: boolean;
|
|
|
|
|
autocomplete?: boolean;
|
|
|
|
|
addItem?: {
|
|
|
|
|
displayText: string;
|
|
|
|
|
addItemHandler: (name: string) => void;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default DropdownComponent;
|