1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | import { __assign, __decorate, __extends, __spreadArrays } from "tslib";
|
17 | import classNames from "classnames";
|
18 | import * as React from "react";
|
19 | import { polyfill } from "react-lifecycles-compat";
|
20 | import { AbstractPureComponent2, Classes, Keys, refHandler, setRef, Utils } from "../../common";
|
21 | import { DISPLAYNAME_PREFIX } from "../../common/props";
|
22 | import { Icon, IconSize } from "../icon/icon";
|
23 | import { Tag } from "../tag/tag";
|
24 |
|
25 | var NONE = -1;
|
26 | var TagInput = (function (_super) {
|
27 | __extends(TagInput, _super);
|
28 | function TagInput() {
|
29 | var _this = _super !== null && _super.apply(this, arguments) || this;
|
30 | _this.state = {
|
31 | activeIndex: NONE,
|
32 | inputValue: _this.props.inputValue || "",
|
33 | isInputFocused: false,
|
34 | };
|
35 | _this.inputElement = null;
|
36 | _this.handleRef = refHandler(_this, "inputElement", _this.props.inputRef);
|
37 | _this.addTags = function (value, method) {
|
38 | if (method === void 0) { method = "default"; }
|
39 | var _a = _this.props, inputValue = _a.inputValue, onAdd = _a.onAdd, onChange = _a.onChange, values = _a.values;
|
40 | var newValues = _this.getValues(value);
|
41 | var shouldClearInput = (onAdd === null || onAdd === void 0 ? void 0 : onAdd(newValues, method)) !== false && inputValue === undefined;
|
42 |
|
43 | if (Utils.isFunction(onChange)) {
|
44 | shouldClearInput = onChange(__spreadArrays(values, newValues)) !== false && shouldClearInput;
|
45 | }
|
46 |
|
47 | if (shouldClearInput) {
|
48 | _this.setState({ inputValue: "" });
|
49 | }
|
50 | };
|
51 | _this.maybeRenderTag = function (tag, index) {
|
52 | if (!tag) {
|
53 | return null;
|
54 | }
|
55 | var _a = _this.props, large = _a.large, tagProps = _a.tagProps;
|
56 | var props = Utils.isFunction(tagProps) ? tagProps(tag, index) : tagProps;
|
57 | return (React.createElement(Tag, __assign({ active: index === _this.state.activeIndex, "data-tag-index": index, key: tag + "__" + index, large: large, onRemove: _this.props.disabled ? undefined : _this.handleRemoveTag }, props), tag));
|
58 | };
|
59 | _this.handleContainerClick = function () {
|
60 | var _a;
|
61 | (_a = _this.inputElement) === null || _a === void 0 ? void 0 : _a.focus();
|
62 | };
|
63 | _this.handleContainerBlur = function (_a) {
|
64 | var currentTarget = _a.currentTarget;
|
65 | _this.requestAnimationFrame(function () {
|
66 |
|
67 |
|
68 | if (!currentTarget.contains(document.activeElement)) {
|
69 | if (_this.props.addOnBlur && _this.state.inputValue !== undefined && _this.state.inputValue.length > 0) {
|
70 | _this.addTags(_this.state.inputValue, "blur");
|
71 | }
|
72 | _this.setState({ activeIndex: NONE, isInputFocused: false });
|
73 | }
|
74 | });
|
75 | };
|
76 | _this.handleInputFocus = function (event) {
|
77 | var _a, _b;
|
78 | _this.setState({ isInputFocused: true });
|
79 | (_b = (_a = _this.props.inputProps) === null || _a === void 0 ? void 0 : _a.onFocus) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
80 | };
|
81 | _this.handleInputChange = function (event) {
|
82 | var _a, _b, _c, _d;
|
83 | _this.setState({ activeIndex: NONE, inputValue: event.currentTarget.value });
|
84 | (_b = (_a = _this.props).onInputChange) === null || _b === void 0 ? void 0 : _b.call(_a, event);
|
85 | (_d = (_c = _this.props.inputProps) === null || _c === void 0 ? void 0 : _c.onChange) === null || _d === void 0 ? void 0 : _d.call(_c, event);
|
86 | };
|
87 | _this.handleInputKeyDown = function (event) {
|
88 |
|
89 |
|
90 | var _a = event.currentTarget, selectionEnd = _a.selectionEnd, value = _a.value;
|
91 | var activeIndex = _this.state.activeIndex;
|
92 | var activeIndexToEmit = activeIndex;
|
93 | if (event.which === Keys.ENTER && value.length > 0) {
|
94 | _this.addTags(value, "default");
|
95 | }
|
96 | else if (selectionEnd === 0 && _this.props.values.length > 0) {
|
97 |
|
98 |
|
99 | if (event.which === Keys.ARROW_LEFT || event.which === Keys.ARROW_RIGHT) {
|
100 | var nextActiveIndex = _this.getNextActiveIndex(event.which === Keys.ARROW_RIGHT ? 1 : -1);
|
101 | if (nextActiveIndex !== activeIndex) {
|
102 | event.stopPropagation();
|
103 | activeIndexToEmit = nextActiveIndex;
|
104 | _this.setState({ activeIndex: nextActiveIndex });
|
105 | }
|
106 | }
|
107 | else if (event.which === Keys.BACKSPACE) {
|
108 | _this.handleBackspaceToRemove(event);
|
109 | }
|
110 | else if (event.which === Keys.DELETE) {
|
111 | _this.handleDeleteToRemove(event);
|
112 | }
|
113 | }
|
114 | _this.invokeKeyPressCallback("onKeyDown", event, activeIndexToEmit);
|
115 | };
|
116 | _this.handleInputKeyUp = function (event) {
|
117 | _this.invokeKeyPressCallback("onKeyUp", event, _this.state.activeIndex);
|
118 | };
|
119 | _this.handleInputPaste = function (event) {
|
120 | var separator = _this.props.separator;
|
121 | var value = event.clipboardData.getData("text");
|
122 | if (!_this.props.addOnPaste || value.length === 0) {
|
123 | return;
|
124 | }
|
125 |
|
126 |
|
127 | if (separator === false || value.split(separator).length === 1) {
|
128 | return;
|
129 | }
|
130 | event.preventDefault();
|
131 | _this.addTags(value, "paste");
|
132 | };
|
133 | _this.handleRemoveTag = function (event) {
|
134 |
|
135 | var index = +event.currentTarget.parentElement.getAttribute("data-tag-index");
|
136 | _this.removeIndexFromValues(index);
|
137 | };
|
138 | return _this;
|
139 | }
|
140 | TagInput.getDerivedStateFromProps = function (props, state) {
|
141 | if (props.inputValue !== state.prevInputValueProp) {
|
142 | return {
|
143 | inputValue: props.inputValue,
|
144 | prevInputValueProp: props.inputValue,
|
145 | };
|
146 | }
|
147 | return null;
|
148 | };
|
149 | TagInput.prototype.render = function () {
|
150 | var _a;
|
151 | var _b = this.props, className = _b.className, disabled = _b.disabled, fill = _b.fill, inputProps = _b.inputProps, intent = _b.intent, large = _b.large, leftIcon = _b.leftIcon, placeholder = _b.placeholder, values = _b.values;
|
152 | var classes = classNames(Classes.INPUT, Classes.TAG_INPUT, (_a = {},
|
153 | _a[Classes.ACTIVE] = this.state.isInputFocused,
|
154 | _a[Classes.DISABLED] = disabled,
|
155 | _a[Classes.FILL] = fill,
|
156 | _a[Classes.LARGE] = large,
|
157 | _a), Classes.intentClass(intent), className);
|
158 | var isLarge = classes.indexOf(Classes.LARGE) > NONE;
|
159 |
|
160 | var isSomeValueDefined = values.some(function (val) { return !!val; });
|
161 | var resolvedPlaceholder = placeholder == null || isSomeValueDefined ? inputProps === null || inputProps === void 0 ? void 0 : inputProps.placeholder : placeholder;
|
162 | return (React.createElement("div", { className: classes, onBlur: this.handleContainerBlur, onClick: this.handleContainerClick },
|
163 | React.createElement(Icon, { className: Classes.TAG_INPUT_ICON, icon: leftIcon, size: isLarge ? IconSize.LARGE : IconSize.STANDARD }),
|
164 | React.createElement("div", { className: Classes.TAG_INPUT_VALUES },
|
165 | values.map(this.maybeRenderTag),
|
166 | this.props.children,
|
167 | React.createElement("input", __assign({ value: this.state.inputValue }, inputProps, { onFocus: this.handleInputFocus, onChange: this.handleInputChange, onKeyDown: this.handleInputKeyDown, onKeyUp: this.handleInputKeyUp, onPaste: this.handleInputPaste, placeholder: resolvedPlaceholder, ref: this.handleRef, className: classNames(Classes.INPUT_GHOST, inputProps === null || inputProps === void 0 ? void 0 : inputProps.className), disabled: disabled }))),
|
168 | this.props.rightElement));
|
169 | };
|
170 | TagInput.prototype.componentDidUpdate = function (prevProps) {
|
171 | if (prevProps.inputRef !== this.props.inputRef) {
|
172 | setRef(prevProps.inputRef, null);
|
173 | this.handleRef = refHandler(this, "inputElement", this.props.inputRef);
|
174 | setRef(this.props.inputRef, this.inputElement);
|
175 | }
|
176 | };
|
177 | TagInput.prototype.getNextActiveIndex = function (direction) {
|
178 | var activeIndex = this.state.activeIndex;
|
179 | if (activeIndex === NONE) {
|
180 |
|
181 | return direction < 0 ? this.findNextIndex(this.props.values.length, -1) : NONE;
|
182 | }
|
183 | else {
|
184 |
|
185 |
|
186 |
|
187 | return this.findNextIndex(activeIndex, direction);
|
188 | }
|
189 | };
|
190 | TagInput.prototype.findNextIndex = function (startIndex, direction) {
|
191 | var values = this.props.values;
|
192 | var index = startIndex + direction;
|
193 | while (index > 0 && index < values.length && !values[index]) {
|
194 | index += direction;
|
195 | }
|
196 | return Utils.clamp(index, 0, values.length);
|
197 | };
|
198 | |
199 |
|
200 |
|
201 |
|
202 |
|
203 | TagInput.prototype.getValues = function (inputValue) {
|
204 | var separator = this.props.separator;
|
205 |
|
206 |
|
207 | return (separator === false ? [inputValue] : inputValue.split(separator))
|
208 | .map(function (val) { return val.trim(); })
|
209 | .filter(function (val) { return val.length > 0; });
|
210 | };
|
211 | TagInput.prototype.handleBackspaceToRemove = function (event) {
|
212 | var previousActiveIndex = this.state.activeIndex;
|
213 |
|
214 | this.setState({ activeIndex: this.getNextActiveIndex(-1) });
|
215 |
|
216 | if (this.isValidIndex(previousActiveIndex)) {
|
217 | event.stopPropagation();
|
218 | this.removeIndexFromValues(previousActiveIndex);
|
219 | }
|
220 | };
|
221 | TagInput.prototype.handleDeleteToRemove = function (event) {
|
222 | var activeIndex = this.state.activeIndex;
|
223 | if (this.isValidIndex(activeIndex)) {
|
224 | event.stopPropagation();
|
225 | this.removeIndexFromValues(activeIndex);
|
226 | }
|
227 | };
|
228 |
|
229 | TagInput.prototype.removeIndexFromValues = function (index) {
|
230 | var _a = this.props, onChange = _a.onChange, onRemove = _a.onRemove, values = _a.values;
|
231 | onRemove === null || onRemove === void 0 ? void 0 : onRemove(values[index], index);
|
232 | if (Utils.isFunction(onChange)) {
|
233 | onChange(values.filter(function (_, i) { return i !== index; }));
|
234 | }
|
235 | };
|
236 | TagInput.prototype.invokeKeyPressCallback = function (propCallbackName, event, activeIndex) {
|
237 | var _a, _b, _c, _d;
|
238 | (_b = (_a = this.props)[propCallbackName]) === null || _b === void 0 ? void 0 : _b.call(_a, event, activeIndex === NONE ? undefined : activeIndex);
|
239 | (_d = (_c = this.props.inputProps)[propCallbackName]) === null || _d === void 0 ? void 0 : _d.call(_c, event);
|
240 | };
|
241 |
|
242 | TagInput.prototype.isValidIndex = function (index) {
|
243 | return index !== NONE && index < this.props.values.length;
|
244 | };
|
245 | TagInput.displayName = DISPLAYNAME_PREFIX + ".TagInput";
|
246 | TagInput.defaultProps = {
|
247 | addOnBlur: false,
|
248 | addOnPaste: true,
|
249 | inputProps: {},
|
250 | separator: /[,\n\r]/,
|
251 | tagProps: {},
|
252 | };
|
253 | TagInput = __decorate([
|
254 | polyfill
|
255 | ], TagInput);
|
256 | return TagInput;
|
257 | }(AbstractPureComponent2));
|
258 | export { TagInput };
|
259 |
|
\ | No newline at end of file |