@skbkontur/react-ui 6.3.3 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/components/Input/InputLayout/InputLayout.styles.d.ts +1 -0
  3. package/components/Input/InputLayout/InputLayout.styles.js +11 -8
  4. package/components/Input/InputLayout/InputLayout.styles.js.map +1 -1
  5. package/components/Input/InputLayout/InputLayoutAsideText.js +3 -1
  6. package/components/Input/InputLayout/InputLayoutAsideText.js.map +1 -1
  7. package/components/MenuItem/MenuItem.js +1 -0
  8. package/components/MenuItem/MenuItem.js.map +1 -1
  9. package/components/MenuItem/MenuItem.styles.d.ts +1 -0
  10. package/components/MenuItem/MenuItem.styles.js +9 -6
  11. package/components/MenuItem/MenuItem.styles.js.map +1 -1
  12. package/components/Radio/Radio.js +18 -22
  13. package/components/Radio/Radio.js.map +1 -1
  14. package/components/Radio/Radio.styles.js +1 -1
  15. package/components/Radio/Radio.styles.js.map +1 -1
  16. package/components/SidePage/SidePage.styles.d.ts +1 -0
  17. package/components/SidePage/SidePage.styles.js +19 -16
  18. package/components/SidePage/SidePage.styles.js.map +1 -1
  19. package/components/SidePage/SidePageHeader.js +3 -0
  20. package/components/SidePage/SidePageHeader.js.map +1 -1
  21. package/components/TokenInput/TokenInput.d.ts +17 -16
  22. package/components/TokenInput/TokenInput.js +202 -59
  23. package/components/TokenInput/TokenInput.js.map +1 -1
  24. package/components/TokenInput/TokenInputFailedMenu.d.ts +17 -0
  25. package/components/TokenInput/TokenInputFailedMenu.js +30 -0
  26. package/components/TokenInput/TokenInputFailedMenu.js.map +1 -0
  27. package/components/TokenInput/TokenInputMenu.d.ts +13 -2
  28. package/components/TokenInput/TokenInputMenu.js +134 -19
  29. package/components/TokenInput/TokenInputMenu.js.map +1 -1
  30. package/components/TokenInput/TokenInputMobileMenu.js +3 -2
  31. package/components/TokenInput/TokenInputMobileMenu.js.map +1 -1
  32. package/components/TokenInput/TokenInputReducer.d.ts +6 -1
  33. package/components/TokenInput/TokenInputReducer.js +14 -3
  34. package/components/TokenInput/TokenInputReducer.js.map +1 -1
  35. package/components/TokenInput/locale/locales/en.js +1 -0
  36. package/components/TokenInput/locale/locales/en.js.map +1 -1
  37. package/components/TokenInput/locale/locales/ru.js +1 -0
  38. package/components/TokenInput/locale/locales/ru.js.map +1 -1
  39. package/components/TokenInput/locale/types.d.ts +1 -0
  40. package/components/TokenInput/locale/types.js.map +1 -1
  41. package/internal/Popup/Popup.js.map +1 -1
  42. package/internal/themes/BasicTheme.d.ts +15 -0
  43. package/internal/themes/BasicTheme.js +21 -0
  44. package/internal/themes/BasicTheme.js.map +1 -1
  45. package/internal/themes/DarkTheme6_0.js +1 -0
  46. package/internal/themes/DarkTheme6_0.js.map +1 -1
  47. package/internal/themes/DarkTheme6_4.d.ts +1 -0
  48. package/internal/themes/DarkTheme6_4.js +44 -0
  49. package/internal/themes/DarkTheme6_4.js.map +1 -0
  50. package/internal/themes/LightTheme6_4.d.ts +1 -0
  51. package/internal/themes/LightTheme6_4.js +44 -0
  52. package/internal/themes/LightTheme6_4.js.map +1 -0
  53. package/lib/theming/ThemeVersions.d.ts +1 -1
  54. package/lib/theming/ThemeVersions.js.map +1 -1
  55. package/lib/theming/themes/DarkTheme.d.ts +1 -0
  56. package/lib/theming/themes/DarkTheme.js +3 -1
  57. package/lib/theming/themes/DarkTheme.js.map +1 -1
  58. package/lib/theming/themes/LightTheme.d.ts +1 -0
  59. package/lib/theming/themes/LightTheme.js +3 -1
  60. package/lib/theming/themes/LightTheme.js.map +1 -1
  61. package/package.json +3 -2
@@ -77,8 +77,9 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
77
  };
78
78
  import lodashIsEqual from 'lodash.isequal';
79
79
  import React from 'react';
80
- import logWarning from 'warning';
80
+ import warning from 'warning';
81
81
  import { CommonWrapper } from '../../internal/CommonWrapper/index.js';
82
+ import { ComboBoxRequestStatus } from '../../internal/CustomComboBox/CustomComboBoxTypes.js';
82
83
  import { PopupIds } from '../../internal/Popup/index.js';
83
84
  import { blink } from '../../lib/blink.js';
84
85
  import { createPropsGetter } from '../../lib/createPropsGetter.js';
@@ -121,6 +122,7 @@ export var DefaultState = {
121
122
  inputValueWidth: 2,
122
123
  inputValueHeight: 22,
123
124
  showMobilePopup: false,
125
+ requestStatus: ComboBoxRequestStatus.Unknown,
124
126
  };
125
127
  export var TokenInputDataTids = {
126
128
  root: 'TokenInput__root',
@@ -147,6 +149,8 @@ var TokenInput = /** @class */ (function (_super) {
147
149
  _this.wrapper = null;
148
150
  _this.scrollContainerRef = React.createRef();
149
151
  _this.memoizedTokens = new Map();
152
+ _this.menuNavigatedByUser = false;
153
+ _this.requestId = 0;
150
154
  _this.renderInlineField = function () {
151
155
  return _this.renderTokenInputField({
152
156
  variant: 'inline',
@@ -173,7 +177,7 @@ var TokenInput = /** @class */ (function (_super) {
173
177
  var _e = _this.props, maxMenuHeight = _e.maxMenuHeight, error = _e.error, warning = _e.warning, disabled = _e.disabled, renderNotFound = _e.renderNotFound, inputMode = _e.inputMode, renderTotalCount = _e.renderTotalCount, totalCount = _e.totalCount, ariaDescribedby = _e["aria-describedby"], ariaLabel = _e["aria-label"], maxHeight = _e.maxHeight;
174
178
  var _f = _this.getProps(), selectedItems = _f.selectedItems, menuWidth = _f.menuWidth, menuAlign = _f.menuAlign, renderItem = _f.renderItem;
175
179
  var isMobileFooter = variant === 'mobileFooter';
176
- var _g = _this.state, inFocus = _g.inFocus, inputValueWidth = _g.inputValueWidth, inputValueHeight = _g.inputValueHeight, inputValue = _g.inputValue, reservedInputValue = _g.reservedInputValue, autocompleteItems = _g.autocompleteItems, loading = _g.loading;
180
+ var _g = _this.state, inFocus = _g.inFocus, inputValueWidth = _g.inputValueWidth, inputValueHeight = _g.inputValueHeight, inputValue = _g.inputValue, reservedInputValue = _g.reservedInputValue, loading = _g.loading;
177
181
  var theme = _this.theme;
178
182
  var inputInlineStyles = {
179
183
  // вычисляем ширину чтобы input автоматически перенёсся на следующую строку при необходимости
@@ -198,12 +202,12 @@ var TokenInput = /** @class */ (function (_super) {
198
202
  // input растягивается на всю ширину чтобы placeholder не обрезался
199
203
  _d[_this.styles.inputPlaceholderWrapper()] = Boolean(placeholder),
200
204
  _d)), hideCloseButton: Boolean(placeholder) },
201
- React.createElement("textarea", { id: isMobileFooter || interactive ? _this.textareaId : undefined, ref: isMobileFooter ? _this.mobileInputRef : _this.inlineInputRef, value: inputValue, style: inputInlineStyles, spellCheck: false, disabled: disabled, readOnly: !interactive, tabIndex: !interactive ? -1 : undefined, className: inputClassName, placeholder: placeholder, onFocus: interactive ? _this.handleInputFocus : undefined, onBlur: interactive ? _this.handleInputBlur : undefined, onChange: interactive ? _this.handleChangeInputValue : undefined, onKeyDown: interactive ? _this.handleKeyDown : undefined, onPaste: interactive ? _this.handleInputPaste : undefined, inputMode: inputMode, "aria-label": isMobileFooter || interactive ? ariaLabel : undefined, "aria-describedby": isMobileFooter || interactive ? ariaDescribedby : undefined, "aria-hidden": !interactive ? true : undefined, autoFocus: isMobileFooter })));
205
+ React.createElement("textarea", { id: isMobileFooter || interactive ? _this.textareaId : undefined, ref: isMobileFooter ? _this.mobileInputRef : _this.inlineInputRef, value: inputValue, style: inputInlineStyles, spellCheck: false, disabled: disabled, readOnly: !interactive, tabIndex: !interactive ? -1 : undefined, className: inputClassName, placeholder: placeholder, onFocus: interactive ? _this.handleInputFocus : undefined, onBlur: interactive ? _this.handleInputBlur : undefined, onChange: interactive ? _this.handleChangeInputValue : undefined, onKeyDown: interactive ? _this.handleKeyDown : undefined, onPaste: interactive ? _this.handleInputPaste : undefined, inputMode: inputMode, "aria-label": isMobileFooter || interactive ? ariaLabel : undefined, "aria-describedby": isMobileFooter || interactive ? ariaDescribedby : undefined, "aria-hidden": !interactive ? true : undefined, "aria-busy": interactive && loading ? true : undefined, autoFocus: isMobileFooter })));
202
206
  var inner = (React.createElement(React.Fragment, null,
203
207
  isMobileFooter ? null : (React.createElement(TextWidthHelper, { ref: _this.textHelperRef, text: inputValue, theme: _this.theme, size: _this.size })),
204
208
  _this.renderTokensStart(interactive),
205
209
  inputNode,
206
- showMenu && (React.createElement(TokenInputMenu, { popupMenuId: _this.rootId, ref: _this.tokensInputMenuRef, items: autocompleteItems, loading: loading, opened: showMenu, maxMenuHeight: maxMenuHeight, anchorElementForCursor: _this.input, anchorElementRoot: _this.wrapper, renderNotFound: renderNotFound, renderItem: renderItem, onValueChange: _this.selectItem, renderAddButton: _this.renderAddButton, menuWidth: menuWidth, menuAlign: menuAlign, renderTotalCount: renderTotalCount, totalCount: totalCount, size: _this.size })),
210
+ showMenu && (React.createElement(TokenInputMenu, { popupMenuId: _this.rootId, ref: _this.tokensInputMenuRef, items: _this.getMenuItems(), loading: loading, opened: showMenu, maxMenuHeight: maxMenuHeight, anchorElementForCursor: _this.input, anchorElementRoot: _this.wrapper, renderNotFound: renderNotFound, renderItem: renderItem, onValueChange: _this.selectItem, renderAddButton: _this.renderAddButton, menuWidth: menuWidth, menuAlign: menuAlign, renderTotalCount: renderTotalCount, totalCount: totalCount, size: _this.size, requestStatus: _this.state.requestStatus, repeatRequest: _this.repeatRequest })),
207
211
  _this.renderTokensEnd(interactive),
208
212
  _this.isEditingMode ? (React.createElement(TokenView, { size: _this.size },
209
213
  React.createElement("span", { className: _this.styles.reservedInput(theme) }, reservedInputValue))) : null));
@@ -219,11 +223,12 @@ var TokenInput = /** @class */ (function (_super) {
219
223
  _this.renderMobileMenu = function () {
220
224
  var _a = _this.props, maxMenuHeight = _a.maxMenuHeight, renderNotFound = _a.renderNotFound, renderTotalCount = _a.renderTotalCount, totalCount = _a.totalCount;
221
225
  var renderItem = _this.getProps().renderItem;
222
- var _b = _this.state, autocompleteItems = _b.autocompleteItems, loading = _b.loading;
226
+ var loading = _this.state.loading;
223
227
  return (React.createElement(TokenInputMobileMenu, { popupMenuId: _this.rootId, ref: function (node) {
224
228
  _this.tokensInputMenuRef(node);
225
- }, items: autocompleteItems, loading: loading, opened: true, maxMenuHeight: maxMenuHeight, renderNotFound: renderNotFound, renderItem: renderItem, onValueChange: _this.selectItem, renderAddButton: _this.renderAddButton, renderTotalCount: renderTotalCount, totalCount: totalCount, size: _this.size, mobileFooterComponent: _this.renderMobilePopupFooter(), onCloseRequest: function () {
226
- return _this.dispatch({
229
+ }, items: _this.getMenuItems(), loading: loading, opened: true, maxMenuHeight: maxMenuHeight, renderNotFound: renderNotFound, renderItem: renderItem, onValueChange: _this.selectItem, renderAddButton: _this.renderAddButton, renderTotalCount: renderTotalCount, totalCount: totalCount, size: _this.size, requestStatus: _this.state.requestStatus, repeatRequest: _this.repeatRequest, mobileFooterComponent: _this.renderMobilePopupFooter(), onCloseRequest: function () {
230
+ _this.cancelRequest();
231
+ _this.dispatch({
227
232
  type: 'SET_CLOSE_MOBILE_POPUP',
228
233
  });
229
234
  } }));
@@ -298,6 +303,7 @@ var TokenInput = /** @class */ (function (_super) {
298
303
  _this.dispatch({ type: 'SET_PREVENT_BLUR', payload: false });
299
304
  }
300
305
  else {
306
+ _this.cancelRequest();
301
307
  _this.dispatch({ type: 'BLUR' });
302
308
  _this.getProps().onBlur(event);
303
309
  }
@@ -317,6 +323,9 @@ var TokenInput = /** @class */ (function (_super) {
317
323
  _this.finishTokenEdit();
318
324
  return;
319
325
  }
326
+ if (_this.state.loading || _this.state.requestStatus === ComboBoxRequestStatus.Failed) {
327
+ return;
328
+ }
320
329
  // чекаем автокомплит на совпадение с введенным значением в инпут
321
330
  if (autocompleteItems && autocompleteItems.length === 1) {
322
331
  var item = autocompleteItems[0];
@@ -377,56 +386,91 @@ var TokenInput = /** @class */ (function (_super) {
377
386
  event.clipboardData.setData('text/plain', tokens.join(delimiters[0]));
378
387
  };
379
388
  _this.handleInputPaste = function (event) {
389
+ var _a, _b;
380
390
  if (_this.type === TokenInputType.WithReference || !event.clipboardData) {
381
391
  return;
382
392
  }
383
393
  var paste = event.clipboardData.getData('text');
384
- var _a = _this.getProps(), delimiters = _a.delimiters, selectedItems = _a.selectedItems, valueToItem = _a.valueToItem, onValueChange = _a.onValueChange;
394
+ var _c = _this.getProps(), delimiters = _c.delimiters, selectedItems = _c.selectedItems, onValueChange = _c.onValueChange;
385
395
  if (delimiters.some(function (delimiter) { return paste.includes(delimiter); })) {
386
396
  event.preventDefault();
387
397
  event.stopPropagation();
388
398
  var tokens = _this.splitValueByDelimiters(paste.trim());
389
- var items = tokens
390
- .filter(Boolean)
391
- .map(function (token) { return valueToItem(token); })
392
- .filter(function (item) { return item && !_this.hasValueInItems(selectedItems, item); });
393
- var newItems = selectedItems.concat(items);
394
- onValueChange(newItems);
399
+ var _d = _this.createItemsFromTokens(tokens, selectedItems), items = _d.items, remainder_1 = _d.remainder;
400
+ if (items.length > 0) {
401
+ onValueChange(selectedItems.concat(items));
402
+ }
403
+ _this.menuNavigatedByUser = false;
395
404
  _this.dispatch({ type: 'SET_AUTOCOMPLETE_ITEMS', payload: undefined });
396
- _this.tryGetItems();
405
+ if (remainder_1) {
406
+ _this.blink();
407
+ _this.dispatch({ type: 'UPDATE_QUERY', payload: remainder_1 }, function () { return _this.tryGetItems(remainder_1); });
408
+ (_b = (_a = _this.props).onInputValueChange) === null || _b === void 0 ? void 0 : _b.call(_a, remainder_1);
409
+ }
410
+ else {
411
+ _this.tryGetItems();
412
+ }
397
413
  }
398
414
  };
415
+ _this.repeatRequest = function () {
416
+ var _a;
417
+ _this.tryGetItems(_this.state.inputValue);
418
+ (_a = _this.input) === null || _a === void 0 ? void 0 : _a.focus();
419
+ };
420
+ _this.cancelRequest = function () {
421
+ _this.requestId += 1;
422
+ };
399
423
  _this.tryGetItems = function () {
400
424
  var args_1 = [];
401
425
  for (var _i = 0; _i < arguments.length; _i++) {
402
426
  args_1[_i] = arguments[_i];
403
427
  }
404
428
  return __awaiter(_this, __spreadArray([], args_1, true), void 0, function (query) {
405
- var autocompleteItems, _a, selectedItems_1, valueToItem, valueToString_1, isSelectedItem_1, isEditingItem_1, autocompleteItemsUnique, autocompleteItemsUniqueSimple, editingItem, selectItemIndex, highlightIndex_1, applyMenuHighlight;
429
+ var expectingId, autocompleteItems, _a, _b, selectedItems, valueToItem, valueToString, isSelectedItem, isEditingItem, autocompleteItemsUnique, autocompleteItemsUniqueSimple, editingItem, selectItemIndex, highlightIndex, applyMenuHighlight;
406
430
  var _this = this;
407
- var _b, _c;
431
+ var _c, _d, _e, _f;
408
432
  if (query === void 0) { query = ''; }
409
- return __generator(this, function (_d) {
410
- switch (_d.label) {
433
+ return __generator(this, function (_g) {
434
+ switch (_g.label) {
411
435
  case 0:
412
- if (!(this.props.getItems && (this.isInputValueChanged || !this.props.hideMenuIfEmptyInputValue))) return [3 /*break*/, 2];
436
+ if (!this.props.getItems || (!this.isInputValueChanged && this.props.hideMenuIfEmptyInputValue)) {
437
+ this.cancelRequest();
438
+ return [2 /*return*/];
439
+ }
440
+ this.requestId += 1;
441
+ expectingId = this.requestId;
413
442
  this.dispatch({ type: 'SET_LOADING', payload: true });
414
- return [4 /*yield*/, this.props.getItems(query)];
443
+ _g.label = 1;
415
444
  case 1:
416
- autocompleteItems = _d.sent();
417
- this.dispatch({ type: 'SET_LOADING', payload: false });
418
- _a = this.getProps(), selectedItems_1 = _a.selectedItems, valueToItem = _a.valueToItem, valueToString_1 = _a.valueToString;
419
- isSelectedItem_1 = function (item) { return _this.hasValueInItems(selectedItems_1, item); };
420
- isEditingItem_1 = function (item) {
421
- var editingItem = selectedItems_1[_this.state.editingTokenIndex];
445
+ _g.trys.push([1, 3, , 4]);
446
+ return [4 /*yield*/, this.props.getItems(query)];
447
+ case 2:
448
+ autocompleteItems = _g.sent();
449
+ return [3 /*break*/, 4];
450
+ case 3:
451
+ _a = _g.sent();
452
+ if (expectingId !== this.requestId) {
453
+ return [2 /*return*/];
454
+ }
455
+ this.dispatch({ type: 'SET_REQUEST_FAILURE' });
456
+ (_d = (_c = this.globalObject).requestAnimationFrame) === null || _d === void 0 ? void 0 : _d.call(_c, function () { var _a; return (_a = _this.menuRef) === null || _a === void 0 ? void 0 : _a.highlightItem(0); });
457
+ return [2 /*return*/];
458
+ case 4:
459
+ if (expectingId !== this.requestId) {
460
+ return [2 /*return*/];
461
+ }
462
+ _b = this.getProps(), selectedItems = _b.selectedItems, valueToItem = _b.valueToItem, valueToString = _b.valueToString;
463
+ isSelectedItem = function (item) { return _this.hasValueInItems(selectedItems, item); };
464
+ isEditingItem = function (item) {
465
+ var editingItem = selectedItems[_this.state.editingTokenIndex];
422
466
  return !!editingItem && _this.isEqual(item, editingItem);
423
467
  };
424
468
  autocompleteItemsUnique = autocompleteItems.filter(function (item) {
425
- return isSimpleItem(item) ? !isSelectedItem_1(item) || isEditingItem_1(item) : true;
469
+ return isSimpleItem(item) ? !isSelectedItem(item) || isEditingItem(item) : true;
426
470
  });
427
471
  autocompleteItemsUniqueSimple = autocompleteItemsUnique.filter(isSimpleItem);
428
472
  if (this.isEditingMode) {
429
- editingItem = selectedItems_1[this.state.editingTokenIndex];
473
+ editingItem = selectedItems[this.state.editingTokenIndex];
430
474
  if (this.isEqual(editingItem, valueToItem(this.state.inputValue)) &&
431
475
  !this.hasValueInItems(autocompleteItemsUniqueSimple, editingItem)) {
432
476
  autocompleteItemsUnique.unshift(editingItem);
@@ -438,12 +482,22 @@ var TokenInput = /** @class */ (function (_super) {
438
482
  _this.highlightMenuItem();
439
483
  });
440
484
  }
441
- selectItemIndex = autocompleteItemsUniqueSimple.findIndex(function (item) { return valueToString_1(item).toLowerCase() === _this.state.inputValue.toLowerCase(); });
442
- highlightIndex_1 = selectItemIndex < 0 ? 0 : selectItemIndex;
443
- applyMenuHighlight = function () { var _a; return (_a = _this.menuRef) === null || _a === void 0 ? void 0 : _a.highlightItem(highlightIndex_1); };
444
- (_c = (_b = this.globalObject).requestAnimationFrame) === null || _c === void 0 ? void 0 : _c.call(_b, applyMenuHighlight);
445
- _d.label = 2;
446
- case 2: return [2 /*return*/];
485
+ else {
486
+ this.dispatch({ type: 'SET_LOADING', payload: false });
487
+ }
488
+ selectItemIndex = autocompleteItemsUniqueSimple.findIndex(function (item) { return valueToString(item).toLowerCase() === _this.state.inputValue.toLowerCase(); });
489
+ highlightIndex = null;
490
+ if (selectItemIndex >= 0) {
491
+ highlightIndex = selectItemIndex;
492
+ }
493
+ else {
494
+ highlightIndex = 0;
495
+ }
496
+ if (highlightIndex !== null) {
497
+ applyMenuHighlight = function () { var _a; return (_a = _this.menuRef) === null || _a === void 0 ? void 0 : _a.highlightItem(highlightIndex); };
498
+ (_f = (_e = this.globalObject).requestAnimationFrame) === null || _f === void 0 ? void 0 : _f.call(_e, applyMenuHighlight);
499
+ }
500
+ return [2 /*return*/];
447
501
  }
448
502
  });
449
503
  });
@@ -478,11 +532,20 @@ var TokenInput = /** @class */ (function (_super) {
478
532
  }
479
533
  }
480
534
  var isRightmostTokenNotDisabled = !_this.isTokenDisabled(_this.getProps().selectedItems.length - 1);
481
- var canSetValueToInput = _this.showAddItemHint || ((_b = (_a = _this.state.autocompleteItems) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0;
535
+ var canSetValueToInput = _this.showAddItemHint ||
536
+ ((_b = (_a = _this.state.autocompleteItems) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) > 0 ||
537
+ _this.state.requestStatus === ComboBoxRequestStatus.Failed;
482
538
  switch (true) {
483
539
  case isKeyEnter(e):
484
- if (canSetValueToInput && _this.menuRef) {
485
- _this.menuRef.enter(e);
540
+ if (_this.type !== TokenInputType.WithoutReference) {
541
+ if (!_this.menuNavigatedByUser &&
542
+ !_this.hasExactAutocompleteMatch(_this.state.inputValue) &&
543
+ _this.rejectIfInvalidToken(_this.state.inputValue)) {
544
+ // free-text rejected: blink already done, do not select menu item
545
+ }
546
+ else if (canSetValueToInput && _this.menuRef) {
547
+ _this.menuRef.enter(e);
548
+ }
486
549
  }
487
550
  // don't allow textarea
488
551
  // became multiline
@@ -491,6 +554,7 @@ var TokenInput = /** @class */ (function (_super) {
491
554
  case isKeyArrowVertical(e):
492
555
  e.preventDefault();
493
556
  if (_this.menuRef) {
557
+ _this.menuNavigatedByUser = true;
494
558
  if (isKeyArrowUp(e)) {
495
559
  _this.menuRef.up();
496
560
  }
@@ -606,7 +670,14 @@ var TokenInput = /** @class */ (function (_super) {
606
670
  _this.getProps().onValueChange(items);
607
671
  };
608
672
  _this.handleAddItem = function () {
609
- var item = _this.getProps().valueToItem(_this.state.inputValue);
673
+ var inputValue = _this.state.inputValue;
674
+ if (!inputValue) {
675
+ return;
676
+ }
677
+ if (_this.rejectIfInvalidToken(inputValue)) {
678
+ return;
679
+ }
680
+ var item = _this.getProps().valueToItem(inputValue);
610
681
  if (item) {
611
682
  _this.selectItem(item);
612
683
  }
@@ -660,10 +731,15 @@ var TokenInput = /** @class */ (function (_super) {
660
731
  _this.tryGetItems();
661
732
  };
662
733
  _this.finishTokenEdit = function () {
663
- var _a;
664
- var _b = _this.getProps(), selectedItems = _b.selectedItems, valueToString = _b.valueToString;
665
- var _c = _this.state, editingTokenIndex = _c.editingTokenIndex, inputValue = _c.inputValue, reservedInputValue = _c.reservedInputValue, autocompleteItems = _c.autocompleteItems;
666
- var editedItem = (_a = autocompleteItems === null || autocompleteItems === void 0 ? void 0 : autocompleteItems.find(function (item) { return valueToString(item) === inputValue; })) !== null && _a !== void 0 ? _a : _this.getProps().valueToItem(inputValue);
734
+ var _a = _this.getProps(), selectedItems = _a.selectedItems, valueToString = _a.valueToString;
735
+ var _b = _this.state, editingTokenIndex = _b.editingTokenIndex, inputValue = _b.inputValue, reservedInputValue = _b.reservedInputValue, autocompleteItems = _b.autocompleteItems;
736
+ var autocompleteMatch = autocompleteItems === null || autocompleteItems === void 0 ? void 0 : autocompleteItems.filter(isSimpleItem).find(function (item) { return valueToString(item) === inputValue; });
737
+ var editedItem = autocompleteMatch !== null && autocompleteMatch !== void 0 ? autocompleteMatch : _this.getProps().valueToItem(inputValue);
738
+ if (_this.isInputValueChanged && !autocompleteMatch) {
739
+ if (!inputValue || _this.rejectIfInvalidToken(inputValue)) {
740
+ return;
741
+ }
742
+ }
667
743
  var newItems = selectedItems.concat([]);
668
744
  if (!_this.hasValueInItems(selectedItems, editedItem)) {
669
745
  newItems.splice.apply(newItems, __spreadArray([editingTokenIndex, 1], (_this.isInputValueChanged ? [editedItem] : []), false));
@@ -701,11 +777,17 @@ var TokenInput = /** @class */ (function (_super) {
701
777
  return;
702
778
  }
703
779
  if (returnedValue) {
780
+ var returnedInputValue = _this.getProps().valueToString(returnedValue);
781
+ if (_this.rejectIfInvalidToken(returnedInputValue)) {
782
+ return;
783
+ }
704
784
  _this.selectItem(returnedValue);
705
785
  }
706
786
  };
707
787
  _this.handleChangeInputValue = function (event) {
788
+ var _a, _b;
708
789
  _this.dispatch({ type: 'REMOVE_ALL_ACTIVE_TOKENS' });
790
+ _this.menuNavigatedByUser = false;
709
791
  var query = event.target.value.trimLeft();
710
792
  if (query.endsWith(' ')) {
711
793
  query = query.trimRight() + ' ';
@@ -714,7 +796,9 @@ var TokenInput = /** @class */ (function (_super) {
714
796
  _this.dispatch({ type: 'SET_AUTOCOMPLETE_ITEMS', payload: undefined });
715
797
  }
716
798
  if (_this.isDelimiterInputEnabled && _this.inputValueEndsWithDelimiter(query)) {
717
- if (_this.tryApplyDelimiterFromInputValue(query)) {
799
+ var delimiterResult = _this.tryApplyDelimiterFromInputValue(query);
800
+ if (delimiterResult) {
801
+ (_b = (_a = _this.props).onInputValueChange) === null || _b === void 0 ? void 0 : _b.call(_a, delimiterResult.nextInputValue);
718
802
  return;
719
803
  }
720
804
  }
@@ -792,11 +876,9 @@ var TokenInput = /** @class */ (function (_super) {
792
876
  if (_this.props.renderAddButton) {
793
877
  return _this.props.renderAddButton(value, _this.handleAddItem);
794
878
  }
795
- var _a = _this.locale, addButtonComment = _a.addButtonComment, addButtonTitle = _a.addButtonTitle;
796
- return (React.createElement(MenuItem, { onClick: _this.handleAddItem, comment: addButtonComment, key: "renderAddButton" },
797
- addButtonTitle,
798
- " ",
799
- value));
879
+ var _a = _this.locale, addButtonComment = _a.addButtonComment, addButtonInvalidComment = _a.addButtonInvalidComment, addButtonTitle = _a.addButtonTitle;
880
+ var isInvalid = !_this.canAcceptInputAsToken(value);
881
+ return (React.createElement(MenuItem, { onClick: _this.handleAddItem, comment: isInvalid ? addButtonInvalidComment : addButtonComment, disabled: isInvalid, key: "renderAddButton" }, "".concat(addButtonTitle, " \u00AB").concat(value, "\u00BB")));
800
882
  };
801
883
  _this.isTokenDisabled = function (itemIndex) {
802
884
  var renderedToken;
@@ -898,6 +980,7 @@ var TokenInput = /** @class */ (function (_super) {
898
980
  };
899
981
  TokenInput.prototype.componentWillUnmount = function () {
900
982
  var _a;
983
+ this.cancelRequest();
901
984
  (_a = this.globalObject.document) === null || _a === void 0 ? void 0 : _a.removeEventListener('copy', this.handleCopy);
902
985
  };
903
986
  /** Программно устанавливает фокус на поле.
@@ -953,7 +1036,7 @@ var TokenInput = /** @class */ (function (_super) {
953
1036
  };
954
1037
  TokenInput.prototype.renderMain = function () {
955
1038
  if (this.type !== TokenInputType.WithoutReference && !this.props.getItems) {
956
- logWarning(false, "getItems is required for \"Combined\" and \"WithReference\" modes.");
1039
+ warning(false, "getItems is required for \"Combined\" and \"WithReference\" modes.");
957
1040
  }
958
1041
  var _a = this.getProps(), onMouseEnter = _a.onMouseEnter, onMouseLeave = _a.onMouseLeave;
959
1042
  var showMobilePopup = this.state.showMobilePopup;
@@ -1019,6 +1102,12 @@ var TokenInput = /** @class */ (function (_super) {
1019
1102
  TokenInput.prototype.isCursorVisibleForState = function (state) {
1020
1103
  return state.inFocus && (this.isInputValueChanged || state.activeTokens.length === 0);
1021
1104
  };
1105
+ TokenInput.prototype.getMenuItems = function () {
1106
+ if (this.state.requestStatus === ComboBoxRequestStatus.Failed) {
1107
+ return null;
1108
+ }
1109
+ return this.state.autocompleteItems;
1110
+ };
1022
1111
  TokenInput.prototype.updateInputTextWidth = function () {
1023
1112
  if (this.textHelper) {
1024
1113
  // в IE текст иногда не помещается в input
@@ -1081,9 +1170,56 @@ var TokenInput = /** @class */ (function (_super) {
1081
1170
  }
1082
1171
  return e.key === delimiter;
1083
1172
  };
1173
+ TokenInput.prototype.canAcceptInputAsToken = function (value) {
1174
+ if (!value) {
1175
+ return false;
1176
+ }
1177
+ var isTokenValid = this.props.isTokenValid;
1178
+ if (!isTokenValid) {
1179
+ return true;
1180
+ }
1181
+ return isTokenValid(value);
1182
+ };
1183
+ TokenInput.prototype.rejectIfInvalidToken = function (value) {
1184
+ if (!value || !this.props.isTokenValid) {
1185
+ return false;
1186
+ }
1187
+ if (this.props.isTokenValid(value)) {
1188
+ return false;
1189
+ }
1190
+ this.blink();
1191
+ return true;
1192
+ };
1193
+ TokenInput.prototype.hasExactAutocompleteMatch = function (value) {
1194
+ var _a, _b;
1195
+ var valueToString = this.getProps().valueToString;
1196
+ return (_b = (_a = this.state.autocompleteItems) === null || _a === void 0 ? void 0 : _a.filter(isSimpleItem).some(function (item) { return valueToString(item) === value; })) !== null && _b !== void 0 ? _b : false;
1197
+ };
1198
+ TokenInput.prototype.createItemsFromTokens = function (tokens, selectedItems) {
1199
+ var _a;
1200
+ var _b = this.getProps(), valueToItem = _b.valueToItem, delimiters = _b.delimiters;
1201
+ var items = [];
1202
+ var remainder = '';
1203
+ var joinDelimiter = (_a = delimiters[0]) !== null && _a !== void 0 ? _a : ',';
1204
+ for (var index = 0; index < tokens.length; index++) {
1205
+ var token = tokens[index];
1206
+ if (!token) {
1207
+ continue;
1208
+ }
1209
+ if (!this.canAcceptInputAsToken(token)) {
1210
+ remainder = tokens.slice(index).filter(Boolean).join(joinDelimiter);
1211
+ break;
1212
+ }
1213
+ var item = valueToItem(token);
1214
+ if (item && !this.hasValueInItems(selectedItems.concat(items), item)) {
1215
+ items.push(item);
1216
+ }
1217
+ }
1218
+ return { items: items, remainder: remainder };
1219
+ };
1084
1220
  TokenInput.prototype.tryApplyDelimiterFromInputValue = function (rawValue) {
1085
1221
  var _this = this;
1086
- var _a = this.getProps(), delimiters = _a.delimiters, selectedItems = _a.selectedItems, valueToItem = _a.valueToItem, onValueChange = _a.onValueChange;
1222
+ var _a = this.getProps(), delimiters = _a.delimiters, selectedItems = _a.selectedItems, onValueChange = _a.onValueChange;
1087
1223
  var trailingDelimiter = delimiters.find(function (delimiter) { return rawValue.endsWith(delimiter); });
1088
1224
  if (!trailingDelimiter) {
1089
1225
  return false;
@@ -1091,29 +1227,36 @@ var TokenInput = /** @class */ (function (_super) {
1091
1227
  var valueWithoutTrailingDelimiter = rawValue.slice(0, rawValue.length - trailingDelimiter.length);
1092
1228
  if (this.isEditingMode) {
1093
1229
  if (valueWithoutTrailingDelimiter !== '') {
1230
+ if (this.rejectIfInvalidToken(valueWithoutTrailingDelimiter)) {
1231
+ this.dispatch({ type: 'UPDATE_QUERY', payload: valueWithoutTrailingDelimiter });
1232
+ return { nextInputValue: valueWithoutTrailingDelimiter };
1233
+ }
1094
1234
  this.dispatch({ type: 'UPDATE_QUERY', payload: valueWithoutTrailingDelimiter }, function () {
1095
1235
  _this.finishTokenEdit();
1096
1236
  });
1237
+ return { nextInputValue: valueWithoutTrailingDelimiter };
1097
1238
  }
1098
- return true;
1239
+ return { nextInputValue: this.state.inputValue };
1099
1240
  }
1100
1241
  if (valueWithoutTrailingDelimiter === '') {
1101
1242
  this.dispatch({ type: 'CLEAR_INPUT' });
1102
1243
  this.tryGetItems();
1103
- return true;
1244
+ return { nextInputValue: '' };
1104
1245
  }
1105
1246
  var tokens = this.splitValueByDelimiters(valueWithoutTrailingDelimiter);
1106
- var items = tokens
1107
- .filter(Boolean)
1108
- .map(function (token) { return valueToItem(token); })
1109
- .filter(function (item) { return item && !_this.hasValueInItems(selectedItems, item); });
1247
+ var _b = this.createItemsFromTokens(tokens, selectedItems), items = _b.items, remainder = _b.remainder;
1110
1248
  if (items.length > 0) {
1111
1249
  onValueChange(selectedItems.concat(items));
1112
1250
  }
1251
+ if (remainder) {
1252
+ this.blink();
1253
+ this.dispatch({ type: 'SET_AUTOCOMPLETE_ITEMS', payload: undefined });
1254
+ this.dispatch({ type: 'UPDATE_QUERY', payload: remainder }, function () { return _this.tryGetItems(remainder); });
1255
+ return { nextInputValue: remainder };
1256
+ }
1113
1257
  this.dispatch({ type: 'CLEAR_INPUT' });
1114
- this.dispatch({ type: 'SET_AUTOCOMPLETE_ITEMS', payload: undefined });
1115
1258
  this.tryGetItems();
1116
- return true;
1259
+ return { nextInputValue: '' };
1117
1260
  };
1118
1261
  TokenInput.prototype.moveFocusToLastToken = function () {
1119
1262
  var items = this.getProps().selectedItems;