react-toolbox/components/dropdown/index.jsx

130 lines
3.4 KiB
React
Raw Normal View History

import React from 'react';
2015-10-21 09:13:24 +03:00
import autobind from 'autobind-decorator'
import ReactDOM from 'react-dom';
2015-09-19 18:42:57 +03:00
import Ripple from '../ripple';
2015-10-09 16:55:00 +03:00
import style from './style';
2015-09-19 18:42:57 +03:00
function _selectValue (value, dataSource) {
let item;
if (value) {
for (item of dataSource) {
if (item.value.toString() === value.toString()) break;
}
return item;
} else {
return dataSource[0];
}
}
2015-10-21 09:13:24 +03:00
@autobind
export default class Dropdown extends React.Component {
static propTypes = {
2015-09-19 18:42:57 +03:00
className: React.PropTypes.string,
dataSource: React.PropTypes.array,
disabled: React.PropTypes.bool,
label: React.PropTypes.string,
onChange: React.PropTypes.func,
template: React.PropTypes.func,
value: React.PropTypes.string
};
static defaultProps = {
className: '',
dataSource: [],
up: false
};
state = {
active: false,
selected: _selectValue(this.props.value, this.props.dataSource),
width: undefined
};
2015-09-19 18:42:57 +03:00
componentDidMount () {
this.setState({
width: ReactDOM.findDOMNode(this).getBoundingClientRect().width
2015-09-19 18:42:57 +03:00
});
}
2015-09-19 18:42:57 +03:00
componentDidUpdate (prev_props, prev_state) {
if (this.props.onChange && prev_state.selected !== this.state.selected && prev_state.active) {
this.props.onChange(this);
}
}
2015-09-19 18:42:57 +03:00
2015-10-09 16:55:00 +03:00
handleClick (event) {
let client = event.target.getBoundingClientRect();
let screen_height = window.innerHeight || document.documentElement.offsetHeight;
this.setState({
active: true,
up: client.top > ((screen_height / 2) + client.height)
});
}
2015-09-19 18:42:57 +03:00
2015-10-09 16:55:00 +03:00
handleClickValue (id) {
2015-09-19 18:42:57 +03:00
if (!this.props.disabled) {
let value = id.toString();
for (let item of this.props.dataSource) {
if (item.value.toString() === value) {
this.setState({
active: false,
selected: item
});
break;
}
}
}
}
2015-09-19 18:42:57 +03:00
2015-10-09 16:55:00 +03:00
renderValues () {
let items = this.props.dataSource.map((item, index) => {
let className;
if (item.value === this.state.selected.value) className = ` ${style.selected}`;
2015-09-19 18:42:57 +03:00
return (
<li
key={index}
2015-10-09 16:55:00 +03:00
className={className}
2015-09-19 18:42:57 +03:00
id={item.value}
2015-10-09 16:55:00 +03:00
onClick={this.handleClickValue.bind(this, item.value)}
2015-09-19 18:42:57 +03:00
>
{ this.props.template ? this.props.template(item) : item.label }
<Ripple className={style.ripple}/>
</li>
);
});
2015-10-09 16:55:00 +03:00
let className = style.values;
if (this.state.up) className += ` ${style.up}`;
let valuesStyle = {width: this.state.width};
return <ul ref='values' className={className} style={valuesStyle}>{ items }</ul>;
}
2015-10-09 16:55:00 +03:00
render () {
let className = style.root;
if (this.props.className) className += ` ${this.props.className}`;
2015-10-09 16:55:00 +03:00
if (this.props.disabled) className += ` ${style.disabled}`;
if (this.state.active) className += ` ${style.active}`;
2015-09-19 18:42:57 +03:00
return (
<div data-react-toolbox='dropdown' className={className}>
2015-10-09 16:55:00 +03:00
{this.props.label ? <label className={style.label}>{this.props.label}</label> : null}
{ this.renderValues() }
<div ref='value' className={style.value} onClick={this.handleClick}>
2015-09-19 18:42:57 +03:00
{ this.props.template ? this.props.template(this.state.selected) : <span>{this.state.selected.label}</span> }
</div>
</div>
);
}
2015-09-19 18:42:57 +03:00
getValue () {
return this.state.selected.value;
}
2015-09-19 18:42:57 +03:00
setValue (data) {
this.setState({selected: data});
}
};