@skbkontur/react-ui 6.3.4 → 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 (56) hide show
  1. package/CHANGELOG.md +29 -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/Radio/Radio.js +18 -22
  8. package/components/Radio/Radio.js.map +1 -1
  9. package/components/Radio/Radio.styles.js +1 -1
  10. package/components/Radio/Radio.styles.js.map +1 -1
  11. package/components/SidePage/SidePage.styles.d.ts +1 -0
  12. package/components/SidePage/SidePage.styles.js +19 -16
  13. package/components/SidePage/SidePage.styles.js.map +1 -1
  14. package/components/SidePage/SidePageHeader.js +3 -0
  15. package/components/SidePage/SidePageHeader.js.map +1 -1
  16. package/components/TokenInput/TokenInput.d.ts +17 -16
  17. package/components/TokenInput/TokenInput.js +202 -59
  18. package/components/TokenInput/TokenInput.js.map +1 -1
  19. package/components/TokenInput/TokenInputFailedMenu.d.ts +17 -0
  20. package/components/TokenInput/TokenInputFailedMenu.js +30 -0
  21. package/components/TokenInput/TokenInputFailedMenu.js.map +1 -0
  22. package/components/TokenInput/TokenInputMenu.d.ts +13 -2
  23. package/components/TokenInput/TokenInputMenu.js +134 -19
  24. package/components/TokenInput/TokenInputMenu.js.map +1 -1
  25. package/components/TokenInput/TokenInputMobileMenu.js +3 -2
  26. package/components/TokenInput/TokenInputMobileMenu.js.map +1 -1
  27. package/components/TokenInput/TokenInputReducer.d.ts +6 -1
  28. package/components/TokenInput/TokenInputReducer.js +14 -3
  29. package/components/TokenInput/TokenInputReducer.js.map +1 -1
  30. package/components/TokenInput/locale/locales/en.js +1 -0
  31. package/components/TokenInput/locale/locales/en.js.map +1 -1
  32. package/components/TokenInput/locale/locales/ru.js +1 -0
  33. package/components/TokenInput/locale/locales/ru.js.map +1 -1
  34. package/components/TokenInput/locale/types.d.ts +1 -0
  35. package/components/TokenInput/locale/types.js.map +1 -1
  36. package/internal/Popup/Popup.js.map +1 -1
  37. package/internal/themes/BasicTheme.d.ts +15 -0
  38. package/internal/themes/BasicTheme.js +21 -0
  39. package/internal/themes/BasicTheme.js.map +1 -1
  40. package/internal/themes/DarkTheme6_0.js +1 -0
  41. package/internal/themes/DarkTheme6_0.js.map +1 -1
  42. package/internal/themes/DarkTheme6_4.d.ts +1 -0
  43. package/internal/themes/DarkTheme6_4.js +44 -0
  44. package/internal/themes/DarkTheme6_4.js.map +1 -0
  45. package/internal/themes/LightTheme6_4.d.ts +1 -0
  46. package/internal/themes/LightTheme6_4.js +44 -0
  47. package/internal/themes/LightTheme6_4.js.map +1 -0
  48. package/lib/theming/ThemeVersions.d.ts +1 -1
  49. package/lib/theming/ThemeVersions.js.map +1 -1
  50. package/lib/theming/themes/DarkTheme.d.ts +1 -0
  51. package/lib/theming/themes/DarkTheme.js +3 -1
  52. package/lib/theming/themes/DarkTheme.js.map +1 -1
  53. package/lib/theming/themes/LightTheme.d.ts +1 -0
  54. package/lib/theming/themes/LightTheme.js +3 -1
  55. package/lib/theming/themes/LightTheme.js.map +1 -1
  56. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"SidePageHeader.js","sourceRoot":"","sources":["SidePageHeader.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Emotion } from '@emotion/css/create-instance';\nimport throttle from 'lodash.throttle';\nimport React, { type JSX } from 'react';\n\nimport type { CommonProps } from '../../internal/CommonWrapper/index.js';\nimport { CommonWrapper } from '../../internal/CommonWrapper/index.js';\nimport { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';\nimport type { TGetRootNode, TSetRootNode } from '../../lib/rootNode/index.js';\nimport { getRootNode, rootNode } from '../../lib/rootNode/index.js';\nimport type { Theme } from '../../lib/theming/Theme.js';\nimport { ThemeContext } from '../../lib/theming/ThemeContext.js';\nimport { isFunction } from '../../lib/utils.js';\nimport { ModalSeparator } from '../Modal/ModalSeparator.js';\nimport { responsiveLayout } from '../ResponsiveLayout/decorator.js';\nimport { Sticky } from '../Sticky/index.js';\nimport { getStyles } from './SidePage.styles.js';\nimport { SidePageCloseButton } from './SidePageCloseButton.js';\nimport { SidePageContext } from './SidePageContext.js';\nimport type { SidePageContextType } from './SidePageContext.js';\n\nexport interface SidePageHeaderProps extends Omit<CommonProps, 'children'> {\n children?: React.ReactNode | ((fixed: boolean) => React.ReactNode);\n /** Закрепляет заголовок сайдпейджа при скролле длинной контент-зоны.\n */\n sticky?: boolean;\n\n /** Определяет, нужно ли показывать разделитель ModalSeparator. */\n hasSeparator?: boolean;\n\n /**\n * Обрезает длинный заголовок. Работает, если включен проп `sticky`.\n * @default false.\n */\n cutTitleOnStuck?: boolean;\n}\n\nexport interface SidePageHeaderState {\n isNativeStuck: boolean;\n isReadyToStuck: boolean;\n}\n\nexport const SidePageHeaderDataTids = {\n root: 'SidePageHeader__root',\n close: 'SidePage__close',\n} as const;\n\n/**\n * Шапка сайдпейджа, состоит из заголовка и крестика закрытия.\n *\n * @visibleName SidePage.Header\n */\n@withRenderEnvironment\n@responsiveLayout\n@rootNode\nexport class SidePageHeader extends React.Component<SidePageHeaderProps, SidePageHeaderState> {\n public static __KONTUR_REACT_UI__ = 'SidePageHeader';\n public static displayName = 'SidePageHeader';\n\n public static contextType = SidePageContext;\n public context: SidePageContextType = this.context;\n\n private isMobileLayout!: boolean;\n\n public state: SidePageHeaderState = {\n isNativeStuck: true,\n isReadyToStuck: false,\n };\n\n public static defaultProps: Partial<SidePageHeaderProps> = {\n hasSeparator: false,\n };\n\n private theme!: Theme;\n private emotion!: Emotion;\n private cx!: Emotion['cx'];\n private styles!: ReturnType<typeof getStyles>;\n private sticky: Sticky | null = null;\n public getRootNode!: TGetRootNode;\n private setRootNode!: TSetRootNode;\n\n public componentDidMount = () => {\n getRootNode(this)?.parentNode?.addEventListener?.('scroll', this.throttleHandleScroll, true);\n this.context.setHasHeader?.();\n this.context.headerRef(this);\n };\n\n public componentWillUnmount = () => {\n getRootNode(this)?.parentNode?.removeEventListener?.('scroll', this.throttleHandleScroll, true);\n this.context.setHasHeader?.(false);\n this.context.headerRef(null);\n };\n\n private throttleHandleScroll = throttle((event: Event) => {\n const target = event.currentTarget as HTMLElement;\n if (target && typeof target.scrollTop === 'number') {\n this.setState({ isNativeStuck: target.scrollTop === 0 });\n }\n this.update();\n }, 5);\n\n public update = (): void => {\n this.sticky?.reflow();\n };\n\n public render(): JSX.Element {\n this.styles = getStyles(this.emotion);\n\n return (\n <ThemeContext.Consumer>\n {(theme) => {\n this.theme = theme;\n return this.renderMain();\n }}\n </ThemeContext.Consumer>\n );\n }\n\n public getStickyProp(): boolean {\n if (typeof this.props.sticky !== 'undefined') {\n return this.props.sticky;\n }\n\n if (this.isMobileLayout) {\n return false;\n }\n\n return true;\n }\n\n private renderMain() {\n const isStickyDesktop = !this.isMobileLayout && this.getStickyProp();\n const isStickyMobile = this.isMobileLayout && this.getStickyProp();\n\n const header = this.renderHeader;\n\n return (\n <CommonWrapper rootNodeRef={this.setRootNode} {...this.props}>\n <div\n data-tid={SidePageHeaderDataTids.root}\n className={this.cx(this.styles.headerWrapper(), {\n [this.styles.headerNativeStuck(this.theme)]: this.state.isNativeStuck,\n })}\n >\n {!this.state.isNativeStuck && (isStickyDesktop || isStickyMobile) ? (\n <Sticky ref={this.stickyRef} side=\"top\">\n {header}\n </Sticky>\n ) : (\n header()\n )}\n </div>\n </CommonWrapper>\n );\n }\n\n private renderHeader = (fixed = false) => {\n const isDisplayed = this.props.hasSeparator || fixed;\n return (\n <div>\n <div\n className={this.cx(this.styles.header(this.theme), {\n [this.styles.headerFixed(this.theme)]: fixed,\n [this.styles.mobileHeader(this.theme)]: this.isMobileLayout,\n })}\n >\n {this.renderClose(fixed)}\n <div\n className={this.cx(this.styles.title(this.theme), {\n [this.styles.mobileTitle(this.theme)]: this.isMobileLayout,\n [this.styles.titleCut()]: fixed && this.props.cutTitleOnStuck,\n })}\n >\n {isFunction(this.props.children) ? this.props.children(fixed) : this.props.children}\n </div>\n </div>\n {isDisplayed && <ModalSeparator fixed={fixed} />}\n </div>\n );\n };\n\n private renderClose = (fixed: boolean) => {\n const stickyOffset = parseInt(this.theme.sidePageHeaderStickyOffset);\n return (\n <div\n className={this.cx(this.styles.wrapperClose(this.theme), {\n [this.styles.wrapperCloseFixed(this.theme)]: fixed,\n [this.styles.mobileWrapperClose(this.theme)]: this.isMobileLayout,\n })}\n >\n {!this.isMobileLayout ? (\n <Sticky side=\"top\" offset={stickyOffset}>\n <SidePageCloseButton isHeaderFixed={fixed} />\n </Sticky>\n ) : (\n <SidePageCloseButton isHeaderFixed={fixed} isMobile={this.isMobileLayout} />\n )}\n </div>\n );\n };\n\n private stickyRef = (el: Sticky | null) => {\n this.sticky = el;\n };\n}\n"]}
1
+ {"version":3,"file":"SidePageHeader.js","sourceRoot":"","sources":["SidePageHeader.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { Emotion } from '@emotion/css/create-instance';\nimport throttle from 'lodash.throttle';\nimport React, { type JSX } from 'react';\n\nimport type { CommonProps } from '../../internal/CommonWrapper/index.js';\nimport { CommonWrapper } from '../../internal/CommonWrapper/index.js';\nimport { withRenderEnvironment } from '../../lib/renderEnvironment/index.js';\nimport type { TGetRootNode, TSetRootNode } from '../../lib/rootNode/index.js';\nimport { getRootNode, rootNode } from '../../lib/rootNode/index.js';\nimport type { Theme } from '../../lib/theming/Theme.js';\nimport { ThemeContext } from '../../lib/theming/ThemeContext.js';\nimport { isThemeGTE } from '../../lib/theming/ThemeHelpers.js';\nimport { isFunction } from '../../lib/utils.js';\nimport { ModalSeparator } from '../Modal/ModalSeparator.js';\nimport { responsiveLayout } from '../ResponsiveLayout/decorator.js';\nimport { Sticky } from '../Sticky/index.js';\nimport { getStyles } from './SidePage.styles.js';\nimport { SidePageCloseButton } from './SidePageCloseButton.js';\nimport { SidePageContext } from './SidePageContext.js';\nimport type { SidePageContextType } from './SidePageContext.js';\n\nexport interface SidePageHeaderProps extends Omit<CommonProps, 'children'> {\n children?: React.ReactNode | ((fixed: boolean) => React.ReactNode);\n /** Закрепляет заголовок сайдпейджа при скролле длинной контент-зоны.\n */\n sticky?: boolean;\n\n /** Определяет, нужно ли показывать разделитель ModalSeparator. */\n hasSeparator?: boolean;\n\n /**\n * Обрезает длинный заголовок. Работает, если включен проп `sticky`.\n * @default false.\n */\n cutTitleOnStuck?: boolean;\n}\n\nexport interface SidePageHeaderState {\n isNativeStuck: boolean;\n isReadyToStuck: boolean;\n}\n\nexport const SidePageHeaderDataTids = {\n root: 'SidePageHeader__root',\n close: 'SidePage__close',\n} as const;\n\n/**\n * Шапка сайдпейджа, состоит из заголовка и крестика закрытия.\n *\n * @visibleName SidePage.Header\n */\n@withRenderEnvironment\n@responsiveLayout\n@rootNode\nexport class SidePageHeader extends React.Component<SidePageHeaderProps, SidePageHeaderState> {\n public static __KONTUR_REACT_UI__ = 'SidePageHeader';\n public static displayName = 'SidePageHeader';\n\n public static contextType = SidePageContext;\n public context: SidePageContextType = this.context;\n\n private isMobileLayout!: boolean;\n\n public state: SidePageHeaderState = {\n isNativeStuck: true,\n isReadyToStuck: false,\n };\n\n public static defaultProps: Partial<SidePageHeaderProps> = {\n hasSeparator: false,\n };\n\n private theme!: Theme;\n private emotion!: Emotion;\n private cx!: Emotion['cx'];\n private styles!: ReturnType<typeof getStyles>;\n private sticky: Sticky | null = null;\n public getRootNode!: TGetRootNode;\n private setRootNode!: TSetRootNode;\n\n public componentDidMount = () => {\n getRootNode(this)?.parentNode?.addEventListener?.('scroll', this.throttleHandleScroll, true);\n this.context.setHasHeader?.();\n this.context.headerRef(this);\n };\n\n public componentWillUnmount = () => {\n getRootNode(this)?.parentNode?.removeEventListener?.('scroll', this.throttleHandleScroll, true);\n this.context.setHasHeader?.(false);\n this.context.headerRef(null);\n };\n\n private throttleHandleScroll = throttle((event: Event) => {\n const target = event.currentTarget as HTMLElement;\n if (target && typeof target.scrollTop === 'number') {\n this.setState({ isNativeStuck: target.scrollTop === 0 });\n }\n this.update();\n }, 5);\n\n public update = (): void => {\n this.sticky?.reflow();\n };\n\n public render(): JSX.Element {\n this.styles = getStyles(this.emotion);\n\n return (\n <ThemeContext.Consumer>\n {(theme) => {\n this.theme = theme;\n return this.renderMain();\n }}\n </ThemeContext.Consumer>\n );\n }\n\n public getStickyProp(): boolean {\n if (typeof this.props.sticky !== 'undefined') {\n return this.props.sticky;\n }\n\n if (this.isMobileLayout) {\n return false;\n }\n\n return true;\n }\n\n private renderMain() {\n const isStickyDesktop = !this.isMobileLayout && this.getStickyProp();\n const isStickyMobile = this.isMobileLayout && this.getStickyProp();\n\n const header = this.renderHeader;\n\n return (\n <CommonWrapper rootNodeRef={this.setRootNode} {...this.props}>\n <div\n data-tid={SidePageHeaderDataTids.root}\n className={this.cx(this.styles.headerWrapper(), {\n [this.styles.headerNativeStuck(this.theme)]: this.state.isNativeStuck,\n })}\n >\n {!this.state.isNativeStuck && (isStickyDesktop || isStickyMobile) ? (\n <Sticky ref={this.stickyRef} side=\"top\">\n {header}\n </Sticky>\n ) : (\n header()\n )}\n </div>\n </CommonWrapper>\n );\n }\n\n private renderHeader = (fixed = false) => {\n const isDisplayed = this.props.hasSeparator || fixed;\n return (\n <div>\n <div\n className={this.cx(this.styles.header(this.theme), {\n [this.styles.headerFixed(this.theme)]: fixed,\n [this.styles.mobileHeader(this.theme)]: this.isMobileLayout,\n })}\n >\n {this.renderClose(fixed)}\n <div\n className={this.cx(this.styles.title(this.theme), {\n [this.styles.mobileTitle(this.theme)]: this.isMobileLayout,\n [this.styles.titleCut()]: fixed && this.props.cutTitleOnStuck,\n })}\n >\n {isFunction(this.props.children) ? this.props.children(fixed) : this.props.children}\n </div>\n </div>\n {isDisplayed && <ModalSeparator fixed={fixed} />}\n </div>\n );\n };\n\n private renderClose = (fixed: boolean) => {\n const themeGTE6_4 = isThemeGTE(this.theme, '6.4');\n const stickyOffset = parseInt(this.theme.sidePageHeaderStickyOffset);\n return (\n <div\n className={this.cx(this.styles.wrapperClose(this.theme), {\n [this.styles.wrapperClose6_4()]: themeGTE6_4,\n [this.styles.wrapperCloseFixed(this.theme)]: fixed,\n [this.styles.mobileWrapperClose(this.theme)]: this.isMobileLayout,\n })}\n >\n {!this.isMobileLayout ? (\n <Sticky side=\"top\" offset={stickyOffset}>\n <SidePageCloseButton isHeaderFixed={fixed} />\n </Sticky>\n ) : (\n <SidePageCloseButton isHeaderFixed={fixed} isMobile={this.isMobileLayout} />\n )}\n </div>\n );\n };\n\n private stickyRef = (el: Sticky | null) => {\n this.sticky = el;\n };\n}\n"]}
@@ -4,6 +4,7 @@ import type { CommonProps } from '../../internal/CommonWrapper/index.js';
4
4
  import type { TGetRootNode } from '../../lib/rootNode/index.js';
5
5
  import type { MenuItemState } from '../MenuItem/index.js';
6
6
  import type { TokenProps, TokenSize } from '../Token/index.js';
7
+ import type { TokenInputInternalState } from './TokenInputReducer.js';
7
8
  export declare enum TokenInputType {
8
9
  WithReference = 0,
9
10
  WithoutReference = 1,
@@ -96,6 +97,9 @@ export interface TokenInputProps<T> extends CommonProps, Pick<AriaAttributes, 'a
96
97
  * Если при потере фокуса в выпадающем списке будет только один элемент и результат `valueToString` с этим элементом будет совпадать со значением в текстовом поле, то сработает `onValueChange` со значением данного элемента.
97
98
  * Сама функция также может вернуть значение, не равное undefined, с которым будет вызван `onValueChange`. Если возвращаемое значение будет равно null, то сработает очистка текущего значения поля, а в режиме редактирования токен будет удален. */
98
99
  onUnexpectedInput?: (value: string) => void | null | undefined | T;
100
+ /** Задаёт функцию, которая проверяет, можно ли создать токен из свободного ввода.
101
+ * Если вернуть `false`, токен не создаётся и поле мигает. Не применяется при выборе из справочника. */
102
+ isTokenValid?: (value: string) => boolean;
99
103
  /** Задаёт типы вводимых данных. Передаёт браузеру информацию о том, какой набор символов показать при вводе данных в конкретное поле на устройствах с экранной клавиатурой. */
100
104
  inputMode?: React.HTMLAttributes<HTMLTextAreaElement>['inputMode'];
101
105
  /**
@@ -119,19 +123,7 @@ export interface TokenInputState<T> {
119
123
  showMobilePopup?: boolean;
120
124
  }
121
125
  export type TokenInputExtendedItem<T> = T | (() => React.ReactElement<T>) | React.ReactElement<T>;
122
- export declare const DefaultState: {
123
- inputValue: string;
124
- reservedInputValue: undefined;
125
- autocompleteItems: undefined;
126
- activeTokens: never[];
127
- editingTokenIndex: number;
128
- inFocus: boolean;
129
- loading: boolean;
130
- preventBlur: boolean;
131
- inputValueWidth: number;
132
- inputValueHeight: number;
133
- showMobilePopup: boolean;
134
- };
126
+ export declare const DefaultState: TokenInputInternalState<any>;
135
127
  export declare const TokenInputDataTids: {
136
128
  readonly root: "TokenInput__root";
137
129
  readonly tokenInputMenu: "TokenInputMenu__root";
@@ -140,14 +132,14 @@ export declare const TokenInputDataTids: {
140
132
  type DefaultProps<T> = Required<Pick<TokenInputProps<T>, 'selectedItems' | 'delimiters' | 'renderItem' | 'renderValue' | 'valueToString' | 'valueToItem' | 'itemToId' | 'onValueChange' | 'width' | 'onBlur' | 'onFocus' | 'onMouseEnter' | 'onMouseLeave' | 'menuWidth' | 'menuAlign'>>;
141
133
  /** Поле с токенами — это поле ввода со списком подсказок. Значения в поле отображаются в виде отдельных токенов.
142
134
  */
143
- export declare class TokenInput<T = string> extends React.PureComponent<TokenInputProps<T>, TokenInputState<T>> {
135
+ export declare class TokenInput<T = string> extends React.PureComponent<TokenInputProps<T>, TokenInputInternalState<T>> {
144
136
  static __KONTUR_REACT_UI__: string;
145
137
  static displayName: string;
146
138
  static defaultProps: DefaultProps<any>;
147
139
  private getDelimiters;
148
140
  private getProps;
149
141
  private get textareaId();
150
- state: TokenInputState<T>;
142
+ state: TokenInputInternalState<T>;
151
143
  private readonly _textareaId;
152
144
  private rootId;
153
145
  private readonly locale;
@@ -166,8 +158,10 @@ export declare class TokenInput<T = string> extends React.PureComponent<TokenInp
166
158
  getRootNode: TGetRootNode;
167
159
  private setRootNode;
168
160
  private memoizedTokens;
161
+ private menuNavigatedByUser;
162
+ private requestId;
169
163
  componentDidMount(): void;
170
- componentDidUpdate(prevProps: TokenInputProps<T> & DefaultProps<T>, prevState: TokenInputState<T>): void;
164
+ componentDidUpdate(prevProps: TokenInputProps<T> & DefaultProps<T>, prevState: TokenInputInternalState<T>): void;
171
165
  private get usesMobilePopup();
172
166
  private isInlineInteractive;
173
167
  componentWillUnmount(): void;
@@ -211,6 +205,7 @@ export declare class TokenInput<T = string> extends React.PureComponent<TokenInp
211
205
  private textHelperRef;
212
206
  private inlineWrapperRef;
213
207
  private mobileWrapperRef;
208
+ private getMenuItems;
214
209
  private dispatch;
215
210
  private updateInputTextWidth;
216
211
  private handleInputFocus;
@@ -227,8 +222,14 @@ export declare class TokenInput<T = string> extends React.PureComponent<TokenInp
227
222
  private inputValueEndsWithDelimiter;
228
223
  private splitValueByDelimiters;
229
224
  private isDelimiterKeyEvent;
225
+ private canAcceptInputAsToken;
226
+ private rejectIfInvalidToken;
227
+ private hasExactAutocompleteMatch;
228
+ private createItemsFromTokens;
230
229
  private tryApplyDelimiterFromInputValue;
231
230
  private handleInputPaste;
231
+ private repeatRequest;
232
+ private cancelRequest;
232
233
  private tryGetItems;
233
234
  private handleKeyDown;
234
235
  private handleInputKeyDown;
@@ -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;