@haraldlons/reactjs-tag-input
Version:
A simple (but fully customizable) react tag input component built using styled components.
270 lines (224 loc) • 10.4 kB
JavaScript
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _templateObject = _taggedTemplateLiteral(['\n ', '\n '], ['\n ', '\n ']);
function _taggedTemplateLiteral(strings, raw) { return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
import React, { Component } from "react";
import PropTypes from 'prop-types';
import styled from 'styled-components';
import Wrapper from './styled/Wrapper';
import Tag from './styled/Tag';
import Input from './styled/Input';
import TagDelete from './styled/TagDelete';
var TagInput = function (_Component) {
_inherits(TagInput, _Component);
function TagInput(props) {
_classCallCheck(this, TagInput);
var _this = _possibleConstructorReturn(this, (TagInput.__proto__ || Object.getPrototypeOf(TagInput)).call(this, props));
_this.state = {
selectedTags: []
};
_this.renderTags = _this.renderTags.bind(_this);
_this.onInputKeyUp = _this.onInputKeyUp.bind(_this);
_this.onInputKeyDown = _this.onInputKeyDown.bind(_this);
_this.focusInput = _this.focusInput.bind(_this);
_this.removeTag = _this.removeTag.bind(_this);
_this.input = React.createRef();
return _this;
}
_createClass(TagInput, [{
key: 'componentDidMount',
value: function componentDidMount() {
var tags = this.props.tags;
var propTags = tags.map(function (tag, index) {
return Object.assign({
index: index
}, tag);
});
this.setState(function (state) {
return {
selectedTags: [].concat(_toConsumableArray(state.selectedTags), _toConsumableArray(propTags))
};
});
this.focusInput();
}
}, {
key: 'onInputKeyUp',
value: function onInputKeyUp(e) {
var _this2 = this;
var _props = this.props,
addTagOnEnterKeyPressed = _props.addTagOnEnterKeyPressed,
onTagsChanged = _props.onTagsChanged;
var inputValue = e.target.value;
var inputNotEmpty = inputValue && inputValue.trim() !== '';
var addTag = function addTag() {
_this2.setState(function (state) {
return {
selectedTags: [].concat(_toConsumableArray(state.selectedTags), [{
index: state.selectedTags.length + 1,
displayValue: inputValue
}])
};
}, function () {
var selectedTags = _this2.state.selectedTags;
_this2.clearInput();
onTagsChanged(selectedTags);
});
};
if (e.key === 'Enter' && inputNotEmpty && addTagOnEnterKeyPressed) {
addTag();
}
}
}, {
key: 'onInputKeyDown',
value: function onInputKeyDown(e) {
var _this3 = this;
var onTagsChanged = this.props.onTagsChanged;
var deleteLastTag = function deleteLastTag() {
_this3.setState(function (state) {
return {
selectedTags: state.selectedTags.splice(0, state.selectedTags.length - 1)
};
}, function () {
var selectedTags = _this3.state.selectedTags;
onTagsChanged(selectedTags);
});
};
if (e.key === 'Backspace' && e.target.selectionStart === 0) {
deleteLastTag();
}
}
}, {
key: 'clearInput',
value: function clearInput() {
this.input.value = '';
}
}, {
key: 'focusInput',
value: function focusInput() {
this.input.focus();
}
}, {
key: 'removeTag',
value: function removeTag(index) {
var _this4 = this;
this.setState(function (state) {
return {
selectedTags: state.selectedTags.filter(function (tag) {
return tag.index !== index;
})
};
}, function () {
var selectedTags = _this4.state.selectedTags;
var onTagsChanged = _this4.props.onTagsChanged;
onTagsChanged(selectedTags);
});
}
}, {
key: 'renderTags',
value: function renderTags() {
var _this5 = this;
var selectedTags = this.state.selectedTags;
var TagComponent = this.getTagStyledComponent();
var Delete = this.getTagDeleteComponent();
var DeleteIcon = this.getDeleteIcon();
return selectedTags.length > 0 ? selectedTags.map(function (tag, index) {
return React.createElement(
TagComponent,
{ key: index },
tag.displayValue,
React.createElement(
Delete,
{ index: tag.index, onClick: function onClick() {
return _this5.removeTag(tag.index);
} },
DeleteIcon
)
);
}) : null;
}
}, {
key: 'renderPlaceholder',
value: function renderPlaceholder() {
var selectedTags = this.state.selectedTags;
var _props2 = this.props,
placeholder = _props2.placeholder,
hideInputPlaceholderTextIfTagsPresent = _props2.hideInputPlaceholderTextIfTagsPresent;
return hideInputPlaceholderTextIfTagsPresent && selectedTags.length > 0 ? null : placeholder;
}
}, {
key: 'getDeleteIcon',
value: function getDeleteIcon() {
var tagDeleteIcon = this.props.tagDeleteIcon;
return tagDeleteIcon || ' x';
}
}, {
key: 'getTagDeleteComponent',
value: function getTagDeleteComponent() {
var tagDeleteStyle = this.props.tagDeleteStyle;
return tagDeleteStyle ? styled(TagDelete)(_templateObject, tagDeleteStyle) : TagDelete;
}
}, {
key: 'getTagStyledComponent',
value: function getTagStyledComponent() {
var tagStyle = this.props.tagStyle;
return tagStyle ? styled(Tag)(_templateObject, tagStyle) : Tag;
}
}, {
key: 'getInputWrapperStyledComponent',
value: function getInputWrapperStyledComponent() {
var wrapperStyle = this.props.wrapperStyle;
return wrapperStyle ? styled(Wrapper)(_templateObject, wrapperStyle) : Wrapper;
}
}, {
key: 'getInputStyledComponent',
value: function getInputStyledComponent() {
var inputStyle = this.props.inputStyle;
return inputStyle ? styled(Input)(_templateObject, inputStyle) : Input;
}
}, {
key: 'render',
value: function render() {
var _this6 = this;
var onInputChanged = this.props.onInputChanged;
var InputWrapper = this.getInputWrapperStyledComponent();
var InputComponent = this.getInputStyledComponent();
return React.createElement(
InputWrapper,
{ onClick: this.focusInput },
this.renderTags(),
React.createElement(InputComponent, {
ref: function ref(el) {
return _this6.input = el;
},
onChange: onInputChanged,
placeholder: this.renderPlaceholder(),
type: 'text',
onKeyUp: this.onInputKeyUp,
onKeyDown: this.onInputKeyDown })
);
}
}]);
return TagInput;
}(Component);
TagInput.propTypes = {
tags: PropTypes.array.isRequired,
onTagsChanged: PropTypes.func.isRequired,
onInputChange: PropTypes.func,
placeholder: PropTypes.string,
wrapperStyle: PropTypes.string,
inputStyle: PropTypes.string,
tagStyle: PropTypes.string,
tagDeleteStyle: PropTypes.string,
tagDeleteIcon: PropTypes.element,
addTagOnEnterKeyPressed: PropTypes.bool,
hideInputPlaceholderTextIfTagsPresent: PropTypes.bool
};
TagInput.defaultProps = {
placeholder: 'Type something and hit enter...',
addTagOnEnterKeyPressed: true,
hideInputPlaceholderTextIfTagsPresent: true
};
export default TagInput;