UNPKG

elemental

Version:
145 lines (135 loc) 4.58 kB
'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var React = require('react'); var Transition = require('react-addons-css-transition-group'); var blacklist = require('blacklist'); var classNames = require('classnames'); var Button = require('./Button'); var ESC_KEYCODE = 27; var NO_OP = function NO_OP() { return undefined; }; module.exports = React.createClass({ displayName: 'Dropdown', propTypes: { alignRight: React.PropTypes.bool, buttonHasDisclosureArrow: React.PropTypes.bool, buttonLabel: React.PropTypes.string, buttonType: React.PropTypes.string, children: React.PropTypes.element, className: React.PropTypes.string, isOpen: React.PropTypes.bool, items: React.PropTypes.array.isRequired, onSelect: React.PropTypes.func }, getDefaultProps: function getDefaultProps() { return { buttonHasDisclosureArrow: true, onSelect: NO_OP }; }, getInitialState: function getInitialState() { return { isOpen: this.props.isOpen || false }; }, componentWillUpdate: function componentWillUpdate(nextProps, nextState) { if (typeof window === 'undefined') return; if (nextState.isOpen) { window.addEventListener('keydown', this.handleKeyDown); } else { window.removeEventListener('keydown', this.handleKeyDown); } }, openDropdown: function openDropdown() { this.setState({ isOpen: true }); }, closeDropdown: function closeDropdown() { this.setState({ isOpen: false }); }, handleKeyDown: function handleKeyDown(e) { if (e.keyCode === ESC_KEYCODE) { this.closeDropdown(); } }, renderChildren: function renderChildren() { var _this = this; return React.Children.map(this.props.children, function (child) { return React.cloneElement(child, { onClick: _this.state.isOpen ? _this.closeDropdown : _this.openDropdown, className: classNames(child.props.className, 'Dropdown-toggle') }); }); }, renderButton: function renderButton() { var disclosureArrow = this.props.buttonHasDisclosureArrow ? React.createElement('span', { className: 'disclosure-arrow' }) : null; return React.createElement( Button, { type: this.props.buttonType, onClick: this.state.isOpen ? this.closeDropdown : this.openDropdown, className: 'Dropdown-toggle' }, this.props.buttonLabel, disclosureArrow ); }, onClick: function onClick(selectedItem) { this.setState({ isOpen: !this.state.isOpen }); this.props.onSelect(selectedItem); }, renderDropdownMenu: function renderDropdownMenu() { var self = this; if (!this.state.isOpen) return null; var dropdownMenuItems = this.props.items.map(function (item, i) { var menuItem; if (item.type === 'header') { menuItem = React.createElement( 'li', { key: 'item-' + i, className: 'Dropdown-menu__header' }, item.label ); } else if (item.type === 'divider') { menuItem = React.createElement('li', { key: 'item-' + i, className: 'Dropdown-menu__divider' }); } else { menuItem = React.createElement( 'li', { key: 'item-' + i, className: 'Dropdown-menu__item' }, React.createElement( 'span', { className: 'Dropdown-menu__action', onClick: self.onClick.bind(self, item.value) }, item.label ) ); } return menuItem; }); return React.createElement( 'ul', { key: 'Dropdown-menu', className: 'Dropdown-menu', role: 'menu' }, dropdownMenuItems ); }, renderDropdownMenuBackground: function renderDropdownMenuBackground() { if (!this.state.isOpen) return null; return React.createElement('div', { className: 'Dropdown-menu-backdrop', onClick: this.closeDropdown }); }, render: function render() { // classes var dropdownClass = classNames('Dropdown', { 'is-open': this.state.isOpen, 'align-right': this.props.alignRight }, this.props.className); // props var props = blacklist(this.props, 'alignRight', 'buttonHasDisclosureArrow', 'buttonLabel', 'buttonType', 'className', 'isOpen', 'items'); return React.createElement( 'span', _extends({ className: dropdownClass }, props), React.Children.count(this.props.children) ? this.renderChildren() : this.renderButton(), React.createElement( Transition, { transitionName: 'Dropdown-menu', transitionEnterTimeout: 100, transitionLeaveTimeout: 100 }, this.renderDropdownMenu() ), this.renderDropdownMenuBackground() ); } });