'use strict';

Object.defineProperty(exports, "__esModule", {
	value: true
});

var _taggedTemplateLiteral2 = require('babel-runtime/helpers/taggedTemplateLiteral');

var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2);

var _extends2 = require('babel-runtime/helpers/extends');

var _extends3 = _interopRequireDefault(_extends2);

var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');

var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);

var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');

var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);

var _createClass2 = require('babel-runtime/helpers/createClass');

var _createClass3 = _interopRequireDefault(_createClass2);

var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');

var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);

var _inherits2 = require('babel-runtime/helpers/inherits');

var _inherits3 = _interopRequireDefault(_inherits2);

var _templateObject = (0, _taggedTemplateLiteral3.default)(['\n\twrapper\n\t\tdisplay        : inline-block\n\t\tvertical-align : bottom\n\n\tcontainer\n\t\tposition   : relative\n\t\ttext-align : inherit\n\n\t\t-webkit-user-select : none\n\t\t-moz-user-select    : none\n\t\t-ms-user-select     : none\n\t\tuser-select         : none\n\n\tarrow\n\t\tdisplay  : inline-block\n\n\tlist\n\t\tposition        : absolute\n\t\tz-index         : 1\n\t\tmargin          : 0\n\t\tpadding         : 0\n\t\tlist-style-type : none\n\t\toverflow-x      : hidden\n\n\t\t&downward\n\t\t\t// when html page is overflown by a long list\n\t\t\t// this bottom margin takes effect\n\t\t\tmargin-bottom : 1em\n\n\t\t&upward\n\t\t\tbottom: 100%\n\n\t\t\t// when html page is overflown by a long list\n\t\t\t// this top margin takes effect\n\t\t\tmargin-top : 1em\n\n\tlist_item\n\t\tdisplay     : inline-block\n\t\twhite-space : nowrap\n\n\tmenu_toggler\n\t\tdisplay : inline-block\n\n\tseparator\n\t\tpadding     : 0\n\t\tline-height : 0\n\t\tfont-size   : 0\n'], ['\n\twrapper\n\t\tdisplay        : inline-block\n\t\tvertical-align : bottom\n\n\tcontainer\n\t\tposition   : relative\n\t\ttext-align : inherit\n\n\t\t-webkit-user-select : none\n\t\t-moz-user-select    : none\n\t\t-ms-user-select     : none\n\t\tuser-select         : none\n\n\tarrow\n\t\tdisplay  : inline-block\n\n\tlist\n\t\tposition        : absolute\n\t\tz-index         : 1\n\t\tmargin          : 0\n\t\tpadding         : 0\n\t\tlist-style-type : none\n\t\toverflow-x      : hidden\n\n\t\t&downward\n\t\t\t// when html page is overflown by a long list\n\t\t\t// this bottom margin takes effect\n\t\t\tmargin-bottom : 1em\n\n\t\t&upward\n\t\t\tbottom: 100%\n\n\t\t\t// when html page is overflown by a long list\n\t\t\t// this top margin takes effect\n\t\t\tmargin-top : 1em\n\n\tlist_item\n\t\tdisplay     : inline-block\n\t\twhite-space : nowrap\n\n\tmenu_toggler\n\t\tdisplay : inline-block\n\n\tseparator\n\t\tpadding     : 0\n\t\tline-height : 0\n\t\tfont-size   : 0\n']); // https://github.com/halt-hammerzeit/react-responsive-ui/blob/master/source/select.js

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactDom = require('react-dom');

var _reactDom2 = _interopRequireDefault(_reactDom);

var _flat = require('react-styling/flat');

var _flat2 = _interopRequireDefault(_flat);

var _classnames = require('classnames');

var _classnames2 = _interopRequireDefault(_classnames);

var _dom = require('./misc/dom');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// Possible enhancements:
//
//  * If the menu is close to a screen edge,
//    automatically reposition it so that it fits on the screen
//  * Maybe show menu immediately above the toggler
//    (like in Material design), not below it.
//
// https://material.google.com/components/menus.html

var Select = function (_Component) {
	(0, _inherits3.default)(Select, _Component);

	function Select(props, context) {
		(0, _classCallCheck3.default)(this, Select);

		// Shouldn't memory leak because
		// the set of options is assumed to be constant.
		var _this = (0, _possibleConstructorReturn3.default)(this, (Select.__proto__ || (0, _getPrototypeOf2.default)(Select)).call(this, props, context));

		_this.state = {};
		_this.options = {};

		_this.toggle = _this.toggle.bind(_this);
		_this.document_clicked = _this.document_clicked.bind(_this);
		_this.on_key_down = _this.on_key_down.bind(_this);

		_this.on_autocomplete_input_change = _this.on_autocomplete_input_change.bind(_this);
		_this.on_key_down_in_container = _this.on_key_down_in_container.bind(_this);

		if (props.autocomplete) {
			if (!props.options) {
				throw new Error('"options" property is required for an "autocomplete" select');
			}

			_this.state.filtered_options = props.options;
		}

		if (props.children && !props.menu) {
			_react2.default.Children.forEach(props.children, function (element) {
				if (!element.props.value) {
					throw new Error('You must specify "value" prop on each child of <Select/>');
				}

				if (!element.props.label) {
					throw new Error('You must specify "label" prop on each child of <Select/>');
				}
			});
		}

		if (props.menu && !props.toggler) {
			throw new Error('Supply a "toggler" component when enabling "menu" in <Select/>');
		}

		if (!props.menu && !props.onChange) {
			throw new Error('"onChange" property must be specified for <Select/>');
		}
		return _this;
	}

	// Client side rendering, javascript is enabled


	(0, _createClass3.default)(Select, [{
		key: 'componentDidMount',
		value: function componentDidMount() {
			document.addEventListener('click', this.document_clicked);

			this.setState({ javascript: true });
		}
	}, {
		key: 'componentDidUpdate',
		value: function componentDidUpdate(previous_props, previous_state) {
			if (this.state.expanded !== previous_state.expanded) {
				if (this.state.expanded && this.should_animate()) {
					if (this.state.height === undefined) {
						this.calculate_height();
					}
				}
			}
		}
	}, {
		key: 'componentWillUnmount',
		value: function componentWillUnmount() {
			document.removeEventListener('click', this.document_clicked);
		}
	}, {
		key: 'render',
		value: function render() {
			var _this2 = this;

			var _props = this.props;
			var upward = _props.upward;
			var scroll = _props.scroll;
			var children = _props.children;
			var menu = _props.menu;
			var toggler = _props.toggler;
			var alignment = _props.alignment;
			var autocomplete = _props.autocomplete;
			var saveOnIcons = _props.saveOnIcons;
			var filtered_options = this.state.filtered_options;

			var options = autocomplete ? filtered_options : this.props.options;

			var list_style = upward ? style.list_upward : style.list_downward;

			// Will be altered
			list_style = (0, _extends3.default)({}, list_style);

			switch (alignment) {
				case 'left':
					list_style.left = 0;
					break;

				case 'right':
					list_style.right = 0;
					break;

				default:
					throw new Error('Unsupported alignment: "' + alignment + '"');
			}

			if (!menu && scroll && this.state.list_height !== undefined) {
				list_style.maxHeight = this.state.list_height + 'px';
			}

			var overflow = scroll && options && this.overflown();

			var list_items = void 0;

			// If a list of options is supplied as an array of `{ value, label }`,
			// then transform those elements to <buttons/>
			if (options) {
				list_items = options.map(function (_ref, index) {
					var value = _ref.value;
					var label = _ref.label;
					var icon = _ref.icon;

					return _this2.render_list_item({ value: value, label: label, icon: !saveOnIcons && icon, overflow: overflow });
				});
			}
			// Else, if a list of options is supplied as a set of child React elements,
			// then render those elements.
			else {
					list_items = _react2.default.Children.map(children, function (element) {
						return _this2.render_list_item({ element: element });
					});
				}

			var wrapper_style = (0, _extends3.default)({}, style.wrapper, { textAlign: alignment });

			var markup = _react2.default.createElement(
				'div',
				{
					ref: function ref(_ref4) {
						return _this2.select = _ref4;
					},
					onKeyDown: this.on_key_down_in_container,
					style: this.props.style ? (0, _extends3.default)({}, wrapper_style, this.props.style) : wrapper_style,
					className: (0, _classnames2.default)('rrui__rich', 'rrui__select', {
						'rrui__select--upward': upward,
						'rrui__select--expanded': this.state.expanded,
						'rrui__select--collapsed': !this.state.expanded
					}) },
				_react2.default.createElement(
					'div',
					{ style: style.container },
					!menu && this.render_selected_item(),
					menu && _react2.default.createElement(
						'div',
						{ ref: function ref(_ref2) {
								return _this2.menu_toggler;
							}, style: style.menu_toggler },
						_react2.default.cloneElement(toggler, { onClick: this.toggle })
					),
					_react2.default.createElement(
						'ul',
						{
							ref: function ref(_ref3) {
								return _this2.list = _ref3;
							},
							style: list_style,
							className: (0, _classnames2.default)('rrui__select__options', {
								'rrui__select__options--expanded': this.state.expanded,
								'rrui__select__options--simple-left-aligned': !children && alignment === 'left',
								'rrui__select__options--simple-right-aligned': !children && alignment === 'right'
							}) },
						list_items
					)
				),
				!this.state.javascript && this.render_static()
			);

			return markup;
		}
	}, {
		key: 'render_list_item',
		value: function render_list_item(_ref5) // , first, last
		{
			var _this3 = this;

			var element = _ref5.element;
			var value = _ref5.value;
			var label = _ref5.label;
			var icon = _ref5.icon;
			var overflow = _ref5.overflow;
			var _props2 = this.props;
			var disabled = _props2.disabled;
			var menu = _props2.menu;
			var scrollbarPadding = _props2.scrollbarPadding;
			var focused_option_value = this.state.focused_option_value;

			// If a list of options is supplied as a set of child React elements,
			// then extract values from their props.

			if (element) {
				value = element.props.value;
			}

			var is_focused = value !== undefined && value === focused_option_value;

			var list_item_style = { textAlign: 'left' };

			var item_style = style.list_item;

			// on overflow the vertical scrollbar will take up space
			// reducing padding-right and the only way to fix that
			// is to add additional padding-right
			//
			// a hack to restore padding-right taken up by a vertical scrollbar
			if (overflow && scrollbarPadding) {
				item_style = (0, _extends3.default)({}, style.list.item);

				item_style.marginRight = (0, _dom.get_scrollbar_width)() + 'px';
			}

			var button = void 0;

			// If a list of options is supplied as a set of child React elements,
			// then enhance those elements with extra props.
			if (element) {
				(function () {
					var extra_props = {
						style: (0, _extends3.default)({}, item_style, element.props.style),
						className: (0, _classnames2.default)('rrui__select__option', {
							'rrui__select__option--focused': is_focused
						}, element.props.className)
					};

					var onClick = element.props.onClick;

					extra_props.onClick = function (event) {
						if (menu) {
							_this3.toggle();
						} else {
							_this3.item_clicked(value, event);
						}

						if (onClick) {
							onClick(event);
						}
					};

					button = _react2.default.cloneElement(element, extra_props);
				})();
			}
			// Else, if a list of options is supplied as an array of `{ value, label }`,
			// then transform those options to <buttons/>
			else {
					button = _react2.default.createElement(
						'button',
						{
							type: 'button',
							onClick: function onClick(event) {
								return _this3.item_clicked(value, event);
							},
							disabled: disabled,
							tabIndex: '-1',
							className: (0, _classnames2.default)('rrui__select__option', 'rrui__button__button', {
								'rrui__select__option--focused': is_focused
							}),
							style: item_style },
						icon && _react2.default.cloneElement(icon, { className: (0, _classnames2.default)(icon.props.className, 'rrui__select__option-icon') }),
						label
					);
				}

			var markup = _react2.default.createElement(
				'li',
				{
					key: value,
					ref: function ref(_ref6) {
						return _this3.options[value] = _ref6;
					},
					className: (0, _classnames2.default)({
						'rrui__select__separator-option': element && element.type === Select.Separator
					}),
					style: list_item_style },
				button
			);

			return markup;
		}
	}, {
		key: 'render_selected_item',
		value: function render_selected_item() {
			var _this4 = this;

			var _props3 = this.props;
			var options = _props3.options;
			var children = _props3.children;
			var value = _props3.value;
			var label = _props3.label;
			var disabled = _props3.disabled;
			var autocomplete = _props3.autocomplete;
			var concise = _props3.concise;
			var _state = this.state;
			var expanded = _state.expanded;
			var autocomplete_width = _state.autocomplete_width;
			var autocomplete_input_value = _state.autocomplete_input_value;


			var selected_label = this.get_selected_option_label();

			if (autocomplete && expanded) {
				var _markup = _react2.default.createElement('input', {
					type: 'text',
					ref: function ref(_ref7) {
						return _this4.autocomplete = _ref7;
					},
					placeholder: selected_label || label,
					value: autocomplete_input_value,
					onChange: this.on_autocomplete_input_change,
					onKeyDown: this.on_key_down,
					style: { width: autocomplete_width + 'px' },
					className: (0, _classnames2.default)('rrui__select__selected', 'rrui__select__selected--autocomplete', {
						'rrui__select__selected--nothing': !selected_label
					}) });

				return _markup;
			}

			var selected = this.get_selected_option();

			var markup = _react2.default.createElement(
				'button',
				{
					ref: function ref(_ref8) {
						return _this4.selected = _ref8;
					},
					type: 'button',
					disabled: disabled,
					onClick: this.toggle,
					onKeyDown: this.on_key_down,
					className: (0, _classnames2.default)('rrui__select__selected', 'rrui__button__button', {
						'rrui__select__selected--nothing': !selected_label
					}) },
				concise && selected && selected.icon ? selected.icon : selected_label || label,
				_react2.default.createElement('div', {
					className: (0, _classnames2.default)('rrui__select__arrow', {
						'rrui__select__arrow--expanded': expanded
					}),
					style: style.arrow })
			);

			return markup;
		}

		// supports disabled javascript

	}, {
		key: 'render_static',
		value: function render_static() {
			var _props4 = this.props;
			var name = _props4.name;
			var value = _props4.value;
			var label = _props4.label;
			var disabled = _props4.disabled;
			var options = _props4.options;
			var menu = _props4.menu;
			var toggler = _props4.toggler;
			var children = _props4.children;


			if (menu) {
				return _react2.default.createElement(
					'div',
					{ className: 'rrui__rich__fallback' },
					toggler
				);
			}

			var markup = _react2.default.createElement(
				'div',
				{ className: 'rrui__rich__fallback' },
				_react2.default.createElement(
					'select',
					{
						name: name,
						value: value === null ? undefined : value,
						disabled: disabled,
						onChange: function onChange(event) {},
						style: { width: 'auto' } },
					options ? options.map(function (item) {
						return _react2.default.createElement(
							'option',
							{
								className: 'rrui__select__option',
								key: item.value,
								value: item.value },
							item.label
						);
					}) : _react2.default.Children.map(children, function (child) {
						return _react2.default.createElement(
							'option',
							{
								className: 'rrui__select__option',
								key: child.props.value,
								value: child.props.value },
							child.props.label
						);
					})
				)
			);

			return markup;
		}
	}, {
		key: 'get_selected_option',
		value: function get_selected_option() {
			return this.get_option(this.props.value);
		}
	}, {
		key: 'get_option',
		value: function get_option(value) {
			var _props5 = this.props;
			var options = _props5.options;
			var children = _props5.children;


			if (options) {
				return options.filter(function (x) {
					return x.value === value;
				})[0];
			}

			var selected = void 0;

			_react2.default.Children.forEach(children, function (child) {
				if (child.props.value === value) {
					selected = child;
				}
			});

			return selected;
		}
	}, {
		key: 'get_selected_option_label',
		value: function get_selected_option_label() {
			var options = this.props.options;


			var selected = this.get_selected_option();

			if (selected) {
				if (options) {
					return selected.label;
				}

				return selected.props.label;
			}
		}
	}, {
		key: 'overflown',
		value: function overflown() {
			return this.props.options.length > this.props.maxItems;
		}
	}, {
		key: 'scrollable_list_height',
		value: function scrollable_list_height() {
			var state = arguments.length <= 0 || arguments[0] === undefined ? this.state : arguments[0];

			return (state.height - 2 * state.vertical_padding) * (this.props.maxItems / this.props.options.length) + state.vertical_padding;
		}
	}, {
		key: 'should_animate',
		value: function should_animate() {
			return true;

			// return this.props.options.length >= this.props.transition_item_count_min
		}
	}, {
		key: 'toggle',
		value: function toggle(event) {
			var _this5 = this;

			var toggle_options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

			if (event) {
				// Don't navigate away when clicking links
				event.preventDefault();

				// Not discarding the click event because
				// other expanded selects may be listening to it.
				// // Discard the click event so that it won't reach `document` click listener
				// event.stopPropagation() // doesn't work
				// event.nativeEvent.stopImmediatePropagation()
			}

			var _props6 = this.props;
			var disabled = _props6.disabled;
			var autocomplete = _props6.autocomplete;
			var options = _props6.options;
			var value = _props6.value;
			var focusUponSelection = _props6.focusUponSelection;


			if (disabled) {
				return;
			}

			var expanded = this.state.expanded;


			if (!expanded && autocomplete) {
				this.setState({
					autocomplete_input_value: '',
					filtered_options: options
				});

				if (!this.state.autocomplete_width) {
					this.setState({ autocomplete_width: this.get_widest_label_width() });
				}
			}

			// Deferring expanding the select upon click
			// because document.onClick should finish first,
			// otherwise `event.target` may be detached from the DOM
			// and it would immediately toggle back to collapsed state.
			setTimeout(function () {
				_this5.setState({
					expanded: !expanded
				});

				if (!expanded && options) {
					// Focus either the selected option
					// or the first option in the list.

					var focused_option_value = value || options[0].value;

					_this5.setState({ focused_option_value: focused_option_value });

					// Scroll down to the focused option
					_this5.scroll_to(focused_option_value);
				}

				// If it's autocomplete, then focus <input/> field
				// upon toggling the select component.
				if (autocomplete && !toggle_options.dont_focus_after_toggle) {
					if (!expanded || expanded && focusUponSelection) {
						setTimeout(function () {
							// Focus the toggler
							if (expanded) {
								_this5.selected.focus();
							} else {
								_this5.autocomplete.focus();
							}
						}, 0);
					}
				}
			}, 0);
		}
	}, {
		key: 'item_clicked',
		value: function item_clicked(value, event) {
			if (event) {
				event.preventDefault();
			}

			var _props7 = this.props;
			var disabled = _props7.disabled;
			var onChange = _props7.onChange;
			var autocomplete = _props7.autocomplete;
			var focusUponSelection = _props7.focusUponSelection;


			if (disabled) {
				return;
			}

			// Focus the toggler
			if (focusUponSelection) {
				if (autocomplete) {
					this.autocomplete.focus();
				} else {
					this.selected.focus();
				}
			}

			onChange(value);

			this.toggle();
		}
	}, {
		key: 'document_clicked',
		value: function document_clicked(event) {
			var autocomplete = _reactDom2.default.findDOMNode(this.autocomplete);
			var selected_option = _reactDom2.default.findDOMNode(this.selected);
			var options_list = _reactDom2.default.findDOMNode(this.list);

			// Don't close the select if its expander button has been clicked,
			// or if autocomplete has been clicked,
			// or if an option was selected from the list.
			if ((0, _dom.is_reachable)(event.target, options_list) || autocomplete && (0, _dom.is_reachable)(event.target, autocomplete) || selected_option && (0, _dom.is_reachable)(event.target, selected_option)) {
				return;
			}

			this.setState({ expanded: false });
		}
	}, {
		key: 'on_key_down_in_container',
		value: function on_key_down_in_container(event) {
			if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) {
				return;
			}

			var expanded = this.state.expanded;


			switch (event.keyCode) {
				// Toggle on Tab out
				case 9:
					if (expanded) {
						this.toggle(undefined, { dont_focus_after_toggle: true });
					}
					return;
			}
		}
	}, {
		key: 'on_key_down',
		value: function on_key_down(event) {
			var _this6 = this;

			if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) {
				return;
			}

			var _props8 = this.props;
			var options = _props8.options;
			var value = _props8.value;
			var autocomplete = _props8.autocomplete;
			var _state2 = this.state;
			var expanded = _state2.expanded;
			var focused_option_value = _state2.focused_option_value;

			// Maybe add support for `children` arrow navigation in future

			if (options) {
				switch (event.keyCode) {
					// Select the previous option (if present) on up arrow
					case 38:
						event.preventDefault();

						var previous = this.previous_focusable_option_value();

						if (previous !== undefined) {
							this.show_option(previous, 'top');
							return this.setState({ focused_option_value: previous });
						}

						return;

					// Select the next option (if present) on down arrow
					case 40:
						event.preventDefault();

						var next = this.next_focusable_option_value();

						if (next !== undefined) {
							this.show_option(next, 'bottom');
							return this.setState({ focused_option_value: next });
						}

						return;

					// Collapse on Escape
					//
					// Maybe add this kind of support for "Escape" key in some future:
					//  hiding the item list, cancelling current item selection process
					//  and restoring the selection present before the item list was toggled.
					//
					case 27:
						// Collapse the list if it's expanded
						if (this.state.expanded) {
							this.toggle();

							// Restore focus when the list is collapsed
							setTimeout(function () {
								_this6.selected.focus();
							}, 0);
						}

						return;

					// on Enter
					case 13:
						// Choose the focused item on Enter
						if (expanded) {
							event.preventDefault();

							// If an item is focused
							// (which may not be a case
							//  when autocomplete is matching no items)
							if (focused_option_value) {
								// Choose the focused item
								this.item_clicked(focused_option_value);
								// And collapse the select
								this.toggle();
							}
						}
						// Else it should have just submitted the form on Enter,
						// but it wouldn't because the select element activator is a <button/>
						// therefore hitting Enter while being focused on it just pushes that button.
						// So submit the enclosing form manually.
						else {
								if ((0, _dom.submit_parent_form)(_reactDom2.default.findDOMNode(this.select))) {
									event.preventDefault();
								}
							}

						return;

					// Open on Spacebar
					case 32:
						// Choose the focused item on Enter
						if (expanded) {
							// ... only if it's not an autocomplete
							if (!autocomplete) {
								event.preventDefault();

								if (focused_option_value) {
									this.item_clicked(focused_option_value);
									this.toggle();
								}
							}
						}
						// Expand the select otherwise
						else {
								event.preventDefault();
								this.toggle();
							}

						return;
				}
			}
		}

		// Get the previous value (relative to the currently focused value)

	}, {
		key: 'previous_focusable_option_value',
		value: function previous_focusable_option_value() {
			var options = this.props.options;
			var focused_option_value = this.state.focused_option_value;


			var i = 0;
			while (i < options.length) {
				if (options[i].value === focused_option_value) {
					if (i - 1 >= 0) {
						return options[i - 1].value;
					}
				}
				i++;
			}
		}

		// Get the next value (relative to the currently focused value)

	}, {
		key: 'next_focusable_option_value',
		value: function next_focusable_option_value() {
			var options = this.props.options;
			var focused_option_value = this.state.focused_option_value;


			var i = 0;
			while (i < options.length) {
				if (options[i].value === focused_option_value) {
					if (i + 1 < options.length) {
						return options[i + 1].value;
					}
				}
				i++;
			}
		}

		// Scrolls to an option having the value

	}, {
		key: 'scroll_to',
		value: function scroll_to(value) {
			var option_element = _reactDom2.default.findDOMNode(this.options[value]);
			_reactDom2.default.findDOMNode(this.list).scrollTop = option_element.offsetTop;
		}

		// Fully shows an option (scrolls to it if neccessary)

	}, {
		key: 'show_option',
		value: function show_option(value, gravity) {
			var option_element = _reactDom2.default.findDOMNode(this.options[value]);
			var list = _reactDom2.default.findDOMNode(this.list);

			switch (gravity) {
				case 'top':
					if (option_element.offsetTop < list.scrollTop) {
						list.scrollTop = option_element.offsetTop;
					}
					return;

				case 'bottom':
					if (option_element.offsetTop + option_element.offsetHeight > list.scrollTop + list.offsetHeight) {
						list.scrollTop = option_element.offsetTop + option_element.offsetHeight - list.offsetHeight;
					}
					return;
			}
		}

		// Calculates height of the expanded item list

	}, {
		key: 'calculate_height',
		value: function calculate_height() {
			var list_dom_node = _reactDom2.default.findDOMNode(this.list);
			var border = parseInt(window.getComputedStyle(list_dom_node).borderTopWidth);
			var height = list_dom_node.scrollHeight; // + 2 * border // inner height + 2 * border

			var vertical_padding = parseInt(window.getComputedStyle(list_dom_node.firstChild).paddingTop);

			// const images = list_dom_node.querySelectorAll('img')

			// if (images.length > 0)
			// {
			// 	return this.preload_images(list_dom_node, images)
			// }

			var state = { height: height, vertical_padding: vertical_padding, border: border };

			if (!this.props.menu && this.props.scroll && this.props.options && this.overflown()) {
				state.list_height = this.scrollable_list_height(state);
			}

			this.setState(state);
		}
	}, {
		key: 'get_widest_label_width',
		value: function get_widest_label_width() {
			// <ul/> -> <li/> -> <button/>
			var label = _reactDom2.default.findDOMNode(this.list).firstChild.firstChild;

			var style = getComputedStyle(label);

			var width = parseFloat(style.width);
			var side_padding = parseFloat(style.paddingLeft);

			return width - 2 * side_padding;
		}
	}, {
		key: 'on_autocomplete_input_change',
		value: function on_autocomplete_input_change(event) {
			var input = event.target.value;

			var options = this.props.options;


			var filtered_options = options.filter(function (_ref9) {
				var value = _ref9.value;
				var label = _ref9.label;
				var verbose = _ref9.verbose;
				var icon = _ref9.icon;

				return (verbose || label).toLowerCase().indexOf(input.toLowerCase()) !== -1;
			});

			this.setState({
				autocomplete_input_value: input,
				filtered_options: filtered_options,
				focused_option_value: filtered_options.length > 0 ? filtered_options[0].value : undefined
			});
		}

		// // https://github.com/daviferreira/react-sanfona/blob/master/src/AccordionItem/index.jsx#L54
		// // Wait for images to load before calculating maxHeight
		// preload_images(node, images)
		// {
		// 	let images_loaded = 0
		//
		// 	const image_loaded = () =>
		// 	{
		// 		images_loaded++
		//
		// 		if (images_loaded === images.length)
		// 		{
		// 			this.setState
		// 			({
		// 				height: this.props.expanded ? node.scrollHeight : 0
		// 			})
		// 		}
		// 	}
		//
		// 	for (let i = 0; i < images.length; i += 1)
		// 	{
		// 		const image = new Image()
		// 		image.src = images[i].src
		// 		image.onload = image.onerror = image_loaded
		// 	}
		// }

	}]);
	return Select;
}(_react.Component);

Select.propTypes = {
	// A list of selectable options
	options: _react.PropTypes.arrayOf(_react.PropTypes.shape({
		// Option value
		value: _react2.default.PropTypes.string.isRequired,
		// Option label
		label: _react2.default.PropTypes.string.isRequired,
		// Option icon
		icon: _react2.default.PropTypes.node
	})),

	// HTML form input `name` attribute
	name: _react.PropTypes.string,

	// Default label (like "Choose")
	label: _react.PropTypes.string,

	// Show icon only for selected item,
	// and only if `concise` is `true`.
	saveOnIcons: _react.PropTypes.bool,

	// Disables this control
	disabled: _react.PropTypes.bool,

	// Selected option value
	value: _react.PropTypes.any,

	// Is called when an option is selected
	onChange: _react.PropTypes.func,

	// If this flag is set to `true`,
	// and `icon` is specified for a selected option,
	// then the selected option will be displayed
	// as icon only, without the label.
	concise: _react.PropTypes.bool,

	// If set to `true`, autocompletion is available
	// upon expanding the options list.
	autocomplete: _react.PropTypes.bool,

	// Options list alignment ("left", "right")
	alignment: _react.PropTypes.oneOf(['left', 'right']),

	// If `menu` flag is set to `true`
	// then it's gonna be a dropdown menu
	// with `children` elements inside.
	menu: _react.PropTypes.bool,

	// If `menu` flag is set to `true`
	// then `toggler` is the dropdown menu button.
	toggler: _react.PropTypes.element,

	// If `scroll` is `false`, then options list
	// is not limited in height.
	// Is `true` by default (scrollable).
	scroll: _react.PropTypes.bool.isRequired,

	// If this flag is set to `true`,
	// then the dropdown expands itself upward.
	// (as opposed to the default downward)
	upward: _react.PropTypes.bool,

	// Maximum items fitting the options list height (scrollable).
	// Is `6` by default.
	maxItems: _react.PropTypes.number.isRequired,

	// Is `true` by default (only when the list of options is scrollable)
	scrollbarPadding: _react.PropTypes.bool,

	focusUponSelection: _react.PropTypes.bool.isRequired

	// transition_item_count_min : PropTypes.number,
	// transition_duration_min : PropTypes.number,
	// transition_duration_max : PropTypes.number
};
Select.defaultProps = {
	alignment: 'left',

	scroll: true,

	maxItems: 6,

	scrollbarPadding: true,

	focusUponSelection: true

	// transition_item_count_min : 1,
	// transition_duration_min : 60, // milliseconds
	// transition_duration_max : 100 // milliseconds
};
exports.default = Select;


Select.Separator = function (props) {
	return _react2.default.createElement('div', { className: 'rrui__select__separator', style: style.separator });
};

var style = (0, _flat2.default)(_templateObject);
module.exports = exports['default'];
//# sourceMappingURL=select.js.map