UNPKG

backpack-ui

Version:
352 lines (281 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _defineProperty2 = require("babel-runtime/helpers/defineProperty"); var _defineProperty3 = _interopRequireDefault(_defineProperty2); 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 _possibleConstructorReturn2 = require("babel-runtime/helpers/possibleConstructorReturn"); var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); var _createClass2 = require("babel-runtime/helpers/createClass"); var _createClass3 = _interopRequireDefault(_createClass2); var _inherits2 = require("babel-runtime/helpers/inherits"); var _inherits3 = _interopRequireDefault(_inherits2); var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _classnames = require("classnames"); var _classnames2 = _interopRequireDefault(_classnames); var _typeahead = require("./typeahead"); var _typeahead2 = _interopRequireDefault(_typeahead); var _typeaheadToken = require("./typeaheadToken"); var _typeaheadToken2 = _interopRequireDefault(_typeaheadToken); var _accessor = require("./utils/accessor"); var _accessor2 = _interopRequireDefault(_accessor); var _keyEvent = require("./utils/keyEvent"); var _keyEvent2 = _interopRequireDefault(_keyEvent); var _classNames = require("./utils/classNames"); var _classNames2 = _interopRequireDefault(_classNames); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * A typeahead that, when an option is selected, instead of simply filling * the text entry widget, prepends a renderable "token", that may be deleted * by pressing backspace on the beginning of the line with the keyboard. */ var TypeaheadTokenizer = function (_Component) { (0, _inherits3.default)(TypeaheadTokenizer, _Component); (0, _createClass3.default)(TypeaheadTokenizer, null, [{ key: "arraysAreDifferent", value: function arraysAreDifferent(firstArray, secondArray) { if (firstArray.length !== secondArray.length) { return true; } for (var index = secondArray.length - 1; index >= 0; index -= 1) { if (secondArray[index] !== firstArray[index]) { return true; } } return false; } }]); function TypeaheadTokenizer(props) { (0, _classCallCheck3.default)(this, TypeaheadTokenizer); var _this = (0, _possibleConstructorReturn3.default)(this, (TypeaheadTokenizer.__proto__ || (0, _getPrototypeOf2.default)(TypeaheadTokenizer)).call(this, props)); _this.state = { selected: props.defaultSelected.slice(0) }; _this.onKeyDown = _this.onKeyDown.bind(_this); _this.getSelectedTokens = _this.getSelectedTokens.bind(_this); _this.getOptionsForTypeahead = _this.getOptionsForTypeahead.bind(_this); _this.handleBackspace = _this.handleBackspace.bind(_this); _this.removeTokenForValue = _this.removeTokenForValue.bind(_this); _this.addTokenForValue = _this.addTokenForValue.bind(_this); _this.renderTokens = _this.renderTokens.bind(_this); return _this; } (0, _createClass3.default)(TypeaheadTokenizer, [{ key: "componentWillReceiveProps", value: function componentWillReceiveProps(nextProps) { var arraysAreDifferent = TypeaheadTokenizer.arraysAreDifferent(this.props.defaultSelected, nextProps.defaultSelected); if (arraysAreDifferent) { this.setState({ selected: nextProps.defaultSelected.slice(0) }); } } }, { key: "onKeyDown", value: function onKeyDown(event) { // We only care about intercepting backspaces if (event.keyCode === _keyEvent2.default.DOM_VK_BACKSPACE) { return this.handleBackspace(event); } this.props.onKeyDown(event); return null; } }, { key: "getSelectedTokens", value: function getSelectedTokens() { return this.state.selected; } }, { key: "getOptionsForTypeahead", value: function getOptionsForTypeahead() { // return this.props.options without this.selected return this.props.options; } }, { key: "focus", value: function focus() { this.typeahead.focus(); } }, { key: "handleBackspace", value: function handleBackspace(event) { var selected = this.state.selected; // No tokens if (!selected.length) { return; } // Remove token ONLY when backspace pressed at // beginning of line without a selection var inputElement = this.typeahead.inputElement; if (inputElement.selectionStart === inputElement.selectionEnd && inputElement.selectionStart === 0) { this.removeTokenForValue(selected[selected.length - 1]); event.preventDefault(); } } }, { key: "removeTokenForValue", value: function removeTokenForValue(value) { var selected = this.state.selected; var index = selected.indexOf(value); if (index === -1) { return; } // TODO: not sure we should be doing this to state selected.splice(index, 1); this.setState({ selected: selected }); this.props.onTokenRemove(value); } }, { key: "addTokenForValue", value: function addTokenForValue(event, value) { var selected = this.state.selected; if (selected.indexOf(value) !== -1) { return; } // TODO: not sure we should be doing this to state selected.push(value); this.setState({ selected: selected }); this.typeahead.setEntryText(""); this.props.onTokenAdd(value); } // TODO: Support initialized tokens }, { key: "renderTokens", value: function renderTokens() { var _this2 = this; var _props = this.props, customClasses = _props.customClasses, disableDefaultClassNames = _props.disableDefaultClassNames, displayOption = _props.displayOption, formInputOption = _props.formInputOption, name = _props.name; var tokenClasses = (0, _defineProperty3.default)({}, _classNames2.default.token, !disableDefaultClassNames); tokenClasses[customClasses.token] = !!customClasses.token; var result = this.state.selected.map(function (selected) { var displayString = _accessor2.default.valueForOption(displayOption, selected); var value = _accessor2.default.valueForOption(formInputOption || displayOption, selected); return _react2.default.createElement( _typeaheadToken2.default, { className: (0, _classnames2.default)(tokenClasses), key: displayString, onRemove: _this2.removeTokenForValue, object: selected, value: value, name: name }, displayString ); }); return result; } }, { key: "render", value: function render() { var _this3 = this; var classes = {}; classes[this.props.customClasses.typeahead] = !!this.props.customClasses.typeahead; var classList = (0, _classnames2.default)(classes); var tokenizerClasses = [!this.props.disableDefaultClassNames && _classNames2.default.tokenizer]; tokenizerClasses[this.props.className] = !!this.props.className; var tokenizerClassList = (0, _classnames2.default)(tokenizerClasses); return _react2.default.createElement( "div", { className: tokenizerClassList }, this.renderTokens(), _react2.default.createElement(_typeahead2.default, { ref: function ref(node) { return _this3.typeahead = node; }, className: classList, placeholder: this.props.placeholder, disabled: this.props.disabled, inputProps: this.props.inputProps, allowCustomValues: this.props.allowCustomValues, customClasses: this.props.customClasses, options: this.getOptionsForTypeahead(), initialValue: this.props.initialValue, maxVisible: this.props.maxVisible, resultsTruncatedMessage: this.props.resultsTruncatedMessage, onOptionSelected: this.addTokenForValue, onKeyDown: this.onKeyDown, onKeyPress: this.props.onKeyPress, onKeyUp: this.props.onKeyUp, onFocus: this.props.onFocus, onBlur: this.props.onBlur, displayOption: this.props.displayOption, disableDefaultClassNames: this.props.disableDefaultClassNames, filterOption: this.props.filterOption, searchOptions: this.props.searchOptions }) ); } }]); return TypeaheadTokenizer; }(_react.Component); TypeaheadTokenizer.propTypes = { className: _propTypes2.default.string, name: _propTypes2.default.string, options: _propTypes2.default.arrayOf(_propTypes2.default.string), customClasses: _propTypes2.default.objectOf(_propTypes2.default.string), allowCustomValues: _propTypes2.default.number, defaultSelected: _propTypes2.default.arrayOf(_propTypes2.default.string), initialValue: _propTypes2.default.string, placeholder: _propTypes2.default.string, disabled: _propTypes2.default.bool, inputProps: _propTypes2.default.objectOf(_propTypes2.default.string), onTokenRemove: _propTypes2.default.func, onKeyDown: _propTypes2.default.func, onKeyPress: _propTypes2.default.func, onKeyUp: _propTypes2.default.func, onTokenAdd: _propTypes2.default.func, onFocus: _propTypes2.default.func, onBlur: _propTypes2.default.func, filterOption: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.func]), searchOptions: _propTypes2.default.func, displayOption: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.func]), formInputOption: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.func]), maxVisible: _propTypes2.default.number, resultsTruncatedMessage: _propTypes2.default.string, disableDefaultClassNames: _propTypes2.default.bool }; TypeaheadTokenizer.defaultProps = { className: "", name: null, options: [], defaultSelected: [], customClasses: {}, allowCustomValues: 0, initialValue: "", placeholder: "", disabled: false, inputProps: {}, disableDefaultClassNames: false, filterOption: null, searchOptions: null, displayOption: function displayOption(token) { return token; }, formInputOption: null, onKeyDown: function onKeyDown() {}, onKeyPress: function onKeyPress() {}, onKeyUp: function onKeyUp() {}, onFocus: function onFocus() {}, onBlur: function onBlur() {}, onTokenAdd: function onTokenAdd() {}, onTokenRemove: function onTokenRemove() {}, maxVisible: 0, resultsTruncatedMessage: "" }; exports.default = TypeaheadTokenizer;