2019-07-18 08:00:54 +00:00
|
|
|
import React from 'react'
|
|
|
|
import PropTypes from 'prop-types'
|
|
|
|
import styled from 'styled-components';
|
|
|
|
import InputBlock from '../input-block'
|
|
|
|
import DropDownItem from '../drop-down-item'
|
|
|
|
import DropDown from '../drop-down'
|
2019-08-08 11:14:25 +00:00
|
|
|
import { Icons } from '../icons'
|
2019-08-02 07:35:54 +00:00
|
|
|
import { handleAnyClick } from '../../utils/event';
|
2019-07-18 08:00:54 +00:00
|
|
|
|
|
|
|
const StyledComboBox = styled.div`
|
2019-08-08 11:14:25 +00:00
|
|
|
* {
|
|
|
|
${props => !props.withBorder && `border-color: transparent !important;`}
|
|
|
|
}
|
|
|
|
|
|
|
|
${state => state.isOpen && `
|
|
|
|
.input-group-append > div {
|
|
|
|
-moz-transform: scaleY(-1);
|
|
|
|
-o-transform: scaleY(-1);
|
|
|
|
-webkit-transform: scaleY(-1);
|
|
|
|
transform: scaleY(-1);
|
2019-07-26 09:02:08 +00:00
|
|
|
}
|
2019-08-08 11:14:25 +00:00
|
|
|
`}
|
|
|
|
|
|
|
|
& > div > input {
|
|
|
|
&::placeholder {
|
|
|
|
font-family: Open Sans;
|
|
|
|
font-style: normal;
|
|
|
|
font-weight: 600;
|
|
|
|
font-size: 13px;
|
|
|
|
line-height: 20px;
|
|
|
|
${props => !props.isDisabled && `color: #333333;`}
|
|
|
|
${props => (!props.withBorder & !props.isDisabled) && `border-bottom: 1px dotted #333333;`}
|
|
|
|
opacity: 1;
|
|
|
|
|
|
|
|
-webkit-touch-callout: none;
|
|
|
|
-webkit-user-select: none;
|
|
|
|
-moz-user-select: none;
|
|
|
|
-ms-user-select: none;
|
|
|
|
user-select: none;
|
2019-07-18 08:00:54 +00:00
|
|
|
}
|
2019-08-08 11:14:25 +00:00
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const StyledIcon = styled.span`
|
|
|
|
width: 16px;
|
|
|
|
margin-left: 8px;
|
|
|
|
line-height: 14px;
|
2019-07-18 08:00:54 +00:00
|
|
|
`;
|
|
|
|
|
2019-07-24 17:43:18 +00:00
|
|
|
class ComboBox extends React.PureComponent {
|
2019-07-30 13:49:33 +00:00
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2019-07-18 08:00:54 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
this.ref = React.createRef();
|
2019-07-26 09:02:08 +00:00
|
|
|
|
2019-08-09 09:19:07 +00:00
|
|
|
const selectedItem = this.getSelected();
|
2019-08-05 15:12:25 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
this.state = {
|
|
|
|
isOpen: props.opened,
|
2019-08-09 09:19:07 +00:00
|
|
|
boxLabel: selectedItem && selectedItem.label,
|
|
|
|
boxIcon: selectedItem && selectedItem.icon,
|
2019-07-30 13:49:33 +00:00
|
|
|
options: props.options
|
|
|
|
};
|
2019-07-24 17:43:18 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
this.handleClick = this.handleClick.bind(this);
|
|
|
|
this.stopAction = this.stopAction.bind(this);
|
|
|
|
this.toggle = this.toggle.bind(this);
|
|
|
|
this.comboBoxClick = this.comboBoxClick.bind(this);
|
|
|
|
this.optionClick = this.optionClick.bind(this);
|
2019-08-02 07:35:54 +00:00
|
|
|
|
2019-08-06 07:39:33 +00:00
|
|
|
if (props.opened)
|
2019-08-02 07:35:54 +00:00
|
|
|
handleAnyClick(true, this.handleClick);
|
2019-07-30 13:49:33 +00:00
|
|
|
}
|
2019-07-18 08:00:54 +00:00
|
|
|
|
2019-08-02 07:35:54 +00:00
|
|
|
handleClick = (e) => this.state.isOpen && !this.ref.current.contains(e.target) && this.toggle(false);
|
2019-08-05 12:45:12 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
stopAction = (e) => e.preventDefault();
|
2019-08-05 12:45:12 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
toggle = (isOpen) => this.setState({ isOpen: isOpen });
|
2019-08-05 12:45:12 +00:00
|
|
|
|
|
|
|
comboBoxClick = (e) => {
|
2019-08-08 08:17:27 +00:00
|
|
|
if (this.props.isDisabled || !!e.target.closest('.input-group-prepend')) return;
|
2019-08-06 07:39:33 +00:00
|
|
|
|
|
|
|
this.setState({
|
2019-07-31 18:42:23 +00:00
|
|
|
option: this.props.option,
|
|
|
|
isOpen: !this.state.isOpen
|
|
|
|
});
|
2019-07-30 13:49:33 +00:00
|
|
|
};
|
2019-08-05 12:45:12 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
optionClick = (option) => {
|
2019-08-06 07:39:33 +00:00
|
|
|
this.setState({
|
2019-07-31 18:42:23 +00:00
|
|
|
boxLabel: option.label,
|
2019-08-08 11:14:25 +00:00
|
|
|
boxIcon: option.icon,
|
2019-07-31 18:42:23 +00:00
|
|
|
isOpen: !this.state.isOpen
|
|
|
|
});
|
2019-07-30 13:49:33 +00:00
|
|
|
this.props.onSelect && this.props.onSelect(option);
|
|
|
|
};
|
2019-07-18 08:00:54 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
componentWillUnmount() {
|
2019-08-02 07:35:54 +00:00
|
|
|
handleAnyClick(false, this.handleClick);
|
2019-07-30 13:49:33 +00:00
|
|
|
}
|
2019-07-26 09:02:08 +00:00
|
|
|
|
2019-08-09 09:19:07 +00:00
|
|
|
getSelected = () => {
|
2019-08-09 08:18:51 +00:00
|
|
|
const selectedItem = this.props.options.find(x => x.key === this.props.selectedOption)
|
|
|
|
|| this.props.options[0];
|
|
|
|
|
|
|
|
return selectedItem;
|
|
|
|
}
|
|
|
|
|
2019-08-09 09:19:07 +00:00
|
|
|
getSelectedLabel = () => {
|
|
|
|
const selectedItem = this.getSelected();
|
|
|
|
|
|
|
|
return selectedItem ? selectedItem.label : "1-1";
|
|
|
|
}
|
|
|
|
|
2019-08-02 07:35:54 +00:00
|
|
|
componentDidUpdate(prevProps, prevState) {
|
2019-07-30 13:49:33 +00:00
|
|
|
if (this.props.opened !== prevProps.opened) {
|
|
|
|
this.toggle(this.props.opened);
|
2019-07-18 08:00:54 +00:00
|
|
|
}
|
2019-08-02 07:35:54 +00:00
|
|
|
|
2019-08-06 07:39:33 +00:00
|
|
|
if (this.state.isOpen !== prevState.isOpen) {
|
2019-08-02 07:35:54 +00:00
|
|
|
handleAnyClick(this.state.isOpen, this.handleClick);
|
|
|
|
}
|
2019-08-05 15:12:25 +00:00
|
|
|
|
2019-08-09 08:18:51 +00:00
|
|
|
if (this.props.options.length !== prevProps.options.length) { //TODO: Move options from state
|
2019-08-09 09:19:07 +00:00
|
|
|
const label = this.getSelectedLabel();
|
2019-08-09 08:18:51 +00:00
|
|
|
this.setState({
|
|
|
|
options: this.props.options,
|
|
|
|
boxLabel: label
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-08-06 07:39:33 +00:00
|
|
|
if (this.props.selectedOption !== prevProps.selectedOption) {
|
2019-08-09 09:19:07 +00:00
|
|
|
const label = this.getSelectedLabel();
|
2019-08-06 07:39:33 +00:00
|
|
|
this.setState({ boxLabel: label });
|
2019-08-05 15:12:25 +00:00
|
|
|
}
|
2019-07-30 13:49:33 +00:00
|
|
|
}
|
2019-07-18 08:00:54 +00:00
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
render() {
|
2019-08-02 07:35:54 +00:00
|
|
|
console.log("ComboBox render");
|
2019-08-09 07:57:12 +00:00
|
|
|
|
|
|
|
const dropDownMaxHeightProp = this.props.dropDownMaxHeight ? { maxHeight: this.props.dropDownMaxHeight } : {}
|
|
|
|
|
2019-07-30 13:49:33 +00:00
|
|
|
return (
|
2019-08-08 11:14:25 +00:00
|
|
|
<StyledComboBox ref={this.ref}
|
|
|
|
{...this.props}
|
|
|
|
{...this.state}
|
|
|
|
data={this.state.boxLabel}
|
|
|
|
onClick={this.comboBoxClick}
|
|
|
|
onSelect={this.stopAction}
|
|
|
|
>
|
2019-07-30 13:49:33 +00:00
|
|
|
<InputBlock placeholder={this.state.boxLabel}
|
|
|
|
iconName='ExpanderDownIcon'
|
|
|
|
iconSize={8}
|
|
|
|
isIconFill={true}
|
|
|
|
iconColor='#A3A9AE'
|
|
|
|
scale={true}
|
|
|
|
isDisabled={this.props.isDisabled}
|
|
|
|
isReadOnly={true}
|
|
|
|
>
|
2019-08-08 11:14:25 +00:00
|
|
|
{this.state.boxIcon &&
|
|
|
|
<StyledIcon>
|
|
|
|
{React.createElement(Icons[this.state.boxIcon],
|
|
|
|
{
|
|
|
|
size: "scale",
|
|
|
|
color: this.props.isDisabled ? '#D0D5DA' : '#333333',
|
|
|
|
isfill: true
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</StyledIcon>}
|
2019-07-30 13:49:33 +00:00
|
|
|
{this.props.children}
|
|
|
|
<DropDown
|
|
|
|
directionX={this.props.directionX}
|
|
|
|
directionY={this.props.directionY}
|
|
|
|
manualWidth='100%'
|
|
|
|
manualY='102%'
|
|
|
|
isOpen={this.state.isOpen}
|
2019-08-09 07:57:12 +00:00
|
|
|
{...dropDownMaxHeightProp}
|
2019-07-30 13:49:33 +00:00
|
|
|
>
|
|
|
|
{this.state.options.map((option) =>
|
|
|
|
<DropDownItem {...option}
|
|
|
|
disabled={option.label === this.state.boxLabel}
|
2019-07-31 18:42:23 +00:00
|
|
|
onClick={this.optionClick.bind(this, option)}
|
2019-07-30 13:49:33 +00:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</DropDown>
|
|
|
|
</InputBlock>
|
|
|
|
</StyledComboBox>
|
|
|
|
);
|
|
|
|
}
|
2019-07-18 08:00:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
ComboBox.propTypes = {
|
2019-07-30 13:49:33 +00:00
|
|
|
isDisabled: PropTypes.bool,
|
|
|
|
withBorder: PropTypes.bool,
|
2019-08-06 07:39:33 +00:00
|
|
|
selectedOption: PropTypes.oneOfType([
|
|
|
|
PropTypes.string,
|
|
|
|
PropTypes.number
|
|
|
|
]),
|
2019-07-30 13:49:33 +00:00
|
|
|
options: PropTypes.array,
|
2019-08-09 07:57:12 +00:00
|
|
|
onSelect: PropTypes.func,
|
|
|
|
dropDownMaxHeight: PropTypes.string
|
2019-07-18 08:00:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ComboBox.defaultProps = {
|
2019-07-30 13:49:33 +00:00
|
|
|
isDisabled: false,
|
2019-08-09 07:57:12 +00:00
|
|
|
withBorder: true,
|
|
|
|
dropDownMaxHeight: null
|
2019-07-18 08:00:54 +00:00
|
|
|
}
|
2019-07-26 09:02:08 +00:00
|
|
|
|
2019-07-18 08:00:54 +00:00
|
|
|
export default ComboBox;
|