@lyra/components
Version:
Basic UX components
313 lines (269 loc) • 11 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _get2 = require('lodash/get');
var _get3 = _interopRequireDefault(_get2);
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 _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _searchableStyle = require('part:@lyra/components/selects/searchable-style');
var _searchableStyle2 = _interopRequireDefault(_searchableStyle);
var _angleDownIcon = require('part:@lyra/base/angle-down-icon');
var _angleDownIcon2 = _interopRequireDefault(_angleDownIcon);
var _default = require('part:@lyra/components/textinputs/default');
var _default2 = _interopRequireDefault(_default);
var _spinner = require('part:@lyra/components/loading/spinner');
var _spinner2 = _interopRequireDefault(_spinner);
var _closeIcon = require('part:@lyra/base/close-icon');
var _closeIcon2 = _interopRequireDefault(_closeIcon);
var _SelectMenu = require('./SelectMenu');
var _SelectMenu2 = _interopRequireDefault(_SelectMenu);
var _stacked = require('part:@lyra/components/utilities/stacked');
var _stacked2 = _interopRequireDefault(_stacked);
var _captureOutsideClicks = require('part:@lyra/components/utilities/capture-outside-clicks');
var _captureOutsideClicks2 = _interopRequireDefault(_captureOutsideClicks);
var _escapable = require('part:@lyra/components/utilities/escapable');
var _escapable2 = _interopRequireDefault(_escapable);
var _portal = require('part:@lyra/components/utilities/portal');
var _reactPopper = require('react-popper');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /* eslint-disable complexity */
const noop = () => {};
class StatelessSearchableSelect extends _react2.default.PureComponent {
constructor(...args) {
var _temp;
return _temp = super(...args), this.handleSelect = item => {
this.props.onChange(item);
}, this.handleArrowClick = () => {
var _props = this.props;
const isOpen = _props.isOpen,
onOpen = _props.onOpen;
if (isOpen) {
this.handleClose();
} else {
onOpen();
}
}, this.handleArrowKeyPress = event => {
if (event.key === 'Enter') {
this.handleArrowClick();
}
}, this.handleInputChange = event => {
this.props.onInputChange(event.target.value);
}, this.handleKeyDown = event => {
var _props2 = this.props;
const items = _props2.items,
highlightIndex = _props2.highlightIndex,
onHighlightIndexChange = _props2.onHighlightIndexChange,
isOpen = _props2.isOpen,
onOpen = _props2.onOpen;
if (event.key === 'ArrowDown' && !isOpen) {
onOpen();
}
if (!items || items.length === 0) {
return;
}
const lastIndex = items.length - 1;
if (event.key === 'ArrowUp') {
event.preventDefault();
const nextIndex = highlightIndex - 1;
onHighlightIndexChange(nextIndex < 0 ? lastIndex : nextIndex);
}
if (event.key === 'ArrowDown') {
event.preventDefault();
if (!isOpen) {
onOpen();
}
const nextIndex = highlightIndex + 1;
onHighlightIndexChange(nextIndex > lastIndex ? 0 : nextIndex);
}
}, this.handleKeyUp = event => {
var _props3 = this.props;
const items = _props3.items,
onChange = _props3.onChange,
highlightIndex = _props3.highlightIndex;
if (event.key === 'Enter' && highlightIndex > -1 && items[highlightIndex]) {
onChange(items[highlightIndex]);
}
}, this.handleClose = event => {
this.props.onClose();
}, this.setInput = input => {
this._input = input;
}, _temp;
}
focus() {
this._input.focus();
}
render() {
var _props4 = this.props;
const onClear = _props4.onClear,
placeholder = _props4.placeholder,
isLoading = _props4.isLoading,
value = _props4.value,
items = _props4.items,
renderItem = _props4.renderItem,
isOpen = _props4.isOpen,
highlightIndex = _props4.highlightIndex,
isInputSelected = _props4.isInputSelected,
inputValue = _props4.inputValue,
onChange = _props4.onChange,
onInputChange = _props4.onInputChange,
onOpen = _props4.onOpen,
onClose = _props4.onClose,
dropdownPosition = _props4.dropdownPosition,
disabled = _props4.disabled,
onHighlightIndexChange = _props4.onHighlightIndexChange,
openItemElement = _props4.openItemElement,
readOnly = _props4.readOnly,
rest = _objectWithoutProperties(_props4, ['onClear', 'placeholder', 'isLoading', 'value', 'items', 'renderItem', 'isOpen', 'highlightIndex', 'isInputSelected', 'inputValue', 'onChange', 'onInputChange', 'onOpen', 'onClose', 'dropdownPosition', 'disabled', 'onHighlightIndexChange', 'openItemElement', 'readOnly']);
return _react2.default.createElement(
_reactPopper.Manager,
null,
_react2.default.createElement(
_reactPopper.Target,
{
className: disabled ? _searchableStyle2.default.selectContainerDisabled : _searchableStyle2.default.selectContainer
},
_react2.default.createElement(_default2.default, _extends({}, rest, {
className: _searchableStyle2.default.select,
placeholder: placeholder,
onChange: this.handleInputChange,
onKeyDown: this.handleKeyDown,
onKeyUp: this.handleKeyUp,
value: inputValue || '',
selected: isInputSelected,
disabled: disabled,
ref: this.setInput
})),
_react2.default.createElement(
'div',
{ className: _searchableStyle2.default.functions },
openItemElement && value && _react2.default.createElement(
'span',
{ className: _searchableStyle2.default.openItem },
openItemElement(value)
),
onClear && value && _react2.default.createElement(
'button',
{
type: 'button',
className: _searchableStyle2.default.clearButton,
onClick: onClear
},
_react2.default.createElement(_closeIcon2.default, { color: 'inherit' })
),
!isLoading && _react2.default.createElement(
'div',
{
className: _searchableStyle2.default.arrow,
onClick: disabled ? null : this.handleArrowClick,
tabIndex: 0,
onKeyPress: disabled ? null : this.handleArrowKeyPress
},
_react2.default.createElement(_angleDownIcon2.default, { color: 'inherit' })
),
isLoading && _react2.default.createElement(_spinner2.default, null)
)
),
isOpen && _react2.default.createElement(
_stacked2.default,
null,
isActive => _react2.default.createElement(
_portal.Portal,
null,
_react2.default.createElement(
_reactPopper.Popper,
{
placement: 'bottom',
className: _searchableStyle2.default.popper,
modifiers: {
preventOverflow: {
boundariesElement: 'viewport'
},
customStyle: {
enabled: true,
fn: data => {
const width = (0, _get3.default)(data, 'instance.reference.clientWidth') || 500;
data.styles = _extends({}, data.styles, {
width: width
});
return data;
}
}
}
},
_react2.default.createElement(
'div',
null,
_react2.default.createElement(
_captureOutsideClicks2.default,
{
onClickOutside: isActive && isOpen ? this.handleClose : undefined
},
_react2.default.createElement(
'div',
{ className: _searchableStyle2.default.listContainer },
_react2.default.createElement(_escapable2.default, {
onEscape: event => (isActive || event.shiftKey) && this.handleClose()
}),
items.length === 0 && !isLoading && _react2.default.createElement(
'p',
{ className: _searchableStyle2.default.noResultText },
'No results'
),
items.length === 0 && isLoading && _react2.default.createElement(
'div',
{ className: _searchableStyle2.default.listSpinner },
_react2.default.createElement(_spinner2.default, { message: 'Loading items\u2026' })
),
items.length > 0 && _react2.default.createElement(_SelectMenu2.default, {
items: items,
value: value,
onSelect: this.handleSelect,
renderItem: renderItem,
highlightIndex: highlightIndex
})
)
)
)
)
)
)
);
}
}
exports.default = StatelessSearchableSelect;
StatelessSearchableSelect.propTypes = {
onChange: _propTypes2.default.func,
value: _propTypes2.default.any,
inputValue: _propTypes2.default.string,
onInputChange: _propTypes2.default.func,
onClear: _propTypes2.default.func,
renderItem: _propTypes2.default.func,
placeholder: _propTypes2.default.string,
isLoading: _propTypes2.default.bool,
isOpen: _propTypes2.default.bool,
onOpen: _propTypes2.default.func,
onClose: _propTypes2.default.func,
openItemElement: _propTypes2.default.func,
items: _propTypes2.default.array,
highlightIndex: _propTypes2.default.number,
onHighlightIndexChange: _propTypes2.default.func,
isInputSelected: _propTypes2.default.bool,
disabled: _propTypes2.default.bool,
dropdownPosition: _propTypes2.default.string,
readOnly: _propTypes2.default.bool
};
StatelessSearchableSelect.defaultProps = {
onChange: noop,
onOpen: noop,
onClose: noop,
onInputChange: noop,
isLoading: false,
readOnly: false,
renderItem: item => item,
items: [],
dropdownPosition: 'bottom'
};