thinkful-ui
Version:
Shared navigation and UI resources for Thinkful.
107 lines (88 loc) • 2.6 kB
JSX
const React = require('react');
const cx = require('classnames');
require('./dropdown.less');
/**
* Shared dropdown menu element
* @property data {Array} of items to display in the dropdown,
containing `value` and `displayName`
* @property selectedInd {Int} of the selected index in the list
* @property defaultDisplay {String} of default value that should be displayed
* @property handleChange {Function} to handle dropdown click/change
*/
const Dropdown = React.createClass({
propTypes: {
data: React.PropTypes.array.isRequired,
initialSelectedInd: React.PropTypes.number,
selectedInd: React.PropTypes.number,
defaultDisplay: React.PropTypes.string,
handleChange: React.PropTypes.func.isRequired
},
getInitialState() {
return {open: false};
},
getDefaultProps() {
return {data: []};
},
componentDidMount() {
document.addEventListener('click', this._checkClickAway);
},
componentWillUnmount() {
document.removeEventListener('click', this._checkClickAway);
},
_checkClickAway(e) {
if (!e.target.hasAttribute('data-clickable')) {
this.setState({open: false});
}
},
_generateNodes() {
const {data} = this.props;
return data.map((item, ind) => {
return (
<p
className={cx("dropdown-item", item.className)}
id={ind}
key={ind}
value={item.value}>
{item.displayName}
</p>
);
});
},
_toggleOpen() {
this.setState({open: !this.state.open});
},
_handleChange(event) {
let {handleChange} = this.props;
this._toggleOpen();
handleChange(event);
},
componentClickAway() {
this.setState({open: false});
},
render() {
let {
initialSelectedInd, selectedInd, data,
defaultDisplay, className} = this.props;
selectedInd = selectedInd === undefined ? initialSelectedInd : selectedInd;
const dropdownClasses = cx(
'dd-open',
{'hidden': !this.state.open});
return (
<div className={cx("dropdown-container", className)}>
<div
className="button dd-button"
onClick={this._toggleOpen}
data-clickable>
<span className="dropdown-text">{data[selectedInd] && data[selectedInd].displayName || defaultDisplay}</span>
<span className="icon-navigatedown" aria-hidden="true"></span>
</div>
<div
className={dropdownClasses}
onClick={this._handleChange}>
{this._generateNodes()}
</div>
</div>
);
}
});
module.exports = Dropdown;