@vkontakte/vkui 7.5.3 → 7.5.4

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ChipsInputBase.d.ts","sourceRoot":"","sources":["../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,UAAU,EAAmB,0BAA0B,EAAc,MAAM,SAAS,CAAC;AAQnG,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,UAAU,EAAE,mXAsClD,0BAA0B,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,SAgQxC,CAAC"}
1
+ {"version":3,"file":"ChipsInputBase.d.ts","sourceRoot":"","sources":["../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsB/B,OAAO,KAAK,EAAE,UAAU,EAAmB,0BAA0B,EAAc,MAAM,SAAS,CAAC;AAQnG,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,UAAU,EAAE,mXAsClD,0BAA0B,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,SAsRxC,CAAC"}
@@ -147,7 +147,8 @@ export const ChipsInputBase = (_param)=>{
147
147
  removeChipOption(v, getChipOptionIndexByValueProp(v, value));
148
148
  };
149
149
  const handleRootClick = (event)=>{
150
- if (event.defaultPrevented || contains(event.currentTarget, getActiveElementByAnotherElement(event.currentTarget))) {
150
+ const activeElement = getActiveElementByAnotherElement(event.currentTarget);
151
+ if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {
151
152
  return;
152
153
  }
153
154
  if (inputRef.current) {
@@ -194,6 +195,24 @@ export const ChipsInputBase = (_param)=>{
194
195
  clearButton
195
196
  ]);
196
197
  const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;
198
+ const handleRootMouseDown = (e)=>{
199
+ // Если клик был в один из чипов, то preventDefault делать не нужно, так как не будет срабатывать выделение текста
200
+ if (isHTMLElement(e.target) && contains(listboxRef.current, e.target) && listboxRef.current !== e.target) {
201
+ return;
202
+ }
203
+ const activeElement = getActiveElementByAnotherElement(e.currentTarget);
204
+ // Когда выделен текст чипа не нужно делать preventDefault, чтобы сбросить выделение
205
+ if (contains(listboxRef.current, activeElement)) {
206
+ return;
207
+ }
208
+ // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста
209
+ if (e.target === inputRef.current) {
210
+ return;
211
+ }
212
+ // Делаем preventDefault, чтобы при клике в поле, вне инпута, высота поля не скакала от того,
213
+ // что фокус сначала пропадает из инпута, а потом возвращается
214
+ e.preventDefault();
215
+ };
197
216
  return /*#__PURE__*/ _jsx(FormField, {
198
217
  Component: "div",
199
218
  getRootRef: getRootRef,
@@ -210,6 +229,7 @@ export const ChipsInputBase = (_param)=>{
210
229
  className: className,
211
230
  maxHeight: maxHeight,
212
231
  onClick: disabled ? undefined : handleRootClick,
232
+ onMouseDown: handleRootMouseDown,
213
233
  children: /*#__PURE__*/ _jsxs("div", {
214
234
  className: classNames("vkuiChipsInputBase__host", sizeY !== 'regular' && sizeYClassNames[sizeY], withPlaceholder && "vkuiChipsInputBase__hasPlaceholder", inputValue && "vkuiChipsInputBase__hasInputValue"),
215
235
  ref: containerRef,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { isHTMLElement } from '@vkontakte/vkui-floating-ui/utils/dom';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { getHorizontalFocusGoTo, Keys } from '../../lib/accessibility';\nimport {\n contains as checkTargetIsInputEl,\n contains,\n getActiveElementByAnotherElement,\n} from '../../lib/dom';\nimport { FormField } from '../FormField/FormField';\nimport { FormFieldClearButton } from '../FormFieldClearButton/FormFieldClearButton';\nimport { Text } from '../Typography/Text/Text';\nimport { DEFAULT_INPUT_VALUE, DEFAULT_VALUE, renderChipDefault } from './constants';\nimport {\n getChipOptionIndexByHTMLElement,\n getChipOptionIndexByValueProp,\n getChipOptionValueByHTMLElement,\n getNextChipOptionIndexByNavigateToProp,\n isInputValueEmpty,\n} from './helpers';\nimport type { ChipOption, ChipOptionValue, ChipsInputBasePrivateProps, NavigateTo } from './types';\nimport styles from './ChipsInputBase.module.css';\n\nconst sizeYClassNames = {\n none: styles.sizeYNone,\n compact: styles.sizeYCompact,\n} as const;\n\nexport const ChipsInputBase = <O extends ChipOption>({\n // FormFieldProps\n getRootRef,\n style,\n className,\n before,\n after,\n status,\n mode,\n maxHeight,\n\n // option\n value = DEFAULT_VALUE,\n onAddChipOption,\n 'onRemoveChipOption': onRemoveChipOptionProp,\n renderChip = renderChipDefault,\n\n // input\n getRef,\n 'id': idProp,\n inputValue = DEFAULT_INPUT_VALUE,\n placeholder,\n disabled,\n readOnly,\n addOnBlur,\n onBlur,\n onInputChange,\n\n // clear\n ClearButton = FormFieldClearButton,\n clearButtonShown,\n clearButtonTestId,\n onClear,\n\n // a11y\n chipsListLabel = 'Выбранные элементы',\n 'aria-label': ariaLabel = '',\n ...restProps\n}: ChipsInputBasePrivateProps<O>): React.ReactNode => {\n const { sizeY = 'none' } = useAdaptivity();\n const idGenerated = React.useId();\n const inputRef = useExternRef(getRef);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const listboxRef = React.useRef<HTMLDivElement>(null);\n\n const valueLength = value.length;\n const withPlaceholder = valueLength === 0;\n const [lastFocusedChipOptionIndex, setLastFocusedChipOptionIndex] = React.useState(0);\n\n const resetChipOptionFocusToInputEl = (inputEl: HTMLInputElement) => {\n setLastFocusedChipOptionIndex(0);\n inputEl.focus();\n };\n\n const moveFocusToChipOption = (\n currentIndex: number,\n navigateTo: NavigateTo,\n listboxEl: HTMLElement,\n ) => {\n const index = getNextChipOptionIndexByNavigateToProp(currentIndex, navigateTo, valueLength);\n // eslint-disable-next-line no-restricted-properties\n const foundEl = listboxEl.querySelector<HTMLElement>(`[data-index=\"${index}\"]`);\n\n if (foundEl) {\n setLastFocusedChipOptionIndex(index);\n foundEl.focus();\n }\n };\n\n const removeChipOption = (o: O | ChipOptionValue, index: number) => {\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!inputRef.current || !listboxRef.current) {\n return;\n }\n\n if (valueLength > 1) {\n if (index === valueLength - 1) {\n moveFocusToChipOption(index, 'prev', listboxRef.current);\n } else {\n moveFocusToChipOption(index, 'next', listboxRef.current);\n }\n } else {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n\n onRemoveChipOptionProp(o);\n };\n\n const handleListboxKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const targetEl = event.target;\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (event.defaultPrevented || !listboxRef.current || !isHTMLElement(targetEl)) {\n return;\n }\n\n switch (event.key) {\n case Keys.ENTER: {\n if (\n !readOnly &&\n checkTargetIsInputEl(targetEl, inputRef.current) &&\n inputRef.current &&\n !isInputValueEmpty(inputRef.current)\n ) {\n event.preventDefault();\n onAddChipOption(inputRef.current.value);\n }\n break;\n }\n case Keys.DELETE:\n case Keys.BACKSPACE: {\n if (!readOnly && valueLength > 0) {\n if (!checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n removeChipOption(\n getChipOptionValueByHTMLElement(targetEl),\n getChipOptionIndexByHTMLElement(targetEl),\n );\n } else if (event.key === Keys.BACKSPACE && isInputValueEmpty(inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n 'last',\n listboxRef.current,\n );\n }\n }\n break;\n }\n case Keys.HOME:\n case Keys.END:\n case Keys.ARROW_UP:\n case Keys.ARROW_LEFT:\n case Keys.ARROW_DOWN:\n case Keys.ARROW_RIGHT: {\n if (valueLength !== 0 && !checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n getHorizontalFocusGoTo(event.key),\n listboxRef.current,\n );\n }\n break;\n }\n }\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(event);\n }\n\n if (addOnBlur && !event.defaultPrevented && inputRef.current) {\n onAddChipOption(inputRef.current.value);\n }\n };\n\n const handleChipRemove = (event: React.MouseEvent, v: ChipOptionValue) => {\n event.preventDefault();\n event.stopPropagation();\n removeChipOption(v, getChipOptionIndexByValueProp(v, value));\n };\n\n const handleRootClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (\n event.defaultPrevented ||\n contains(event.currentTarget, getActiveElementByAnotherElement(event.currentTarget))\n ) {\n return;\n }\n\n if (inputRef.current) {\n inputRef.current.focus();\n }\n };\n\n const handleClear = React.useCallback(() => {\n if (inputRef.current) {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n onClear();\n }, [inputRef, onClear]);\n\n const clearButton = React.useMemo(() => {\n if (clearButtonShown) {\n return (\n <ClearButton onClick={handleClear} disabled={disabled} data-testid={clearButtonTestId} />\n );\n }\n return undefined;\n }, [ClearButton, clearButtonShown, clearButtonTestId, disabled, handleClear]);\n\n const afterItems = React.useMemo(() => {\n if (clearButton || after) {\n return (\n <>\n {clearButton}\n {after}\n </>\n );\n }\n return undefined;\n }, [after, clearButton]);\n\n const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;\n\n return (\n <FormField\n Component=\"div\"\n getRootRef={getRootRef}\n // role=\"group\" добавлена, чтобы этот блок можно было найти с помощью стрелочек при использовании NVDA\n // Если убрать, то aria-label не будет читаться\n role=\"group\"\n aria-label={ariaLabel}\n style={style}\n disabled={disabled}\n before={before}\n after={afterItems}\n status={status}\n mode={mode}\n className={className}\n maxHeight={maxHeight}\n onClick={disabled ? undefined : handleRootClick}\n >\n <div\n className={classNames(\n styles.host,\n sizeY !== 'regular' && sizeYClassNames[sizeY],\n withPlaceholder && styles.hasPlaceholder,\n inputValue && styles.hasInputValue,\n )}\n ref={containerRef}\n onKeyDown={disabled ? undefined : handleListboxKeyDown}\n >\n <div\n className={styles.listBox}\n // для a11y\n ref={listboxRef}\n role=\"listbox\"\n aria-orientation=\"horizontal\"\n aria-disabled={disabled}\n aria-readonly={readOnly}\n aria-label={chipsListLabel}\n >\n {value.map((option, index) => (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderChip(\n {\n 'Component': 'div',\n 'value': option.value,\n 'label': option.label,\n 'disabled': option.disabled || disabled,\n 'readOnly': option.readOnly || readOnly,\n 'className': styles.chip,\n 'onRemove': handleChipRemove,\n // чтобы можно было легче найти этот чип в DOM\n 'data-index': index,\n 'data-value': option.value,\n 'data-value-type': typeof option.value,\n // для a11y\n 'tabIndex': lastFocusedChipOptionIndex === index ? 0 : -1,\n 'role': 'option',\n 'aria-selected': true,\n 'aria-posinset': index + 1,\n 'aria-setsize': valueLength,\n 'aria-description': 'Для удаления используйте Backspace или Delete',\n },\n option,\n )}\n </React.Fragment>\n ))}\n </div>\n <Text\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n {...restProps}\n aria-label={ariaLabel}\n Component=\"input\"\n type=\"text\"\n id={inputId}\n getRootRef={inputRef}\n className={styles.el}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={withPlaceholder ? placeholder : undefined}\n value={inputValue}\n onChange={onInputChange}\n onBlur={handleInputBlur}\n />\n </div>\n </FormField>\n );\n};\n"],"names":["React","classNames","isHTMLElement","useAdaptivity","useExternRef","getHorizontalFocusGoTo","Keys","contains","checkTargetIsInputEl","getActiveElementByAnotherElement","FormField","FormFieldClearButton","Text","DEFAULT_INPUT_VALUE","DEFAULT_VALUE","renderChipDefault","getChipOptionIndexByHTMLElement","getChipOptionIndexByValueProp","getChipOptionValueByHTMLElement","getNextChipOptionIndexByNavigateToProp","isInputValueEmpty","sizeYClassNames","none","compact","ChipsInputBase","getRootRef","style","className","before","after","status","mode","maxHeight","value","onAddChipOption","onRemoveChipOptionProp","renderChip","getRef","idProp","inputValue","placeholder","disabled","readOnly","addOnBlur","onBlur","onInputChange","ClearButton","clearButtonShown","clearButtonTestId","onClear","chipsListLabel","ariaLabel","restProps","sizeY","idGenerated","useId","inputRef","containerRef","useRef","listboxRef","valueLength","length","withPlaceholder","lastFocusedChipOptionIndex","setLastFocusedChipOptionIndex","useState","resetChipOptionFocusToInputEl","inputEl","focus","moveFocusToChipOption","currentIndex","navigateTo","listboxEl","index","foundEl","querySelector","removeChipOption","o","current","handleListboxKeyDown","event","targetEl","target","defaultPrevented","key","ENTER","preventDefault","DELETE","BACKSPACE","HOME","END","ARROW_UP","ARROW_LEFT","ARROW_DOWN","ARROW_RIGHT","handleInputBlur","handleChipRemove","v","stopPropagation","handleRootClick","currentTarget","handleClear","useCallback","clearButton","useMemo","onClick","data-testid","undefined","afterItems","inputId","Component","role","aria-label","div","ref","onKeyDown","aria-orientation","aria-disabled","aria-readonly","map","option","Fragment","label","autoCapitalize","autoComplete","autoCorrect","spellCheck","type","id","onChange"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { isHTMLElement } from '@vkontakte/vkui-floating-ui/utils/dom';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { getHorizontalFocusGoTo, Keys } from '../../lib/accessibility';\nimport {\n contains as checkTargetIsInputEl,\n contains,\n getActiveElementByAnotherElement,\n} from '../../lib/dom';\nimport { FormField } from '../FormField/FormField';\nimport { FormFieldClearButton } from '../FormFieldClearButton/FormFieldClearButton';\nimport { Text } from '../Typography/Text/Text';\nimport { DEFAULT_INPUT_VALUE, DEFAULT_VALUE, renderChipDefault } from './constants';\nimport {\n getChipOptionIndexByHTMLElement,\n getChipOptionIndexByValueProp,\n getChipOptionValueByHTMLElement,\n getNextChipOptionIndexByNavigateToProp,\n isInputValueEmpty,\n} from './helpers';\nimport type { ChipOption, ChipOptionValue, ChipsInputBasePrivateProps, NavigateTo } from './types';\nimport styles from './ChipsInputBase.module.css';\n\nconst sizeYClassNames = {\n none: styles.sizeYNone,\n compact: styles.sizeYCompact,\n} as const;\n\nexport const ChipsInputBase = <O extends ChipOption>({\n // FormFieldProps\n getRootRef,\n style,\n className,\n before,\n after,\n status,\n mode,\n maxHeight,\n\n // option\n value = DEFAULT_VALUE,\n onAddChipOption,\n 'onRemoveChipOption': onRemoveChipOptionProp,\n renderChip = renderChipDefault,\n\n // input\n getRef,\n 'id': idProp,\n inputValue = DEFAULT_INPUT_VALUE,\n placeholder,\n disabled,\n readOnly,\n addOnBlur,\n onBlur,\n onInputChange,\n\n // clear\n ClearButton = FormFieldClearButton,\n clearButtonShown,\n clearButtonTestId,\n onClear,\n\n // a11y\n chipsListLabel = 'Выбранные элементы',\n 'aria-label': ariaLabel = '',\n ...restProps\n}: ChipsInputBasePrivateProps<O>): React.ReactNode => {\n const { sizeY = 'none' } = useAdaptivity();\n const idGenerated = React.useId();\n const inputRef = useExternRef(getRef);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const listboxRef = React.useRef<HTMLDivElement>(null);\n\n const valueLength = value.length;\n const withPlaceholder = valueLength === 0;\n const [lastFocusedChipOptionIndex, setLastFocusedChipOptionIndex] = React.useState(0);\n\n const resetChipOptionFocusToInputEl = (inputEl: HTMLInputElement) => {\n setLastFocusedChipOptionIndex(0);\n inputEl.focus();\n };\n\n const moveFocusToChipOption = (\n currentIndex: number,\n navigateTo: NavigateTo,\n listboxEl: HTMLElement,\n ) => {\n const index = getNextChipOptionIndexByNavigateToProp(currentIndex, navigateTo, valueLength);\n // eslint-disable-next-line no-restricted-properties\n const foundEl = listboxEl.querySelector<HTMLElement>(`[data-index=\"${index}\"]`);\n\n if (foundEl) {\n setLastFocusedChipOptionIndex(index);\n foundEl.focus();\n }\n };\n\n const removeChipOption = (o: O | ChipOptionValue, index: number) => {\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!inputRef.current || !listboxRef.current) {\n return;\n }\n\n if (valueLength > 1) {\n if (index === valueLength - 1) {\n moveFocusToChipOption(index, 'prev', listboxRef.current);\n } else {\n moveFocusToChipOption(index, 'next', listboxRef.current);\n }\n } else {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n\n onRemoveChipOptionProp(o);\n };\n\n const handleListboxKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const targetEl = event.target;\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (event.defaultPrevented || !listboxRef.current || !isHTMLElement(targetEl)) {\n return;\n }\n\n switch (event.key) {\n case Keys.ENTER: {\n if (\n !readOnly &&\n checkTargetIsInputEl(targetEl, inputRef.current) &&\n inputRef.current &&\n !isInputValueEmpty(inputRef.current)\n ) {\n event.preventDefault();\n onAddChipOption(inputRef.current.value);\n }\n break;\n }\n case Keys.DELETE:\n case Keys.BACKSPACE: {\n if (!readOnly && valueLength > 0) {\n if (!checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n removeChipOption(\n getChipOptionValueByHTMLElement(targetEl),\n getChipOptionIndexByHTMLElement(targetEl),\n );\n } else if (event.key === Keys.BACKSPACE && isInputValueEmpty(inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n 'last',\n listboxRef.current,\n );\n }\n }\n break;\n }\n case Keys.HOME:\n case Keys.END:\n case Keys.ARROW_UP:\n case Keys.ARROW_LEFT:\n case Keys.ARROW_DOWN:\n case Keys.ARROW_RIGHT: {\n if (valueLength !== 0 && !checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n getHorizontalFocusGoTo(event.key),\n listboxRef.current,\n );\n }\n break;\n }\n }\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(event);\n }\n\n if (addOnBlur && !event.defaultPrevented && inputRef.current) {\n onAddChipOption(inputRef.current.value);\n }\n };\n\n const handleChipRemove = (event: React.MouseEvent, v: ChipOptionValue) => {\n event.preventDefault();\n event.stopPropagation();\n removeChipOption(v, getChipOptionIndexByValueProp(v, value));\n };\n\n const handleRootClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const activeElement = getActiveElementByAnotherElement(event.currentTarget);\n if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {\n return;\n }\n\n if (inputRef.current) {\n inputRef.current.focus();\n }\n };\n\n const handleClear = React.useCallback(() => {\n if (inputRef.current) {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n onClear();\n }, [inputRef, onClear]);\n\n const clearButton = React.useMemo(() => {\n if (clearButtonShown) {\n return (\n <ClearButton onClick={handleClear} disabled={disabled} data-testid={clearButtonTestId} />\n );\n }\n return undefined;\n }, [ClearButton, clearButtonShown, clearButtonTestId, disabled, handleClear]);\n\n const afterItems = React.useMemo(() => {\n if (clearButton || after) {\n return (\n <>\n {clearButton}\n {after}\n </>\n );\n }\n return undefined;\n }, [after, clearButton]);\n\n const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;\n\n const handleRootMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n // Если клик был в один из чипов, то preventDefault делать не нужно, так как не будет срабатывать выделение текста\n if (\n isHTMLElement(e.target) &&\n contains(listboxRef.current, e.target) &&\n listboxRef.current !== e.target\n ) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(e.currentTarget);\n // Когда выделен текст чипа не нужно делать preventDefault, чтобы сбросить выделение\n if (contains(listboxRef.current, activeElement)) {\n return;\n }\n // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста\n if (e.target === inputRef.current) {\n return;\n }\n // Делаем preventDefault, чтобы при клике в поле, вне инпута, высота поля не скакала от того,\n // что фокус сначала пропадает из инпута, а потом возвращается\n e.preventDefault();\n };\n\n return (\n <FormField\n Component=\"div\"\n getRootRef={getRootRef}\n // role=\"group\" добавлена, чтобы этот блок можно было найти с помощью стрелочек при использовании NVDA\n // Если убрать, то aria-label не будет читаться\n role=\"group\"\n aria-label={ariaLabel}\n style={style}\n disabled={disabled}\n before={before}\n after={afterItems}\n status={status}\n mode={mode}\n className={className}\n maxHeight={maxHeight}\n onClick={disabled ? undefined : handleRootClick}\n onMouseDown={handleRootMouseDown}\n >\n <div\n className={classNames(\n styles.host,\n sizeY !== 'regular' && sizeYClassNames[sizeY],\n withPlaceholder && styles.hasPlaceholder,\n inputValue && styles.hasInputValue,\n )}\n ref={containerRef}\n onKeyDown={disabled ? undefined : handleListboxKeyDown}\n >\n <div\n className={styles.listBox}\n // для a11y\n ref={listboxRef}\n role=\"listbox\"\n aria-orientation=\"horizontal\"\n aria-disabled={disabled}\n aria-readonly={readOnly}\n aria-label={chipsListLabel}\n >\n {value.map((option, index) => (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderChip(\n {\n 'Component': 'div',\n 'value': option.value,\n 'label': option.label,\n 'disabled': option.disabled || disabled,\n 'readOnly': option.readOnly || readOnly,\n 'className': styles.chip,\n 'onRemove': handleChipRemove,\n // чтобы можно было легче найти этот чип в DOM\n 'data-index': index,\n 'data-value': option.value,\n 'data-value-type': typeof option.value,\n // для a11y\n 'tabIndex': lastFocusedChipOptionIndex === index ? 0 : -1,\n 'role': 'option',\n 'aria-selected': true,\n 'aria-posinset': index + 1,\n 'aria-setsize': valueLength,\n 'aria-description': 'Для удаления используйте Backspace или Delete',\n },\n option,\n )}\n </React.Fragment>\n ))}\n </div>\n <Text\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n {...restProps}\n aria-label={ariaLabel}\n Component=\"input\"\n type=\"text\"\n id={inputId}\n getRootRef={inputRef}\n className={styles.el}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={withPlaceholder ? placeholder : undefined}\n value={inputValue}\n onChange={onInputChange}\n onBlur={handleInputBlur}\n />\n </div>\n </FormField>\n );\n};\n"],"names":["React","classNames","isHTMLElement","useAdaptivity","useExternRef","getHorizontalFocusGoTo","Keys","contains","checkTargetIsInputEl","getActiveElementByAnotherElement","FormField","FormFieldClearButton","Text","DEFAULT_INPUT_VALUE","DEFAULT_VALUE","renderChipDefault","getChipOptionIndexByHTMLElement","getChipOptionIndexByValueProp","getChipOptionValueByHTMLElement","getNextChipOptionIndexByNavigateToProp","isInputValueEmpty","sizeYClassNames","none","compact","ChipsInputBase","getRootRef","style","className","before","after","status","mode","maxHeight","value","onAddChipOption","onRemoveChipOptionProp","renderChip","getRef","idProp","inputValue","placeholder","disabled","readOnly","addOnBlur","onBlur","onInputChange","ClearButton","clearButtonShown","clearButtonTestId","onClear","chipsListLabel","ariaLabel","restProps","sizeY","idGenerated","useId","inputRef","containerRef","useRef","listboxRef","valueLength","length","withPlaceholder","lastFocusedChipOptionIndex","setLastFocusedChipOptionIndex","useState","resetChipOptionFocusToInputEl","inputEl","focus","moveFocusToChipOption","currentIndex","navigateTo","listboxEl","index","foundEl","querySelector","removeChipOption","o","current","handleListboxKeyDown","event","targetEl","target","defaultPrevented","key","ENTER","preventDefault","DELETE","BACKSPACE","HOME","END","ARROW_UP","ARROW_LEFT","ARROW_DOWN","ARROW_RIGHT","handleInputBlur","handleChipRemove","v","stopPropagation","handleRootClick","activeElement","currentTarget","handleClear","useCallback","clearButton","useMemo","onClick","data-testid","undefined","afterItems","inputId","handleRootMouseDown","e","Component","role","aria-label","onMouseDown","div","ref","onKeyDown","aria-orientation","aria-disabled","aria-readonly","map","option","Fragment","label","autoCapitalize","autoComplete","autoCorrect","spellCheck","type","id","onChange"],"mappings":"AAAA;;;;;AAEA,YAAYA,WAAW,QAAQ;AAC/B,SAASC,UAAU,QAAQ,kBAAkB;AAC7C,SAASC,aAAa,QAAQ,wCAAwC;AACtE,SAASC,aAAa,QAAQ,+BAA4B;AAC1D,SAASC,YAAY,QAAQ,8BAA2B;AACxD,SAASC,sBAAsB,EAAEC,IAAI,QAAQ,6BAA0B;AACvE,SACEC,YAAYC,oBAAoB,EAChCD,QAAQ,EACRE,gCAAgC,QAC3B,mBAAgB;AACvB,SAASC,SAAS,QAAQ,4BAAyB;AACnD,SAASC,oBAAoB,QAAQ,kDAA+C;AACpF,SAASC,IAAI,QAAQ,6BAA0B;AAC/C,SAASC,mBAAmB,EAAEC,aAAa,EAAEC,iBAAiB,QAAQ,iBAAc;AACpF,SACEC,+BAA+B,EAC/BC,6BAA6B,EAC7BC,+BAA+B,EAC/BC,sCAAsC,EACtCC,iBAAiB,QACZ,eAAY;AAInB,MAAMC,kBAAkB;IACtBC,IAAI;IACJC,OAAO;AACT;AAEA,OAAO,MAAMC,iBAAiB;QAAuB,EACnD,iBAAiB;IACjBC,UAAU,EACVC,KAAK,EACLC,SAAS,EACTC,MAAM,EACNC,KAAK,EACLC,MAAM,EACNC,IAAI,EACJC,SAAS,EAET,SAAS;IACTC,QAAQnB,aAAa,EACrBoB,eAAe,EACf,sBAAsBC,sBAAsB,EAC5CC,aAAarB,iBAAiB,EAE9B,QAAQ;IACRsB,MAAM,EACN,MAAMC,MAAM,EACZC,aAAa1B,mBAAmB,EAChC2B,WAAW,EACXC,QAAQ,EACRC,QAAQ,EACRC,SAAS,EACTC,MAAM,EACNC,aAAa,EAEb,QAAQ;IACRC,cAAcnC,oBAAoB,EAClCoC,gBAAgB,EAChBC,iBAAiB,EACjBC,OAAO,EAEP,OAAO;IACPC,iBAAiB,oBAAoB,EACrC,cAAcC,YAAY,EAAE,EAEE,WAD3BC;QAnCH3B;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QAGAC;QACAC;QACA;QACAE;QAGAC;QACA;QACAE;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QAGAC;QACAC;QACAC;QACAC;QAGAC;QACA;;IAGA,MAAM,EAAEG,QAAQ,MAAM,EAAE,GAAGlD;IAC3B,MAAMmD,cAActD,MAAMuD,KAAK;IAC/B,MAAMC,WAAWpD,aAAaiC;IAC9B,MAAMoB,eAAezD,MAAM0D,MAAM,CAAiB;IAClD,MAAMC,aAAa3D,MAAM0D,MAAM,CAAiB;IAEhD,MAAME,cAAc3B,MAAM4B,MAAM;IAChC,MAAMC,kBAAkBF,gBAAgB;IACxC,MAAM,CAACG,4BAA4BC,8BAA8B,GAAGhE,MAAMiE,QAAQ,CAAC;IAEnF,MAAMC,gCAAgC,CAACC;QACrCH,8BAA8B;QAC9BG,QAAQC,KAAK;IACf;IAEA,MAAMC,wBAAwB,CAC5BC,cACAC,YACAC;QAEA,MAAMC,QAAQtD,uCAAuCmD,cAAcC,YAAYX;QAC/E,oDAAoD;QACpD,MAAMc,UAAUF,UAAUG,aAAa,CAAc,CAAC,aAAa,EAAEF,MAAM,EAAE,CAAC;QAE9E,IAAIC,SAAS;YACXV,8BAA8BS;YAC9BC,QAAQN,KAAK;QACf;IACF;IAEA,MAAMQ,mBAAmB,CAACC,GAAwBJ;QAChD,6EAA6E,GAC7E,IAAI,CAACjB,SAASsB,OAAO,IAAI,CAACnB,WAAWmB,OAAO,EAAE;YAC5C;QACF;QAEA,IAAIlB,cAAc,GAAG;YACnB,IAAIa,UAAUb,cAAc,GAAG;gBAC7BS,sBAAsBI,OAAO,QAAQd,WAAWmB,OAAO;YACzD,OAAO;gBACLT,sBAAsBI,OAAO,QAAQd,WAAWmB,OAAO;YACzD;QACF,OAAO;YACLZ,8BAA8BV,SAASsB,OAAO;QAChD;QAEA3C,uBAAuB0C;IACzB;IAEA,MAAME,uBAAuB,CAACC;QAC5B,MAAMC,WAAWD,MAAME,MAAM;QAC7B,6EAA6E,GAC7E,IAAIF,MAAMG,gBAAgB,IAAI,CAACxB,WAAWmB,OAAO,IAAI,CAAC5E,cAAc+E,WAAW;YAC7E;QACF;QAEA,OAAQD,MAAMI,GAAG;YACf,KAAK9E,KAAK+E,KAAK;gBAAE;oBACf,IACE,CAAC3C,YACDlC,qBAAqByE,UAAUzB,SAASsB,OAAO,KAC/CtB,SAASsB,OAAO,IAChB,CAAC1D,kBAAkBoC,SAASsB,OAAO,GACnC;wBACAE,MAAMM,cAAc;wBACpBpD,gBAAgBsB,SAASsB,OAAO,CAAC7C,KAAK;oBACxC;oBACA;gBACF;YACA,KAAK3B,KAAKiF,MAAM;YAChB,KAAKjF,KAAKkF,SAAS;gBAAE;oBACnB,IAAI,CAAC9C,YAAYkB,cAAc,GAAG;wBAChC,IAAI,CAACpD,qBAAqByE,UAAUzB,SAASsB,OAAO,GAAG;4BACrDE,MAAMM,cAAc;4BACpBV,iBACE1D,gCAAgC+D,WAChCjE,gCAAgCiE;wBAEpC,OAAO,IAAID,MAAMI,GAAG,KAAK9E,KAAKkF,SAAS,IAAIpE,kBAAkBoC,SAASsB,OAAO,GAAG;4BAC9EE,MAAMM,cAAc;4BACpBjB,sBACErD,gCAAgCiE,WAChC,QACAtB,WAAWmB,OAAO;wBAEtB;oBACF;oBACA;gBACF;YACA,KAAKxE,KAAKmF,IAAI;YACd,KAAKnF,KAAKoF,GAAG;YACb,KAAKpF,KAAKqF,QAAQ;YAClB,KAAKrF,KAAKsF,UAAU;YACpB,KAAKtF,KAAKuF,UAAU;YACpB,KAAKvF,KAAKwF,WAAW;gBAAE;oBACrB,IAAIlC,gBAAgB,KAAK,CAACpD,qBAAqByE,UAAUzB,SAASsB,OAAO,GAAG;wBAC1EE,MAAMM,cAAc;wBACpBjB,sBACErD,gCAAgCiE,WAChC5E,uBAAuB2E,MAAMI,GAAG,GAChCzB,WAAWmB,OAAO;oBAEtB;oBACA;gBACF;QACF;IACF;IAEA,MAAMiB,kBAAkB,CAACf;QACvB,IAAIpC,QAAQ;YACVA,OAAOoC;QACT;QAEA,IAAIrC,aAAa,CAACqC,MAAMG,gBAAgB,IAAI3B,SAASsB,OAAO,EAAE;YAC5D5C,gBAAgBsB,SAASsB,OAAO,CAAC7C,KAAK;QACxC;IACF;IAEA,MAAM+D,mBAAmB,CAAChB,OAAyBiB;QACjDjB,MAAMM,cAAc;QACpBN,MAAMkB,eAAe;QACrBtB,iBAAiBqB,GAAGhF,8BAA8BgF,GAAGhE;IACvD;IAEA,MAAMkE,kBAAkB,CAACnB;QACvB,MAAMoB,gBAAgB3F,iCAAiCuE,MAAMqB,aAAa;QAC1E,IAAIrB,MAAMG,gBAAgB,IAAI5E,SAASyE,MAAMqB,aAAa,EAAED,gBAAgB;YAC1E;QACF;QAEA,IAAI5C,SAASsB,OAAO,EAAE;YACpBtB,SAASsB,OAAO,CAACV,KAAK;QACxB;IACF;IAEA,MAAMkC,cAActG,MAAMuG,WAAW,CAAC;QACpC,IAAI/C,SAASsB,OAAO,EAAE;YACpBZ,8BAA8BV,SAASsB,OAAO;QAChD;QACA7B;IACF,GAAG;QAACO;QAAUP;KAAQ;IAEtB,MAAMuD,cAAcxG,MAAMyG,OAAO,CAAC;QAChC,IAAI1D,kBAAkB;YACpB,qBACE,KAACD;gBAAY4D,SAASJ;gBAAa7D,UAAUA;gBAAUkE,eAAa3D;;QAExE;QACA,OAAO4D;IACT,GAAG;QAAC9D;QAAaC;QAAkBC;QAAmBP;QAAU6D;KAAY;IAE5E,MAAMO,aAAa7G,MAAMyG,OAAO,CAAC;QAC/B,IAAID,eAAe3E,OAAO;YACxB,qBACE;;oBACG2E;oBACA3E;;;QAGP;QACA,OAAO+E;IACT,GAAG;QAAC/E;QAAO2E;KAAY;IAEvB,MAAMM,UAAUxE,UAAU,CAAC,8BAA8B,EAAEgB,aAAa;IAExE,MAAMyD,sBAAsB,CAACC;QAC3B,kHAAkH;QAClH,IACE9G,cAAc8G,EAAE9B,MAAM,KACtB3E,SAASoD,WAAWmB,OAAO,EAAEkC,EAAE9B,MAAM,KACrCvB,WAAWmB,OAAO,KAAKkC,EAAE9B,MAAM,EAC/B;YACA;QACF;QACA,MAAMkB,gBAAgB3F,iCAAiCuG,EAAEX,aAAa;QACtE,oFAAoF;QACpF,IAAI9F,SAASoD,WAAWmB,OAAO,EAAEsB,gBAAgB;YAC/C;QACF;QACA,qGAAqG;QACrG,IAAIY,EAAE9B,MAAM,KAAK1B,SAASsB,OAAO,EAAE;YACjC;QACF;QACA,6FAA6F;QAC7F,8DAA8D;QAC9DkC,EAAE1B,cAAc;IAClB;IAEA,qBACE,KAAC5E;QACCuG,WAAU;QACVxF,YAAYA;QACZ,sGAAsG;QACtG,+CAA+C;QAC/CyF,MAAK;QACLC,cAAYhE;QACZzB,OAAOA;QACPe,UAAUA;QACVb,QAAQA;QACRC,OAAOgF;QACP/E,QAAQA;QACRC,MAAMA;QACNJ,WAAWA;QACXK,WAAWA;QACX0E,SAASjE,WAAWmE,YAAYT;QAChCiB,aAAaL;kBAEb,cAAA,MAACM;YACC1F,WAAW1B,uCAEToD,UAAU,aAAahC,eAAe,CAACgC,MAAM,EAC7CS,yDACAvB;YAEF+E,KAAK7D;YACL8D,WAAW9E,WAAWmE,YAAY7B;;8BAElC,KAACsC;oBACC1F,SAAS;oBACT,WAAW;oBACX2F,KAAK3D;oBACLuD,MAAK;oBACLM,oBAAiB;oBACjBC,iBAAehF;oBACfiF,iBAAehF;oBACfyE,cAAYjE;8BAEXjB,MAAM0F,GAAG,CAAC,CAACC,QAAQnD,sBAClB,KAACzE,MAAM6H,QAAQ;sCACZzF,WACC;gCACE,aAAa;gCACb,SAASwF,OAAO3F,KAAK;gCACrB,SAAS2F,OAAOE,KAAK;gCACrB,YAAYF,OAAOnF,QAAQ,IAAIA;gCAC/B,YAAYmF,OAAOlF,QAAQ,IAAIA;gCAC/B,WAAW;gCACX,YAAYsD;gCACZ,8CAA8C;gCAC9C,cAAcvB;gCACd,cAAcmD,OAAO3F,KAAK;gCAC1B,mBAAmB,OAAO2F,OAAO3F,KAAK;gCACtC,WAAW;gCACX,YAAY8B,+BAA+BU,QAAQ,IAAI,CAAC;gCACxD,QAAQ;gCACR,iBAAiB;gCACjB,iBAAiBA,QAAQ;gCACzB,gBAAgBb;gCAChB,oBAAoB;4BACtB,GACAgE;2BAtBiB,GAAG,OAAOA,OAAO3F,KAAK,CAAC,CAAC,EAAE2F,OAAO3F,KAAK,EAAE;;8BA2BjE,KAACrB;oBACCmH,gBAAe;oBACfC,cAAa;oBACbC,aAAY;oBACZC,YAAY;mBACR9E;oBACJ+D,cAAYhE;oBACZ8D,WAAU;oBACVkB,MAAK;oBACLC,IAAItB;oBACJrF,YAAY+B;oBACZ7B,SAAS;oBACTc,UAAUA;oBACVC,UAAUA;oBACVF,aAAasB,kBAAkBtB,cAAcoE;oBAC7C3E,OAAOM;oBACP8F,UAAUxF;oBACVD,QAAQmD;;;;;AAKlB,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"file":"ChipsSelect.d.ts","sourceRoot":"","sources":["../../../src/components/ChipsSelect/ChipsSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAa7D,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAkC5E,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,UAAU,CACpD,SAAQ,mBAAmB,CAAC,CAAC,CAAC,EAC5B,mBAAmB,CAAC,CAAC,CAAC,EACtB,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC,EAClD,IAAI,CAAC,yBAAyB,EAAE,oBAAoB,CAAC;IACvD;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,EAChB,sBAAsB,GACvB,EAAE;QACD,sBAAsB,EAAE,KAAK,CAAC,SAAS,CAAC;KACzC,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAEnF;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,UAAU,EAAE,yuBAsDpD,gBAAgB,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,SAwanC,CAAC"}
1
+ {"version":3,"file":"ChipsSelect.d.ts","sourceRoot":"","sources":["../../../src/components/ChipsSelect/ChipsSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAa7D,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAkC5E,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,UAAU,CACpD,SAAQ,mBAAmB,CAAC,CAAC,CAAC,EAC5B,mBAAmB,CAAC,CAAC,CAAC,EACtB,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC,EAClD,IAAI,CAAC,yBAAyB,EAAE,oBAAoB,CAAC;IACvD;;OAEG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC7B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;OAEG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;;OAEG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,EAChB,sBAAsB,GACvB,EAAE;QACD,sBAAsB,EAAE,KAAK,CAAC,SAAS,CAAC;KACzC,KAAK,KAAK,CAAC,SAAS,CAAC;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAEnF;;OAEG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,MAAM,SAAS,UAAU,EAAE,yuBAsDpD,gBAAgB,CAAC,MAAM,CAAC,KAAG,KAAK,CAAC,SAsanC,CAAC"}
@@ -271,10 +271,8 @@ const findIndexBefore = (options = [], endIndex = options.length)=>{
271
271
  ]);
272
272
  useGlobalOnEventOutside('mousedown', handleClickOutside, opened ? rootRef : null, opened ? dropdownScrollBoxRef : null);
273
273
  const onDropdownIconClick = React.useCallback((e)=>{
274
- if (opened) {
275
- e.preventDefault();
276
- setOpened(false);
277
- }
274
+ e.preventDefault();
275
+ setOpened(!opened);
278
276
  }, [
279
277
  opened,
280
278
  setOpened
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/ChipsSelect/ChipsSelect.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { type MouseEventHandler } from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useGlobalOnEventOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { Keys } from '../../lib/accessibility';\nimport type { Placement } from '../../lib/floating';\nimport { defaultFilterFn } from '../../lib/select';\nimport { ChipsInputBase } from '../ChipsInputBase/ChipsInputBase';\nimport {\n getNewOptionDataDefault,\n getOptionLabelDefault,\n getOptionValueDefault,\n renderChipDefault,\n} from '../ChipsInputBase/constants';\nimport type { ChipOption, ChipsInputBaseProps } from '../ChipsInputBase/types';\nimport {\n CustomSelectDropdown,\n type CustomSelectDropdownProps,\n} from '../CustomSelectDropdown/CustomSelectDropdown';\nimport {\n CustomSelectOption,\n type CustomSelectOptionProps,\n} from '../CustomSelectOption/CustomSelectOption';\nimport { DropdownIcon } from '../DropdownIcon/DropdownIcon';\nimport type { FormFieldProps } from '../FormField/FormField';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport {\n DEFAULT_EMPTY_TEXT,\n DEFAULT_SELECTED_BEHAVIOR,\n FOCUS_ACTION_NEXT,\n FOCUS_ACTION_PREV,\n isCreateNewOptionPreset,\n isEmptyOptionPreset,\n isNotServicePreset,\n renderOptionDefault,\n} from './constants';\nimport type { FocusActionType, OptionPreset } from './types';\nimport { useChipsSelect, type UseChipsSelectProps } from './useChipsSelect';\nimport styles from './ChipsSelect.module.css';\n\nconst findIndexAfter = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n startIndex = -1,\n) => {\n if (startIndex >= options.length - 1) {\n return -1;\n }\n return options.findIndex(\n (option, i) => i > startIndex && (!isNotServicePreset(option) || !option.disabled),\n );\n};\n\nconst findIndexBefore = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n endIndex: number = options.length,\n) => {\n let result = -1;\n if (endIndex <= 0) {\n return result;\n }\n for (let i = endIndex - 1; i >= 0; i--) {\n let option = options[i];\n\n if (!isNotServicePreset(option) || !option.disabled) {\n result = i;\n break;\n }\n }\n return result;\n};\n\nexport interface ChipsSelectProps<O extends ChipOption>\n extends ChipsInputBaseProps<O>,\n UseChipsSelectProps<O>,\n Pick<FormFieldProps, 'status' | 'mode' | 'before'>,\n Pick<CustomSelectDropdownProps, 'overscrollBehavior'> {\n /**\n * Расположение выпадающего списка.\n */\n placement?: 'top' | 'bottom';\n /**\n * Отрисовка Spinner вместо списка опций в выпадающем списке.\n */\n fetching?: boolean;\n /**\n * Закрытие выпадающего списка после выбора элемента.\n */\n closeAfterSelect?: boolean;\n /**\n * Ширина раскрывающегося списка зависит от контента.\n */\n dropdownAutoWidth?: boolean;\n /**\n * Принудительно использовать портал.\n */\n forceDropdownPortal?: boolean;\n /**\n * Передает атрибут `data-testid` для дропдауна.\n */\n dropdownTestId?: string;\n /**\n * Иконка раскрывающегося списка.\n */\n icon?: React.ReactNode;\n /**\n * Добавляет значение в список на событие `onBlur` (использовать вместе с `creatable`).\n */\n addOnBlur?: boolean;\n /**\n * Отключает максимальную высоту по умолчанию.\n */\n noMaxHeight?: boolean;\n /**\n * Функция для отрисовки кастомной опции в выпадающем списке.\n */\n renderOption?: (props: CustomSelectOptionProps, option: O) => React.ReactNode;\n /**\n * Рендер-проп для кастомного рендера содержимого дропдауна.\n * В `defaultDropdownContent` содержится список опций.\n */\n renderDropdown?: ({\n defaultDropdownContent,\n }: {\n defaultDropdownContent: React.ReactNode;\n }) => React.ReactNode;\n /**\n * Событие срабатывающее перед `onChange`.\n */\n onChangeStart?: (event: React.MouseEvent | React.KeyboardEvent, option: O) => void;\n\n /**\n * Отступ от выпадающего списка.\n */\n dropdownOffsetDistance?: number;\n\n /**\n * Если `true`, то справа будет отображаться кнопка для очистки значения.\n */\n allowClearButton?: boolean;\n}\n\n/**\n * @see https://vkui.io/components/chips-select\n */\nexport const ChipsSelect = <Option extends ChipOption>({\n // FormFieldProps\n id: labelledbyId,\n getRootRef,\n className,\n status = 'default',\n icon: dropdownIconProp,\n onChangeStart,\n\n // CustomSelectDropdownProps\n options: optionsProp,\n placement: placementProp = 'bottom',\n closeAfterSelect = true,\n selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,\n emptyText = DEFAULT_EMPTY_TEXT,\n creatable = false,\n fetching = false,\n dropdownAutoWidth,\n forceDropdownPortal,\n noMaxHeight = false,\n filterFn = defaultFilterFn,\n sortFn = false,\n dropdownTestId,\n onClose,\n onOpen,\n overscrollBehavior,\n renderDropdown,\n\n // ChipsInputProps\n getRef,\n value: valueProp,\n defaultValue,\n inputValue: inputValueProp,\n defaultInputValue,\n disabled,\n readOnly,\n getOptionValue = getOptionValueDefault,\n getOptionLabel = getOptionLabelDefault,\n getNewOptionData = getNewOptionDataDefault,\n renderChip = renderChipDefault,\n renderOption = renderOptionDefault,\n onChange,\n onFocus: onFocusProp,\n onInputChange: onInputChangeProp,\n onBlur: onBlurProp,\n onKeyDown: onKeyDownProp,\n dropdownOffsetDistance = 0,\n allowClearButton,\n clearButtonTestId,\n delimiter,\n\n // a11y\n chipsListLabel,\n ...restProps\n}: ChipsSelectProps<Option>): React.ReactNode => {\n const {\n // Связано с ChipsInputProps\n // option\n value,\n addOptionFromInput,\n addOption,\n removeOption,\n clearOptions,\n // input\n inputRef: inputRefHook,\n inputValue,\n clearInput,\n onInputChange,\n\n // Связано с CustomSelectDropdownProps\n options,\n opened,\n setOpened,\n focusedOption,\n focusedOptionIndex,\n setFocusedOption,\n setFocusedOptionIndex,\n } = useChipsSelect({\n // option\n value: valueProp,\n defaultValue,\n onChange,\n getOptionValue,\n getOptionLabel,\n getNewOptionData,\n\n // input\n inputValue: inputValueProp,\n defaultInputValue,\n onInputChange: onInputChangeProp,\n\n // dropdown\n options: optionsProp,\n emptyText,\n creatable,\n filterFn,\n sortFn,\n selectedBehavior,\n onClose,\n onOpen,\n\n // other\n disabled,\n delimiter,\n });\n\n // Связано с ChipsInputProps\n const rootRef = useExternRef(getRootRef);\n const inputRef = useExternRef(getRef, inputRefHook);\n\n // Связано с CustomSelectDropdownProps\n const [dropdownVerticalPlacement, setDropdownVerticalPlacement] = React.useState<\n 'top' | 'bottom'\n >(placementProp);\n\n const onDropdownPlacementChange = React.useCallback((placement: Placement) => {\n if (placement.startsWith('top')) {\n setDropdownVerticalPlacement('top');\n } else if (placement.startsWith('bottom')) {\n setDropdownVerticalPlacement('bottom');\n }\n }, []);\n\n const dropdownId = React.useId();\n const dropdownCurrentItemId =\n focusedOptionIndex !== null ? `${dropdownId}-${focusedOptionIndex}` : undefined;\n const dropdownScrollBoxRef = React.useRef<HTMLDivElement>(null);\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onFocusProp) {\n onFocusProp(event);\n }\n\n if (!readOnly) {\n setOpened(true);\n setFocusedOptionIndex(null);\n }\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlurProp) {\n onBlurProp(event);\n }\n\n // Не добавляем значение, если его нужно выбрать строго из списка\n if (!readOnly && !event.defaultPrevented && !creatable) {\n event.preventDefault();\n }\n };\n\n const chipsSelectOptions = React.useRef<HTMLElement[]>([]).current;\n\n const scrollToElement = (index: number, center = false) => {\n const dropdown = dropdownScrollBoxRef.current;\n const item = chipsSelectOptions[index];\n\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!item || !dropdown) {\n return;\n }\n\n const dropdownHeight = dropdown.offsetHeight;\n const scrollTop = dropdown.scrollTop;\n const itemTop = item.offsetTop;\n const itemHeight = item.offsetHeight;\n\n /* istanbul ignore next: нет представления как воспроизвести */\n if (center) {\n dropdown.scrollTop = itemTop - dropdownHeight / 2 + itemHeight / 2;\n } else if (itemTop + itemHeight > dropdownHeight + scrollTop) {\n dropdown.scrollTop = itemTop - dropdownHeight + itemHeight;\n } else if (itemTop < scrollTop) {\n dropdown.scrollTop = itemTop;\n }\n };\n\n const focusOptionByIndex = (index: number, oldIndex: number | null) => {\n if (index === oldIndex) {\n /* istanbul ignore next: нет представления как воспроизвести */\n return;\n }\n\n const option = options[index];\n\n if (isNotServicePreset(option) && option.disabled) {\n return;\n }\n\n scrollToElement(index);\n setFocusedOptionIndex(index);\n };\n\n const focusOption = (nextIndex: number | null, type: FocusActionType) => {\n let index = nextIndex === null ? -1 : nextIndex;\n\n if (type === FOCUS_ACTION_NEXT) {\n const nextIndex = findIndexAfter(options, index);\n index = nextIndex === -1 ? findIndexAfter(options) : nextIndex; // Следующий за index или первый валидный до index\n } else if (type === FOCUS_ACTION_PREV) {\n const beforeIndex = findIndexBefore(options, index);\n index = beforeIndex === -1 ? findIndexBefore(options) : beforeIndex; // Предшествующий index или последний валидный после index\n }\n\n focusOptionByIndex(index, focusedOptionIndex);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (onKeyDownProp) {\n onKeyDownProp(event);\n }\n\n if (event.defaultPrevented || readOnly) {\n return;\n }\n\n switch (event.key) {\n case Keys.ARROW_UP:\n case Keys.ARROW_DOWN:\n event.preventDefault();\n\n if (!opened) {\n setOpened(true);\n focusOption(null, FOCUS_ACTION_NEXT);\n } else {\n focusOption(\n focusedOptionIndex,\n event.key === Keys.ARROW_UP ? FOCUS_ACTION_PREV : FOCUS_ACTION_NEXT,\n );\n }\n break;\n case Keys.ENTER: {\n if (!opened) {\n break;\n }\n if (focusedOptionIndex != null) {\n const foundOption = options[focusedOptionIndex];\n if (foundOption && isNotServicePreset(foundOption)) {\n event.preventDefault();\n\n if (onChangeStart) {\n onChangeStart(event, foundOption);\n }\n\n addOption(foundOption);\n setFocusedOptionIndex(null);\n clearInput();\n if (closeAfterSelect) {\n setOpened(false);\n }\n\n break;\n }\n }\n\n if (!creatable) {\n event.preventDefault();\n }\n break;\n }\n case Keys.ESCAPE:\n case Keys.TAB:\n if (opened) {\n setOpened(false);\n }\n }\n };\n\n React.useEffect(() => {\n if (focusedOptionIndex === null) {\n setFocusedOption(null);\n } else {\n const foundFocusedOptionIndex = options[focusedOptionIndex];\n\n if (foundFocusedOptionIndex && isNotServicePreset(foundFocusedOptionIndex)) {\n setFocusedOption(foundFocusedOptionIndex);\n }\n }\n }, [options, focusedOptionIndex, setFocusedOption]);\n\n const onDropdownMouseLeave = React.useCallback(() => {\n setFocusedOptionIndex(null);\n }, [setFocusedOptionIndex]);\n\n const handleClickOutside = React.useCallback(() => {\n setOpened(false);\n }, [setOpened]);\n\n useGlobalOnEventOutside(\n 'mousedown', // см. https://github.com/VKCOM/VKUI/pull/8582\n handleClickOutside,\n opened ? rootRef : null,\n opened ? dropdownScrollBoxRef : null,\n );\n\n const onDropdownIconClick: MouseEventHandler<SVGSVGElement> = React.useCallback(\n (e) => {\n if (opened) {\n e.preventDefault();\n setOpened(false);\n }\n },\n [opened, setOpened],\n );\n\n const dropdownContent = React.useMemo(() => {\n const defaultDropdownContent = options.map((option, index) => {\n const dropdownItemId = `${dropdownId}-${index}`;\n\n if (isEmptyOptionPreset(option)) {\n return (\n <Footnote key=\"empty-text\" className={styles.empty}>\n {option.placeholder}\n </Footnote>\n );\n }\n if (isCreateNewOptionPreset(option)) {\n return (\n <CustomSelectOption\n key=\"create-new-option\"\n id={dropdownItemId}\n hovered={focusedOptionIndex === index}\n onMouseDown={() => addOptionFromInput(inputValue)}\n onMouseEnter={() => setFocusedOptionIndex(index)}\n >\n {option.actionText}\n </CustomSelectOption>\n );\n }\n return (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderOption(\n {\n id: dropdownItemId,\n disabled: option.disabled,\n hovered: focusedOption\n ? getOptionValue(option) === getOptionValue(focusedOption)\n : false,\n children: option.label,\n selected: !!value.find(\n (selectedOption: Option) =>\n getOptionValue(selectedOption) === getOptionValue(option),\n ),\n getRootRef(node) {\n if (node) {\n chipsSelectOptions[index] = node;\n }\n },\n onMouseDown(event: React.MouseEvent<HTMLDivElement>) {\n if (option.disabled) {\n return;\n }\n if (onChangeStart) {\n onChangeStart(event, option);\n }\n\n if (!event.defaultPrevented) {\n closeAfterSelect && setOpened(false);\n addOption(option);\n clearInput();\n }\n },\n onMouseEnter() {\n setFocusedOptionIndex(index);\n },\n },\n option,\n )}\n </React.Fragment>\n );\n });\n\n if (renderDropdown) {\n return renderDropdown({\n defaultDropdownContent,\n });\n }\n return defaultDropdownContent;\n }, [\n addOption,\n addOptionFromInput,\n chipsSelectOptions,\n clearInput,\n closeAfterSelect,\n dropdownId,\n focusedOption,\n focusedOptionIndex,\n getOptionValue,\n inputValue,\n onChangeStart,\n options,\n renderDropdown,\n renderOption,\n setFocusedOptionIndex,\n setOpened,\n value,\n ]);\n\n const openedClassNames = React.useMemo(\n () =>\n (opened &&\n dropdownOffsetDistance === 0 &&\n (dropdownVerticalPlacement.includes('top') ? styles.popUp : styles.popDown)) ||\n undefined,\n [dropdownOffsetDistance, opened, dropdownVerticalPlacement],\n );\n\n const clearButtonShown = allowClearButton && (!!value.length || !!inputValue.length);\n\n return (\n <>\n <ChipsInputBase\n {...restProps}\n disabled={disabled}\n readOnly={readOnly}\n clearButtonShown={clearButtonShown}\n clearButtonTestId={clearButtonTestId}\n // FormFieldProps\n id={labelledbyId}\n getRootRef={rootRef}\n className={classNames(styles.host, openedClassNames, className)}\n status={status}\n after={\n dropdownIconProp || (\n <DropdownIcon\n opened={opened}\n onClick={onDropdownIconClick}\n className={classNames(\n styles.dropdownIcon,\n clearButtonShown && styles.dropdownIconWithOffset,\n )}\n />\n )\n }\n // option\n value={value}\n onAddChipOption={addOptionFromInput}\n onRemoveChipOption={removeOption}\n renderChip={renderChip}\n onClear={clearOptions}\n // input\n getRef={inputRef}\n inputValue={inputValue}\n onInputChange={onInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n // a11y\n role=\"combobox\"\n aria-expanded={opened}\n aria-autocomplete=\"list\"\n aria-activedescendant={opened ? dropdownCurrentItemId : undefined}\n aria-haspopup=\"listbox\"\n chipsListLabel={chipsListLabel}\n />\n {opened && (\n <CustomSelectDropdown\n data-testid={dropdownTestId}\n targetRef={rootRef}\n placement={dropdownVerticalPlacement}\n scrollBoxRef={dropdownScrollBoxRef}\n onPlacementChange={onDropdownPlacementChange}\n onMouseLeave={onDropdownMouseLeave}\n fetching={fetching}\n autoWidth={dropdownAutoWidth}\n forcePortal={forceDropdownPortal}\n noMaxHeight={noMaxHeight}\n offsetDistance={dropdownOffsetDistance}\n overscrollBehavior={overscrollBehavior}\n // a11y\n id={dropdownId}\n role=\"listbox\"\n aria-labelledby={labelledbyId}\n >\n {dropdownContent}\n </CustomSelectDropdown>\n )}\n </>\n );\n};\n"],"names":["React","classNames","useExternRef","useGlobalOnEventOutside","Keys","defaultFilterFn","ChipsInputBase","getNewOptionDataDefault","getOptionLabelDefault","getOptionValueDefault","renderChipDefault","CustomSelectDropdown","CustomSelectOption","DropdownIcon","Footnote","DEFAULT_EMPTY_TEXT","DEFAULT_SELECTED_BEHAVIOR","FOCUS_ACTION_NEXT","FOCUS_ACTION_PREV","isCreateNewOptionPreset","isEmptyOptionPreset","isNotServicePreset","renderOptionDefault","useChipsSelect","findIndexAfter","options","startIndex","length","findIndex","option","i","disabled","findIndexBefore","endIndex","result","ChipsSelect","id","labelledbyId","getRootRef","className","status","icon","dropdownIconProp","onChangeStart","optionsProp","placement","placementProp","closeAfterSelect","selectedBehavior","emptyText","creatable","fetching","dropdownAutoWidth","forceDropdownPortal","noMaxHeight","filterFn","sortFn","dropdownTestId","onClose","onOpen","overscrollBehavior","renderDropdown","getRef","value","valueProp","defaultValue","inputValue","inputValueProp","defaultInputValue","readOnly","getOptionValue","getOptionLabel","getNewOptionData","renderChip","renderOption","onChange","onFocus","onFocusProp","onInputChange","onInputChangeProp","onBlur","onBlurProp","onKeyDown","onKeyDownProp","dropdownOffsetDistance","allowClearButton","clearButtonTestId","delimiter","chipsListLabel","restProps","addOptionFromInput","addOption","removeOption","clearOptions","inputRef","inputRefHook","clearInput","opened","setOpened","focusedOption","focusedOptionIndex","setFocusedOption","setFocusedOptionIndex","rootRef","dropdownVerticalPlacement","setDropdownVerticalPlacement","useState","onDropdownPlacementChange","useCallback","startsWith","dropdownId","useId","dropdownCurrentItemId","undefined","dropdownScrollBoxRef","useRef","handleFocus","event","handleBlur","defaultPrevented","preventDefault","chipsSelectOptions","current","scrollToElement","index","center","dropdown","item","dropdownHeight","offsetHeight","scrollTop","itemTop","offsetTop","itemHeight","focusOptionByIndex","oldIndex","focusOption","nextIndex","type","beforeIndex","handleKeyDown","key","ARROW_UP","ARROW_DOWN","ENTER","foundOption","ESCAPE","TAB","useEffect","foundFocusedOptionIndex","onDropdownMouseLeave","handleClickOutside","onDropdownIconClick","e","dropdownContent","useMemo","defaultDropdownContent","map","dropdownItemId","placeholder","hovered","onMouseDown","onMouseEnter","actionText","Fragment","children","label","selected","find","selectedOption","node","openedClassNames","includes","clearButtonShown","after","onClick","onAddChipOption","onRemoveChipOption","onClear","role","aria-expanded","aria-autocomplete","aria-activedescendant","aria-haspopup","data-testid","targetRef","scrollBoxRef","onPlacementChange","onMouseLeave","autoWidth","forcePortal","offsetDistance","aria-labelledby"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/ChipsSelect/ChipsSelect.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { type MouseEventHandler } from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useGlobalOnEventOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { Keys } from '../../lib/accessibility';\nimport type { Placement } from '../../lib/floating';\nimport { defaultFilterFn } from '../../lib/select';\nimport { ChipsInputBase } from '../ChipsInputBase/ChipsInputBase';\nimport {\n getNewOptionDataDefault,\n getOptionLabelDefault,\n getOptionValueDefault,\n renderChipDefault,\n} from '../ChipsInputBase/constants';\nimport type { ChipOption, ChipsInputBaseProps } from '../ChipsInputBase/types';\nimport {\n CustomSelectDropdown,\n type CustomSelectDropdownProps,\n} from '../CustomSelectDropdown/CustomSelectDropdown';\nimport {\n CustomSelectOption,\n type CustomSelectOptionProps,\n} from '../CustomSelectOption/CustomSelectOption';\nimport { DropdownIcon } from '../DropdownIcon/DropdownIcon';\nimport type { FormFieldProps } from '../FormField/FormField';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport {\n DEFAULT_EMPTY_TEXT,\n DEFAULT_SELECTED_BEHAVIOR,\n FOCUS_ACTION_NEXT,\n FOCUS_ACTION_PREV,\n isCreateNewOptionPreset,\n isEmptyOptionPreset,\n isNotServicePreset,\n renderOptionDefault,\n} from './constants';\nimport type { FocusActionType, OptionPreset } from './types';\nimport { useChipsSelect, type UseChipsSelectProps } from './useChipsSelect';\nimport styles from './ChipsSelect.module.css';\n\nconst findIndexAfter = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n startIndex = -1,\n) => {\n if (startIndex >= options.length - 1) {\n return -1;\n }\n return options.findIndex(\n (option, i) => i > startIndex && (!isNotServicePreset(option) || !option.disabled),\n );\n};\n\nconst findIndexBefore = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n endIndex: number = options.length,\n) => {\n let result = -1;\n if (endIndex <= 0) {\n return result;\n }\n for (let i = endIndex - 1; i >= 0; i--) {\n let option = options[i];\n\n if (!isNotServicePreset(option) || !option.disabled) {\n result = i;\n break;\n }\n }\n return result;\n};\n\nexport interface ChipsSelectProps<O extends ChipOption>\n extends ChipsInputBaseProps<O>,\n UseChipsSelectProps<O>,\n Pick<FormFieldProps, 'status' | 'mode' | 'before'>,\n Pick<CustomSelectDropdownProps, 'overscrollBehavior'> {\n /**\n * Расположение выпадающего списка.\n */\n placement?: 'top' | 'bottom';\n /**\n * Отрисовка Spinner вместо списка опций в выпадающем списке.\n */\n fetching?: boolean;\n /**\n * Закрытие выпадающего списка после выбора элемента.\n */\n closeAfterSelect?: boolean;\n /**\n * Ширина раскрывающегося списка зависит от контента.\n */\n dropdownAutoWidth?: boolean;\n /**\n * Принудительно использовать портал.\n */\n forceDropdownPortal?: boolean;\n /**\n * Передает атрибут `data-testid` для дропдауна.\n */\n dropdownTestId?: string;\n /**\n * Иконка раскрывающегося списка.\n */\n icon?: React.ReactNode;\n /**\n * Добавляет значение в список на событие `onBlur` (использовать вместе с `creatable`).\n */\n addOnBlur?: boolean;\n /**\n * Отключает максимальную высоту по умолчанию.\n */\n noMaxHeight?: boolean;\n /**\n * Функция для отрисовки кастомной опции в выпадающем списке.\n */\n renderOption?: (props: CustomSelectOptionProps, option: O) => React.ReactNode;\n /**\n * Рендер-проп для кастомного рендера содержимого дропдауна.\n * В `defaultDropdownContent` содержится список опций.\n */\n renderDropdown?: ({\n defaultDropdownContent,\n }: {\n defaultDropdownContent: React.ReactNode;\n }) => React.ReactNode;\n /**\n * Событие срабатывающее перед `onChange`.\n */\n onChangeStart?: (event: React.MouseEvent | React.KeyboardEvent, option: O) => void;\n\n /**\n * Отступ от выпадающего списка.\n */\n dropdownOffsetDistance?: number;\n\n /**\n * Если `true`, то справа будет отображаться кнопка для очистки значения.\n */\n allowClearButton?: boolean;\n}\n\n/**\n * @see https://vkui.io/components/chips-select\n */\nexport const ChipsSelect = <Option extends ChipOption>({\n // FormFieldProps\n id: labelledbyId,\n getRootRef,\n className,\n status = 'default',\n icon: dropdownIconProp,\n onChangeStart,\n\n // CustomSelectDropdownProps\n options: optionsProp,\n placement: placementProp = 'bottom',\n closeAfterSelect = true,\n selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,\n emptyText = DEFAULT_EMPTY_TEXT,\n creatable = false,\n fetching = false,\n dropdownAutoWidth,\n forceDropdownPortal,\n noMaxHeight = false,\n filterFn = defaultFilterFn,\n sortFn = false,\n dropdownTestId,\n onClose,\n onOpen,\n overscrollBehavior,\n renderDropdown,\n\n // ChipsInputProps\n getRef,\n value: valueProp,\n defaultValue,\n inputValue: inputValueProp,\n defaultInputValue,\n disabled,\n readOnly,\n getOptionValue = getOptionValueDefault,\n getOptionLabel = getOptionLabelDefault,\n getNewOptionData = getNewOptionDataDefault,\n renderChip = renderChipDefault,\n renderOption = renderOptionDefault,\n onChange,\n onFocus: onFocusProp,\n onInputChange: onInputChangeProp,\n onBlur: onBlurProp,\n onKeyDown: onKeyDownProp,\n dropdownOffsetDistance = 0,\n allowClearButton,\n clearButtonTestId,\n delimiter,\n\n // a11y\n chipsListLabel,\n ...restProps\n}: ChipsSelectProps<Option>): React.ReactNode => {\n const {\n // Связано с ChipsInputProps\n // option\n value,\n addOptionFromInput,\n addOption,\n removeOption,\n clearOptions,\n // input\n inputRef: inputRefHook,\n inputValue,\n clearInput,\n onInputChange,\n\n // Связано с CustomSelectDropdownProps\n options,\n opened,\n setOpened,\n focusedOption,\n focusedOptionIndex,\n setFocusedOption,\n setFocusedOptionIndex,\n } = useChipsSelect({\n // option\n value: valueProp,\n defaultValue,\n onChange,\n getOptionValue,\n getOptionLabel,\n getNewOptionData,\n\n // input\n inputValue: inputValueProp,\n defaultInputValue,\n onInputChange: onInputChangeProp,\n\n // dropdown\n options: optionsProp,\n emptyText,\n creatable,\n filterFn,\n sortFn,\n selectedBehavior,\n onClose,\n onOpen,\n\n // other\n disabled,\n delimiter,\n });\n\n // Связано с ChipsInputProps\n const rootRef = useExternRef(getRootRef);\n const inputRef = useExternRef(getRef, inputRefHook);\n\n // Связано с CustomSelectDropdownProps\n const [dropdownVerticalPlacement, setDropdownVerticalPlacement] = React.useState<\n 'top' | 'bottom'\n >(placementProp);\n\n const onDropdownPlacementChange = React.useCallback((placement: Placement) => {\n if (placement.startsWith('top')) {\n setDropdownVerticalPlacement('top');\n } else if (placement.startsWith('bottom')) {\n setDropdownVerticalPlacement('bottom');\n }\n }, []);\n\n const dropdownId = React.useId();\n const dropdownCurrentItemId =\n focusedOptionIndex !== null ? `${dropdownId}-${focusedOptionIndex}` : undefined;\n const dropdownScrollBoxRef = React.useRef<HTMLDivElement>(null);\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onFocusProp) {\n onFocusProp(event);\n }\n\n if (!readOnly) {\n setOpened(true);\n setFocusedOptionIndex(null);\n }\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlurProp) {\n onBlurProp(event);\n }\n\n // Не добавляем значение, если его нужно выбрать строго из списка\n if (!readOnly && !event.defaultPrevented && !creatable) {\n event.preventDefault();\n }\n };\n\n const chipsSelectOptions = React.useRef<HTMLElement[]>([]).current;\n\n const scrollToElement = (index: number, center = false) => {\n const dropdown = dropdownScrollBoxRef.current;\n const item = chipsSelectOptions[index];\n\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!item || !dropdown) {\n return;\n }\n\n const dropdownHeight = dropdown.offsetHeight;\n const scrollTop = dropdown.scrollTop;\n const itemTop = item.offsetTop;\n const itemHeight = item.offsetHeight;\n\n /* istanbul ignore next: нет представления как воспроизвести */\n if (center) {\n dropdown.scrollTop = itemTop - dropdownHeight / 2 + itemHeight / 2;\n } else if (itemTop + itemHeight > dropdownHeight + scrollTop) {\n dropdown.scrollTop = itemTop - dropdownHeight + itemHeight;\n } else if (itemTop < scrollTop) {\n dropdown.scrollTop = itemTop;\n }\n };\n\n const focusOptionByIndex = (index: number, oldIndex: number | null) => {\n if (index === oldIndex) {\n /* istanbul ignore next: нет представления как воспроизвести */\n return;\n }\n\n const option = options[index];\n\n if (isNotServicePreset(option) && option.disabled) {\n return;\n }\n\n scrollToElement(index);\n setFocusedOptionIndex(index);\n };\n\n const focusOption = (nextIndex: number | null, type: FocusActionType) => {\n let index = nextIndex === null ? -1 : nextIndex;\n\n if (type === FOCUS_ACTION_NEXT) {\n const nextIndex = findIndexAfter(options, index);\n index = nextIndex === -1 ? findIndexAfter(options) : nextIndex; // Следующий за index или первый валидный до index\n } else if (type === FOCUS_ACTION_PREV) {\n const beforeIndex = findIndexBefore(options, index);\n index = beforeIndex === -1 ? findIndexBefore(options) : beforeIndex; // Предшествующий index или последний валидный после index\n }\n\n focusOptionByIndex(index, focusedOptionIndex);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (onKeyDownProp) {\n onKeyDownProp(event);\n }\n\n if (event.defaultPrevented || readOnly) {\n return;\n }\n\n switch (event.key) {\n case Keys.ARROW_UP:\n case Keys.ARROW_DOWN:\n event.preventDefault();\n\n if (!opened) {\n setOpened(true);\n focusOption(null, FOCUS_ACTION_NEXT);\n } else {\n focusOption(\n focusedOptionIndex,\n event.key === Keys.ARROW_UP ? FOCUS_ACTION_PREV : FOCUS_ACTION_NEXT,\n );\n }\n break;\n case Keys.ENTER: {\n if (!opened) {\n break;\n }\n if (focusedOptionIndex != null) {\n const foundOption = options[focusedOptionIndex];\n if (foundOption && isNotServicePreset(foundOption)) {\n event.preventDefault();\n\n if (onChangeStart) {\n onChangeStart(event, foundOption);\n }\n\n addOption(foundOption);\n setFocusedOptionIndex(null);\n clearInput();\n if (closeAfterSelect) {\n setOpened(false);\n }\n\n break;\n }\n }\n\n if (!creatable) {\n event.preventDefault();\n }\n break;\n }\n case Keys.ESCAPE:\n case Keys.TAB:\n if (opened) {\n setOpened(false);\n }\n }\n };\n\n React.useEffect(() => {\n if (focusedOptionIndex === null) {\n setFocusedOption(null);\n } else {\n const foundFocusedOptionIndex = options[focusedOptionIndex];\n\n if (foundFocusedOptionIndex && isNotServicePreset(foundFocusedOptionIndex)) {\n setFocusedOption(foundFocusedOptionIndex);\n }\n }\n }, [options, focusedOptionIndex, setFocusedOption]);\n\n const onDropdownMouseLeave = React.useCallback(() => {\n setFocusedOptionIndex(null);\n }, [setFocusedOptionIndex]);\n\n const handleClickOutside = React.useCallback(() => {\n setOpened(false);\n }, [setOpened]);\n\n useGlobalOnEventOutside(\n 'mousedown', // см. https://github.com/VKCOM/VKUI/pull/8582\n handleClickOutside,\n opened ? rootRef : null,\n opened ? dropdownScrollBoxRef : null,\n );\n\n const onDropdownIconClick: MouseEventHandler<SVGSVGElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n setOpened(!opened);\n },\n [opened, setOpened],\n );\n\n const dropdownContent = React.useMemo(() => {\n const defaultDropdownContent = options.map((option, index) => {\n const dropdownItemId = `${dropdownId}-${index}`;\n\n if (isEmptyOptionPreset(option)) {\n return (\n <Footnote key=\"empty-text\" className={styles.empty}>\n {option.placeholder}\n </Footnote>\n );\n }\n if (isCreateNewOptionPreset(option)) {\n return (\n <CustomSelectOption\n key=\"create-new-option\"\n id={dropdownItemId}\n hovered={focusedOptionIndex === index}\n onMouseDown={() => addOptionFromInput(inputValue)}\n onMouseEnter={() => setFocusedOptionIndex(index)}\n >\n {option.actionText}\n </CustomSelectOption>\n );\n }\n return (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderOption(\n {\n id: dropdownItemId,\n disabled: option.disabled,\n hovered: focusedOption\n ? getOptionValue(option) === getOptionValue(focusedOption)\n : false,\n children: option.label,\n selected: !!value.find(\n (selectedOption: Option) =>\n getOptionValue(selectedOption) === getOptionValue(option),\n ),\n getRootRef(node) {\n if (node) {\n chipsSelectOptions[index] = node;\n }\n },\n onMouseDown(event: React.MouseEvent<HTMLDivElement>) {\n if (option.disabled) {\n return;\n }\n if (onChangeStart) {\n onChangeStart(event, option);\n }\n\n if (!event.defaultPrevented) {\n closeAfterSelect && setOpened(false);\n addOption(option);\n clearInput();\n }\n },\n onMouseEnter() {\n setFocusedOptionIndex(index);\n },\n },\n option,\n )}\n </React.Fragment>\n );\n });\n\n if (renderDropdown) {\n return renderDropdown({\n defaultDropdownContent,\n });\n }\n return defaultDropdownContent;\n }, [\n addOption,\n addOptionFromInput,\n chipsSelectOptions,\n clearInput,\n closeAfterSelect,\n dropdownId,\n focusedOption,\n focusedOptionIndex,\n getOptionValue,\n inputValue,\n onChangeStart,\n options,\n renderDropdown,\n renderOption,\n setFocusedOptionIndex,\n setOpened,\n value,\n ]);\n\n const openedClassNames = React.useMemo(\n () =>\n (opened &&\n dropdownOffsetDistance === 0 &&\n (dropdownVerticalPlacement.includes('top') ? styles.popUp : styles.popDown)) ||\n undefined,\n [dropdownOffsetDistance, opened, dropdownVerticalPlacement],\n );\n\n const clearButtonShown = allowClearButton && (!!value.length || !!inputValue.length);\n\n return (\n <>\n <ChipsInputBase\n {...restProps}\n disabled={disabled}\n readOnly={readOnly}\n clearButtonShown={clearButtonShown}\n clearButtonTestId={clearButtonTestId}\n // FormFieldProps\n id={labelledbyId}\n getRootRef={rootRef}\n className={classNames(styles.host, openedClassNames, className)}\n status={status}\n after={\n dropdownIconProp || (\n <DropdownIcon\n opened={opened}\n onClick={onDropdownIconClick}\n className={classNames(\n styles.dropdownIcon,\n clearButtonShown && styles.dropdownIconWithOffset,\n )}\n />\n )\n }\n // option\n value={value}\n onAddChipOption={addOptionFromInput}\n onRemoveChipOption={removeOption}\n renderChip={renderChip}\n onClear={clearOptions}\n // input\n getRef={inputRef}\n inputValue={inputValue}\n onInputChange={onInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n // a11y\n role=\"combobox\"\n aria-expanded={opened}\n aria-autocomplete=\"list\"\n aria-activedescendant={opened ? dropdownCurrentItemId : undefined}\n aria-haspopup=\"listbox\"\n chipsListLabel={chipsListLabel}\n />\n {opened && (\n <CustomSelectDropdown\n data-testid={dropdownTestId}\n targetRef={rootRef}\n placement={dropdownVerticalPlacement}\n scrollBoxRef={dropdownScrollBoxRef}\n onPlacementChange={onDropdownPlacementChange}\n onMouseLeave={onDropdownMouseLeave}\n fetching={fetching}\n autoWidth={dropdownAutoWidth}\n forcePortal={forceDropdownPortal}\n noMaxHeight={noMaxHeight}\n offsetDistance={dropdownOffsetDistance}\n overscrollBehavior={overscrollBehavior}\n // a11y\n id={dropdownId}\n role=\"listbox\"\n aria-labelledby={labelledbyId}\n >\n {dropdownContent}\n </CustomSelectDropdown>\n )}\n </>\n );\n};\n"],"names":["React","classNames","useExternRef","useGlobalOnEventOutside","Keys","defaultFilterFn","ChipsInputBase","getNewOptionDataDefault","getOptionLabelDefault","getOptionValueDefault","renderChipDefault","CustomSelectDropdown","CustomSelectOption","DropdownIcon","Footnote","DEFAULT_EMPTY_TEXT","DEFAULT_SELECTED_BEHAVIOR","FOCUS_ACTION_NEXT","FOCUS_ACTION_PREV","isCreateNewOptionPreset","isEmptyOptionPreset","isNotServicePreset","renderOptionDefault","useChipsSelect","findIndexAfter","options","startIndex","length","findIndex","option","i","disabled","findIndexBefore","endIndex","result","ChipsSelect","id","labelledbyId","getRootRef","className","status","icon","dropdownIconProp","onChangeStart","optionsProp","placement","placementProp","closeAfterSelect","selectedBehavior","emptyText","creatable","fetching","dropdownAutoWidth","forceDropdownPortal","noMaxHeight","filterFn","sortFn","dropdownTestId","onClose","onOpen","overscrollBehavior","renderDropdown","getRef","value","valueProp","defaultValue","inputValue","inputValueProp","defaultInputValue","readOnly","getOptionValue","getOptionLabel","getNewOptionData","renderChip","renderOption","onChange","onFocus","onFocusProp","onInputChange","onInputChangeProp","onBlur","onBlurProp","onKeyDown","onKeyDownProp","dropdownOffsetDistance","allowClearButton","clearButtonTestId","delimiter","chipsListLabel","restProps","addOptionFromInput","addOption","removeOption","clearOptions","inputRef","inputRefHook","clearInput","opened","setOpened","focusedOption","focusedOptionIndex","setFocusedOption","setFocusedOptionIndex","rootRef","dropdownVerticalPlacement","setDropdownVerticalPlacement","useState","onDropdownPlacementChange","useCallback","startsWith","dropdownId","useId","dropdownCurrentItemId","undefined","dropdownScrollBoxRef","useRef","handleFocus","event","handleBlur","defaultPrevented","preventDefault","chipsSelectOptions","current","scrollToElement","index","center","dropdown","item","dropdownHeight","offsetHeight","scrollTop","itemTop","offsetTop","itemHeight","focusOptionByIndex","oldIndex","focusOption","nextIndex","type","beforeIndex","handleKeyDown","key","ARROW_UP","ARROW_DOWN","ENTER","foundOption","ESCAPE","TAB","useEffect","foundFocusedOptionIndex","onDropdownMouseLeave","handleClickOutside","onDropdownIconClick","e","dropdownContent","useMemo","defaultDropdownContent","map","dropdownItemId","placeholder","hovered","onMouseDown","onMouseEnter","actionText","Fragment","children","label","selected","find","selectedOption","node","openedClassNames","includes","clearButtonShown","after","onClick","onAddChipOption","onRemoveChipOption","onClear","role","aria-expanded","aria-autocomplete","aria-activedescendant","aria-haspopup","data-testid","targetRef","scrollBoxRef","onPlacementChange","onMouseLeave","autoWidth","forcePortal","offsetDistance","aria-labelledby"],"mappings":"AAAA;;;;;AAEA,YAAYA,WAAW,QAAQ;AAE/B,SAASC,UAAU,QAAQ,kBAAkB;AAC7C,SAASC,YAAY,QAAQ,8BAA2B;AACxD,SAASC,uBAAuB,QAAQ,yCAAsC;AAC9E,SAASC,IAAI,QAAQ,6BAA0B;AAE/C,SAASC,eAAe,QAAQ,sBAAmB;AACnD,SAASC,cAAc,QAAQ,sCAAmC;AAClE,SACEC,uBAAuB,EACvBC,qBAAqB,EACrBC,qBAAqB,EACrBC,iBAAiB,QACZ,iCAA8B;AAErC,SACEC,oBAAoB,QAEf,kDAA+C;AACtD,SACEC,kBAAkB,QAEb,8CAA2C;AAClD,SAASC,YAAY,QAAQ,kCAA+B;AAE5D,SAASC,QAAQ,QAAQ,qCAAkC;AAC3D,SACEC,kBAAkB,EAClBC,yBAAyB,EACzBC,iBAAiB,EACjBC,iBAAiB,EACjBC,uBAAuB,EACvBC,mBAAmB,EACnBC,kBAAkB,EAClBC,mBAAmB,QACd,iBAAc;AAErB,SAASC,cAAc,QAAkC,sBAAmB;AAG5E,MAAMC,iBAAiB,CACrBC,UAAkC,EAAE,EACpCC,aAAa,CAAC,CAAC;IAEf,IAAIA,cAAcD,QAAQE,MAAM,GAAG,GAAG;QACpC,OAAO,CAAC;IACV;IACA,OAAOF,QAAQG,SAAS,CACtB,CAACC,QAAQC,IAAMA,IAAIJ,cAAe,CAAA,CAACL,mBAAmBQ,WAAW,CAACA,OAAOE,QAAQ,AAAD;AAEpF;AAEA,MAAMC,kBAAkB,CACtBP,UAAkC,EAAE,EACpCQ,WAAmBR,QAAQE,MAAM;IAEjC,IAAIO,SAAS,CAAC;IACd,IAAID,YAAY,GAAG;QACjB,OAAOC;IACT;IACA,IAAK,IAAIJ,IAAIG,WAAW,GAAGH,KAAK,GAAGA,IAAK;QACtC,IAAID,SAASJ,OAAO,CAACK,EAAE;QAEvB,IAAI,CAACT,mBAAmBQ,WAAW,CAACA,OAAOE,QAAQ,EAAE;YACnDG,SAASJ;YACT;QACF;IACF;IACA,OAAOI;AACT;AAwEA;;CAEC,GACD,OAAO,MAAMC,cAAc;QAA4B,EACrD,iBAAiB;IACjBC,IAAIC,YAAY,EAChBC,UAAU,EACVC,SAAS,EACTC,SAAS,SAAS,EAClBC,MAAMC,gBAAgB,EACtBC,aAAa,EAEb,4BAA4B;IAC5BlB,SAASmB,WAAW,EACpBC,WAAWC,gBAAgB,QAAQ,EACnCC,mBAAmB,IAAI,EACvBC,mBAAmBhC,yBAAyB,EAC5CiC,YAAYlC,kBAAkB,EAC9BmC,YAAY,KAAK,EACjBC,WAAW,KAAK,EAChBC,iBAAiB,EACjBC,mBAAmB,EACnBC,cAAc,KAAK,EACnBC,WAAWlD,eAAe,EAC1BmD,SAAS,KAAK,EACdC,cAAc,EACdC,OAAO,EACPC,MAAM,EACNC,kBAAkB,EAClBC,cAAc,EAEd,kBAAkB;IAClBC,MAAM,EACNC,OAAOC,SAAS,EAChBC,YAAY,EACZC,YAAYC,cAAc,EAC1BC,iBAAiB,EACjBrC,QAAQ,EACRsC,QAAQ,EACRC,iBAAiB7D,qBAAqB,EACtC8D,iBAAiB/D,qBAAqB,EACtCgE,mBAAmBjE,uBAAuB,EAC1CkE,aAAa/D,iBAAiB,EAC9BgE,eAAepD,mBAAmB,EAClCqD,QAAQ,EACRC,SAASC,WAAW,EACpBC,eAAeC,iBAAiB,EAChCC,QAAQC,UAAU,EAClBC,WAAWC,aAAa,EACxBC,yBAAyB,CAAC,EAC1BC,gBAAgB,EAChBC,iBAAiB,EACjBC,SAAS,EAET,OAAO;IACPC,cAAc,EAEW,WADtBC;QAnDHrD;QACAE;QACAC;QACAC;QACAC;QACAE;QAGAlB;QACAoB;QACAE;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QAGAC;QACAC;QACAE;QACAC;QACAE;QACArC;QACAsC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAE;QACAE;QACAE;QACAE;QACAC;QACAC;QACAC;QAGAC;;IAGA,MAAM,EACJ,4BAA4B;IAC5B,SAAS;IACTzB,KAAK,EACL2B,kBAAkB,EAClBC,SAAS,EACTC,YAAY,EACZC,YAAY,EACZ,QAAQ;IACRC,UAAUC,YAAY,EACtB7B,UAAU,EACV8B,UAAU,EACVlB,aAAa,EAEb,sCAAsC;IACtCrD,OAAO,EACPwE,MAAM,EACNC,SAAS,EACTC,aAAa,EACbC,kBAAkB,EAClBC,gBAAgB,EAChBC,qBAAqB,EACtB,GAAG/E,eAAe;QACjB,SAAS;QACTwC,OAAOC;QACPC;QACAU;QACAL;QACAC;QACAC;QAEA,QAAQ;QACRN,YAAYC;QACZC;QACAU,eAAeC;QAEf,WAAW;QACXtD,SAASmB;QACTK;QACAC;QACAK;QACAC;QACAR;QACAU;QACAC;QAEA,QAAQ;QACR5B;QACAwD;IACF;IAEA,4BAA4B;IAC5B,MAAMgB,UAAUrG,aAAaoC;IAC7B,MAAMwD,WAAW5F,aAAa4D,QAAQiC;IAEtC,sCAAsC;IACtC,MAAM,CAACS,2BAA2BC,6BAA6B,GAAGzG,MAAM0G,QAAQ,CAE9E5D;IAEF,MAAM6D,4BAA4B3G,MAAM4G,WAAW,CAAC,CAAC/D;QACnD,IAAIA,UAAUgE,UAAU,CAAC,QAAQ;YAC/BJ,6BAA6B;QAC/B,OAAO,IAAI5D,UAAUgE,UAAU,CAAC,WAAW;YACzCJ,6BAA6B;QAC/B;IACF,GAAG,EAAE;IAEL,MAAMK,aAAa9G,MAAM+G,KAAK;IAC9B,MAAMC,wBACJZ,uBAAuB,OAAO,GAAGU,WAAW,CAAC,EAAEV,oBAAoB,GAAGa;IACxE,MAAMC,uBAAuBlH,MAAMmH,MAAM,CAAiB;IAE1D,MAAMC,cAAc,CAACC;QACnB,IAAIxC,aAAa;YACfA,YAAYwC;QACd;QAEA,IAAI,CAAChD,UAAU;YACb6B,UAAU;YACVI,sBAAsB;QACxB;IACF;IAEA,MAAMgB,aAAa,CAACD;QAClB,IAAIpC,YAAY;YACdA,WAAWoC;QACb;QAEA,iEAAiE;QACjE,IAAI,CAAChD,YAAY,CAACgD,MAAME,gBAAgB,IAAI,CAACrE,WAAW;YACtDmE,MAAMG,cAAc;QACtB;IACF;IAEA,MAAMC,qBAAqBzH,MAAMmH,MAAM,CAAgB,EAAE,EAAEO,OAAO;IAElE,MAAMC,kBAAkB,CAACC,OAAeC,SAAS,KAAK;QACpD,MAAMC,WAAWZ,qBAAqBQ,OAAO;QAC7C,MAAMK,OAAON,kBAAkB,CAACG,MAAM;QAEtC,6EAA6E,GAC7E,IAAI,CAACG,QAAQ,CAACD,UAAU;YACtB;QACF;QAEA,MAAME,iBAAiBF,SAASG,YAAY;QAC5C,MAAMC,YAAYJ,SAASI,SAAS;QACpC,MAAMC,UAAUJ,KAAKK,SAAS;QAC9B,MAAMC,aAAaN,KAAKE,YAAY;QAEpC,6DAA6D,GAC7D,IAAIJ,QAAQ;YACVC,SAASI,SAAS,GAAGC,UAAUH,iBAAiB,IAAIK,aAAa;QACnE,OAAO,IAAIF,UAAUE,aAAaL,iBAAiBE,WAAW;YAC5DJ,SAASI,SAAS,GAAGC,UAAUH,iBAAiBK;QAClD,OAAO,IAAIF,UAAUD,WAAW;YAC9BJ,SAASI,SAAS,GAAGC;QACvB;IACF;IAEA,MAAMG,qBAAqB,CAACV,OAAeW;QACzC,IAAIX,UAAUW,UAAU;YACtB,6DAA6D,GAC7D;QACF;QAEA,MAAM1G,SAASJ,OAAO,CAACmG,MAAM;QAE7B,IAAIvG,mBAAmBQ,WAAWA,OAAOE,QAAQ,EAAE;YACjD;QACF;QAEA4F,gBAAgBC;QAChBtB,sBAAsBsB;IACxB;IAEA,MAAMY,cAAc,CAACC,WAA0BC;QAC7C,IAAId,QAAQa,cAAc,OAAO,CAAC,IAAIA;QAEtC,IAAIC,SAASzH,mBAAmB;YAC9B,MAAMwH,YAAYjH,eAAeC,SAASmG;YAC1CA,QAAQa,cAAc,CAAC,IAAIjH,eAAeC,WAAWgH,WAAW,kDAAkD;QACpH,OAAO,IAAIC,SAASxH,mBAAmB;YACrC,MAAMyH,cAAc3G,gBAAgBP,SAASmG;YAC7CA,QAAQe,gBAAgB,CAAC,IAAI3G,gBAAgBP,WAAWkH,aAAa,0DAA0D;QACjI;QAEAL,mBAAmBV,OAAOxB;IAC5B;IAEA,MAAMwC,gBAAgB,CAACvB;QACrB,IAAIlC,eAAe;YACjBA,cAAckC;QAChB;QAEA,IAAIA,MAAME,gBAAgB,IAAIlD,UAAU;YACtC;QACF;QAEA,OAAQgD,MAAMwB,GAAG;YACf,KAAKzI,KAAK0I,QAAQ;YAClB,KAAK1I,KAAK2I,UAAU;gBAClB1B,MAAMG,cAAc;gBAEpB,IAAI,CAACvB,QAAQ;oBACXC,UAAU;oBACVsC,YAAY,MAAMvH;gBACpB,OAAO;oBACLuH,YACEpC,oBACAiB,MAAMwB,GAAG,KAAKzI,KAAK0I,QAAQ,GAAG5H,oBAAoBD;gBAEtD;gBACA;YACF,KAAKb,KAAK4I,KAAK;gBAAE;oBACf,IAAI,CAAC/C,QAAQ;wBACX;oBACF;oBACA,IAAIG,sBAAsB,MAAM;wBAC9B,MAAM6C,cAAcxH,OAAO,CAAC2E,mBAAmB;wBAC/C,IAAI6C,eAAe5H,mBAAmB4H,cAAc;4BAClD5B,MAAMG,cAAc;4BAEpB,IAAI7E,eAAe;gCACjBA,cAAc0E,OAAO4B;4BACvB;4BAEAtD,UAAUsD;4BACV3C,sBAAsB;4BACtBN;4BACA,IAAIjD,kBAAkB;gCACpBmD,UAAU;4BACZ;4BAEA;wBACF;oBACF;oBAEA,IAAI,CAAChD,WAAW;wBACdmE,MAAMG,cAAc;oBACtB;oBACA;gBACF;YACA,KAAKpH,KAAK8I,MAAM;YAChB,KAAK9I,KAAK+I,GAAG;gBACX,IAAIlD,QAAQ;oBACVC,UAAU;gBACZ;QACJ;IACF;IAEAlG,MAAMoJ,SAAS,CAAC;QACd,IAAIhD,uBAAuB,MAAM;YAC/BC,iBAAiB;QACnB,OAAO;YACL,MAAMgD,0BAA0B5H,OAAO,CAAC2E,mBAAmB;YAE3D,IAAIiD,2BAA2BhI,mBAAmBgI,0BAA0B;gBAC1EhD,iBAAiBgD;YACnB;QACF;IACF,GAAG;QAAC5H;QAAS2E;QAAoBC;KAAiB;IAElD,MAAMiD,uBAAuBtJ,MAAM4G,WAAW,CAAC;QAC7CN,sBAAsB;IACxB,GAAG;QAACA;KAAsB;IAE1B,MAAMiD,qBAAqBvJ,MAAM4G,WAAW,CAAC;QAC3CV,UAAU;IACZ,GAAG;QAACA;KAAU;IAEd/F,wBACE,aACAoJ,oBACAtD,SAASM,UAAU,MACnBN,SAASiB,uBAAuB;IAGlC,MAAMsC,sBAAwDxJ,MAAM4G,WAAW,CAC7E,CAAC6C;QACCA,EAAEjC,cAAc;QAChBtB,UAAU,CAACD;IACb,GACA;QAACA;QAAQC;KAAU;IAGrB,MAAMwD,kBAAkB1J,MAAM2J,OAAO,CAAC;QACpC,MAAMC,yBAAyBnI,QAAQoI,GAAG,CAAC,CAAChI,QAAQ+F;YAClD,MAAMkC,iBAAiB,GAAGhD,WAAW,CAAC,EAAEc,OAAO;YAE/C,IAAIxG,oBAAoBS,SAAS;gBAC/B,qBACE,KAACf;oBAA0ByB,SAAS;8BACjCV,OAAOkI,WAAW;mBADP;YAIlB;YACA,IAAI5I,wBAAwBU,SAAS;gBACnC,qBACE,KAACjB;oBAECwB,IAAI0H;oBACJE,SAAS5D,uBAAuBwB;oBAChCqC,aAAa,IAAMvE,mBAAmBxB;oBACtCgG,cAAc,IAAM5D,sBAAsBsB;8BAEzC/F,OAAOsI,UAAU;mBANd;YASV;YACA,qBACE,KAACnK,MAAMoK,QAAQ;0BACZ1F,aACC;oBACEtC,IAAI0H;oBACJ/H,UAAUF,OAAOE,QAAQ;oBACzBiI,SAAS7D,gBACL7B,eAAezC,YAAYyC,eAAe6B,iBAC1C;oBACJkE,UAAUxI,OAAOyI,KAAK;oBACtBC,UAAU,CAAC,CAACxG,MAAMyG,IAAI,CACpB,CAACC,iBACCnG,eAAemG,oBAAoBnG,eAAezC;oBAEtDS,YAAWoI,IAAI;wBACb,IAAIA,MAAM;4BACRjD,kBAAkB,CAACG,MAAM,GAAG8C;wBAC9B;oBACF;oBACAT,aAAY5C,KAAuC;wBACjD,IAAIxF,OAAOE,QAAQ,EAAE;4BACnB;wBACF;wBACA,IAAIY,eAAe;4BACjBA,cAAc0E,OAAOxF;wBACvB;wBAEA,IAAI,CAACwF,MAAME,gBAAgB,EAAE;4BAC3BxE,oBAAoBmD,UAAU;4BAC9BP,UAAU9D;4BACVmE;wBACF;oBACF;oBACAkE;wBACE5D,sBAAsBsB;oBACxB;gBACF,GACA/F;eApCiB,GAAG,OAAOA,OAAOkC,KAAK,CAAC,CAAC,EAAElC,OAAOkC,KAAK,EAAE;QAwCjE;QAEA,IAAIF,gBAAgB;YAClB,OAAOA,eAAe;gBACpB+F;YACF;QACF;QACA,OAAOA;IACT,GAAG;QACDjE;QACAD;QACA+B;QACAzB;QACAjD;QACA+D;QACAX;QACAC;QACA9B;QACAJ;QACAvB;QACAlB;QACAoC;QACAa;QACA4B;QACAJ;QACAnC;KACD;IAED,MAAM4G,mBAAmB3K,MAAM2J,OAAO,CACpC,IACE,AAAC1D,UACCb,2BAA2B,KAC1BoB,CAAAA,0BAA0BoE,QAAQ,CAAC,8DAAqC,KAC3E3D,WACF;QAAC7B;QAAwBa;QAAQO;KAA0B;IAG7D,MAAMqE,mBAAmBxF,oBAAqB,CAAA,CAAC,CAACtB,MAAMpC,MAAM,IAAI,CAAC,CAACuC,WAAWvC,MAAM,AAAD;IAElF,qBACE;;0BACE,KAACrB,wDACKmF;gBACJ1D,UAAUA;gBACVsC,UAAUA;gBACVwG,kBAAkBA;gBAClBvF,mBAAmBA;gBACnB,iBAAiB;gBACjBlD,IAAIC;gBACJC,YAAYiE;gBACZhE,WAAWtC,oCAAwB0K,kBAAkBpI;gBACrDC,QAAQA;gBACRsI,OACEpI,kCACE,KAAC7B;oBACCoF,QAAQA;oBACR8E,SAASvB;oBACTjH,WAAWtC,4CAET4K;;gBAKR,SAAS;gBACT9G,OAAOA;gBACPiH,iBAAiBtF;gBACjBuF,oBAAoBrF;gBACpBnB,YAAYA;gBACZyG,SAASrF;gBACT,QAAQ;gBACR/B,QAAQgC;gBACR5B,YAAYA;gBACZY,eAAeA;gBACfF,SAASwC;gBACTpC,QAAQsC;gBACRpC,WAAW0D;gBACX,OAAO;gBACPuC,MAAK;gBACLC,iBAAenF;gBACfoF,qBAAkB;gBAClBC,yBAAuBrF,SAASe,wBAAwBC;gBACxDsE,iBAAc;gBACd/F,gBAAgBA;;YAEjBS,wBACC,KAACtF;gBACC6K,eAAa/H;gBACbgI,WAAWlF;gBACX1D,WAAW2D;gBACXkF,cAAcxE;gBACdyE,mBAAmBhF;gBACnBiF,cAActC;gBACdnG,UAAUA;gBACV0I,WAAWzI;gBACX0I,aAAazI;gBACbC,aAAaA;gBACbyI,gBAAgB3G;gBAChBxB,oBAAoBA;gBACpB,OAAO;gBACPxB,IAAI0E;gBACJqE,MAAK;gBACLa,mBAAiB3J;0BAEhBqH;;;;AAKX,EAAE"}
@@ -116,7 +116,8 @@ chipsListLabel = 'Выбранные элементы', 'aria-label': ariaLabel
116
116
  removeChipOption(v, getChipOptionIndexByValueProp(v, value));
117
117
  };
118
118
  const handleRootClick = (event)=>{
119
- if (event.defaultPrevented || contains(event.currentTarget, getActiveElementByAnotherElement(event.currentTarget))) {
119
+ const activeElement = getActiveElementByAnotherElement(event.currentTarget);
120
+ if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {
120
121
  return;
121
122
  }
122
123
  if (inputRef.current) {
@@ -163,6 +164,24 @@ chipsListLabel = 'Выбранные элементы', 'aria-label': ariaLabel
163
164
  clearButton
164
165
  ]);
165
166
  const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;
167
+ const handleRootMouseDown = (e)=>{
168
+ // Если клик был в один из чипов, то preventDefault делать не нужно, так как не будет срабатывать выделение текста
169
+ if (isHTMLElement(e.target) && contains(listboxRef.current, e.target) && listboxRef.current !== e.target) {
170
+ return;
171
+ }
172
+ const activeElement = getActiveElementByAnotherElement(e.currentTarget);
173
+ // Когда выделен текст чипа не нужно делать preventDefault, чтобы сбросить выделение
174
+ if (contains(listboxRef.current, activeElement)) {
175
+ return;
176
+ }
177
+ // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста
178
+ if (e.target === inputRef.current) {
179
+ return;
180
+ }
181
+ // Делаем preventDefault, чтобы при клике в поле, вне инпута, высота поля не скакала от того,
182
+ // что фокус сначала пропадает из инпута, а потом возвращается
183
+ e.preventDefault();
184
+ };
166
185
  return /*#__PURE__*/ _jsx(FormField, {
167
186
  Component: "div",
168
187
  getRootRef: getRootRef,
@@ -179,6 +198,7 @@ chipsListLabel = 'Выбранные элементы', 'aria-label': ariaLabel
179
198
  className: className,
180
199
  maxHeight: maxHeight,
181
200
  onClick: disabled ? undefined : handleRootClick,
201
+ onMouseDown: handleRootMouseDown,
182
202
  children: /*#__PURE__*/ _jsxs("div", {
183
203
  className: classNames(styles.host, sizeY !== 'regular' && sizeYClassNames[sizeY], withPlaceholder && styles.hasPlaceholder, inputValue && styles.hasInputValue),
184
204
  ref: containerRef,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { isHTMLElement } from '@vkontakte/vkui-floating-ui/utils/dom';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { getHorizontalFocusGoTo, Keys } from '../../lib/accessibility';\nimport {\n contains as checkTargetIsInputEl,\n contains,\n getActiveElementByAnotherElement,\n} from '../../lib/dom';\nimport { FormField } from '../FormField/FormField';\nimport { FormFieldClearButton } from '../FormFieldClearButton/FormFieldClearButton';\nimport { Text } from '../Typography/Text/Text';\nimport { DEFAULT_INPUT_VALUE, DEFAULT_VALUE, renderChipDefault } from './constants';\nimport {\n getChipOptionIndexByHTMLElement,\n getChipOptionIndexByValueProp,\n getChipOptionValueByHTMLElement,\n getNextChipOptionIndexByNavigateToProp,\n isInputValueEmpty,\n} from './helpers';\nimport type { ChipOption, ChipOptionValue, ChipsInputBasePrivateProps, NavigateTo } from './types';\nimport styles from './ChipsInputBase.module.css';\n\nconst sizeYClassNames = {\n none: styles.sizeYNone,\n compact: styles.sizeYCompact,\n} as const;\n\nexport const ChipsInputBase = <O extends ChipOption>({\n // FormFieldProps\n getRootRef,\n style,\n className,\n before,\n after,\n status,\n mode,\n maxHeight,\n\n // option\n value = DEFAULT_VALUE,\n onAddChipOption,\n 'onRemoveChipOption': onRemoveChipOptionProp,\n renderChip = renderChipDefault,\n\n // input\n getRef,\n 'id': idProp,\n inputValue = DEFAULT_INPUT_VALUE,\n placeholder,\n disabled,\n readOnly,\n addOnBlur,\n onBlur,\n onInputChange,\n\n // clear\n ClearButton = FormFieldClearButton,\n clearButtonShown,\n clearButtonTestId,\n onClear,\n\n // a11y\n chipsListLabel = 'Выбранные элементы',\n 'aria-label': ariaLabel = '',\n ...restProps\n}: ChipsInputBasePrivateProps<O>): React.ReactNode => {\n const { sizeY = 'none' } = useAdaptivity();\n const idGenerated = React.useId();\n const inputRef = useExternRef(getRef);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const listboxRef = React.useRef<HTMLDivElement>(null);\n\n const valueLength = value.length;\n const withPlaceholder = valueLength === 0;\n const [lastFocusedChipOptionIndex, setLastFocusedChipOptionIndex] = React.useState(0);\n\n const resetChipOptionFocusToInputEl = (inputEl: HTMLInputElement) => {\n setLastFocusedChipOptionIndex(0);\n inputEl.focus();\n };\n\n const moveFocusToChipOption = (\n currentIndex: number,\n navigateTo: NavigateTo,\n listboxEl: HTMLElement,\n ) => {\n const index = getNextChipOptionIndexByNavigateToProp(currentIndex, navigateTo, valueLength);\n // eslint-disable-next-line no-restricted-properties\n const foundEl = listboxEl.querySelector<HTMLElement>(`[data-index=\"${index}\"]`);\n\n if (foundEl) {\n setLastFocusedChipOptionIndex(index);\n foundEl.focus();\n }\n };\n\n const removeChipOption = (o: O | ChipOptionValue, index: number) => {\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!inputRef.current || !listboxRef.current) {\n return;\n }\n\n if (valueLength > 1) {\n if (index === valueLength - 1) {\n moveFocusToChipOption(index, 'prev', listboxRef.current);\n } else {\n moveFocusToChipOption(index, 'next', listboxRef.current);\n }\n } else {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n\n onRemoveChipOptionProp(o);\n };\n\n const handleListboxKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const targetEl = event.target;\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (event.defaultPrevented || !listboxRef.current || !isHTMLElement(targetEl)) {\n return;\n }\n\n switch (event.key) {\n case Keys.ENTER: {\n if (\n !readOnly &&\n checkTargetIsInputEl(targetEl, inputRef.current) &&\n inputRef.current &&\n !isInputValueEmpty(inputRef.current)\n ) {\n event.preventDefault();\n onAddChipOption(inputRef.current.value);\n }\n break;\n }\n case Keys.DELETE:\n case Keys.BACKSPACE: {\n if (!readOnly && valueLength > 0) {\n if (!checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n removeChipOption(\n getChipOptionValueByHTMLElement(targetEl),\n getChipOptionIndexByHTMLElement(targetEl),\n );\n } else if (event.key === Keys.BACKSPACE && isInputValueEmpty(inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n 'last',\n listboxRef.current,\n );\n }\n }\n break;\n }\n case Keys.HOME:\n case Keys.END:\n case Keys.ARROW_UP:\n case Keys.ARROW_LEFT:\n case Keys.ARROW_DOWN:\n case Keys.ARROW_RIGHT: {\n if (valueLength !== 0 && !checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n getHorizontalFocusGoTo(event.key),\n listboxRef.current,\n );\n }\n break;\n }\n }\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(event);\n }\n\n if (addOnBlur && !event.defaultPrevented && inputRef.current) {\n onAddChipOption(inputRef.current.value);\n }\n };\n\n const handleChipRemove = (event: React.MouseEvent, v: ChipOptionValue) => {\n event.preventDefault();\n event.stopPropagation();\n removeChipOption(v, getChipOptionIndexByValueProp(v, value));\n };\n\n const handleRootClick = (event: React.MouseEvent<HTMLDivElement>) => {\n if (\n event.defaultPrevented ||\n contains(event.currentTarget, getActiveElementByAnotherElement(event.currentTarget))\n ) {\n return;\n }\n\n if (inputRef.current) {\n inputRef.current.focus();\n }\n };\n\n const handleClear = React.useCallback(() => {\n if (inputRef.current) {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n onClear();\n }, [inputRef, onClear]);\n\n const clearButton = React.useMemo(() => {\n if (clearButtonShown) {\n return (\n <ClearButton onClick={handleClear} disabled={disabled} data-testid={clearButtonTestId} />\n );\n }\n return undefined;\n }, [ClearButton, clearButtonShown, clearButtonTestId, disabled, handleClear]);\n\n const afterItems = React.useMemo(() => {\n if (clearButton || after) {\n return (\n <>\n {clearButton}\n {after}\n </>\n );\n }\n return undefined;\n }, [after, clearButton]);\n\n const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;\n\n return (\n <FormField\n Component=\"div\"\n getRootRef={getRootRef}\n // role=\"group\" добавлена, чтобы этот блок можно было найти с помощью стрелочек при использовании NVDA\n // Если убрать, то aria-label не будет читаться\n role=\"group\"\n aria-label={ariaLabel}\n style={style}\n disabled={disabled}\n before={before}\n after={afterItems}\n status={status}\n mode={mode}\n className={className}\n maxHeight={maxHeight}\n onClick={disabled ? undefined : handleRootClick}\n >\n <div\n className={classNames(\n styles.host,\n sizeY !== 'regular' && sizeYClassNames[sizeY],\n withPlaceholder && styles.hasPlaceholder,\n inputValue && styles.hasInputValue,\n )}\n ref={containerRef}\n onKeyDown={disabled ? undefined : handleListboxKeyDown}\n >\n <div\n className={styles.listBox}\n // для a11y\n ref={listboxRef}\n role=\"listbox\"\n aria-orientation=\"horizontal\"\n aria-disabled={disabled}\n aria-readonly={readOnly}\n aria-label={chipsListLabel}\n >\n {value.map((option, index) => (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderChip(\n {\n 'Component': 'div',\n 'value': option.value,\n 'label': option.label,\n 'disabled': option.disabled || disabled,\n 'readOnly': option.readOnly || readOnly,\n 'className': styles.chip,\n 'onRemove': handleChipRemove,\n // чтобы можно было легче найти этот чип в DOM\n 'data-index': index,\n 'data-value': option.value,\n 'data-value-type': typeof option.value,\n // для a11y\n 'tabIndex': lastFocusedChipOptionIndex === index ? 0 : -1,\n 'role': 'option',\n 'aria-selected': true,\n 'aria-posinset': index + 1,\n 'aria-setsize': valueLength,\n 'aria-description': 'Для удаления используйте Backspace или Delete',\n },\n option,\n )}\n </React.Fragment>\n ))}\n </div>\n <Text\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n {...restProps}\n aria-label={ariaLabel}\n Component=\"input\"\n type=\"text\"\n id={inputId}\n getRootRef={inputRef}\n className={styles.el}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={withPlaceholder ? placeholder : undefined}\n value={inputValue}\n onChange={onInputChange}\n onBlur={handleInputBlur}\n />\n </div>\n </FormField>\n );\n};\n"],"names":["React","classNames","isHTMLElement","useAdaptivity","useExternRef","getHorizontalFocusGoTo","Keys","contains","checkTargetIsInputEl","getActiveElementByAnotherElement","FormField","FormFieldClearButton","Text","DEFAULT_INPUT_VALUE","DEFAULT_VALUE","renderChipDefault","getChipOptionIndexByHTMLElement","getChipOptionIndexByValueProp","getChipOptionValueByHTMLElement","getNextChipOptionIndexByNavigateToProp","isInputValueEmpty","styles","sizeYClassNames","none","sizeYNone","compact","sizeYCompact","ChipsInputBase","getRootRef","style","className","before","after","status","mode","maxHeight","value","onAddChipOption","onRemoveChipOptionProp","renderChip","getRef","idProp","inputValue","placeholder","disabled","readOnly","addOnBlur","onBlur","onInputChange","ClearButton","clearButtonShown","clearButtonTestId","onClear","chipsListLabel","ariaLabel","restProps","sizeY","idGenerated","useId","inputRef","containerRef","useRef","listboxRef","valueLength","length","withPlaceholder","lastFocusedChipOptionIndex","setLastFocusedChipOptionIndex","useState","resetChipOptionFocusToInputEl","inputEl","focus","moveFocusToChipOption","currentIndex","navigateTo","listboxEl","index","foundEl","querySelector","removeChipOption","o","current","handleListboxKeyDown","event","targetEl","target","defaultPrevented","key","ENTER","preventDefault","DELETE","BACKSPACE","HOME","END","ARROW_UP","ARROW_LEFT","ARROW_DOWN","ARROW_RIGHT","handleInputBlur","handleChipRemove","v","stopPropagation","handleRootClick","currentTarget","handleClear","useCallback","clearButton","useMemo","onClick","data-testid","undefined","afterItems","inputId","Component","role","aria-label","div","host","hasPlaceholder","hasInputValue","ref","onKeyDown","listBox","aria-orientation","aria-disabled","aria-readonly","map","option","Fragment","label","chip","autoCapitalize","autoComplete","autoCorrect","spellCheck","type","id","el","onChange"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/components/ChipsInputBase/ChipsInputBase.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { isHTMLElement } from '@vkontakte/vkui-floating-ui/utils/dom';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { getHorizontalFocusGoTo, Keys } from '../../lib/accessibility';\nimport {\n contains as checkTargetIsInputEl,\n contains,\n getActiveElementByAnotherElement,\n} from '../../lib/dom';\nimport { FormField } from '../FormField/FormField';\nimport { FormFieldClearButton } from '../FormFieldClearButton/FormFieldClearButton';\nimport { Text } from '../Typography/Text/Text';\nimport { DEFAULT_INPUT_VALUE, DEFAULT_VALUE, renderChipDefault } from './constants';\nimport {\n getChipOptionIndexByHTMLElement,\n getChipOptionIndexByValueProp,\n getChipOptionValueByHTMLElement,\n getNextChipOptionIndexByNavigateToProp,\n isInputValueEmpty,\n} from './helpers';\nimport type { ChipOption, ChipOptionValue, ChipsInputBasePrivateProps, NavigateTo } from './types';\nimport styles from './ChipsInputBase.module.css';\n\nconst sizeYClassNames = {\n none: styles.sizeYNone,\n compact: styles.sizeYCompact,\n} as const;\n\nexport const ChipsInputBase = <O extends ChipOption>({\n // FormFieldProps\n getRootRef,\n style,\n className,\n before,\n after,\n status,\n mode,\n maxHeight,\n\n // option\n value = DEFAULT_VALUE,\n onAddChipOption,\n 'onRemoveChipOption': onRemoveChipOptionProp,\n renderChip = renderChipDefault,\n\n // input\n getRef,\n 'id': idProp,\n inputValue = DEFAULT_INPUT_VALUE,\n placeholder,\n disabled,\n readOnly,\n addOnBlur,\n onBlur,\n onInputChange,\n\n // clear\n ClearButton = FormFieldClearButton,\n clearButtonShown,\n clearButtonTestId,\n onClear,\n\n // a11y\n chipsListLabel = 'Выбранные элементы',\n 'aria-label': ariaLabel = '',\n ...restProps\n}: ChipsInputBasePrivateProps<O>): React.ReactNode => {\n const { sizeY = 'none' } = useAdaptivity();\n const idGenerated = React.useId();\n const inputRef = useExternRef(getRef);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const listboxRef = React.useRef<HTMLDivElement>(null);\n\n const valueLength = value.length;\n const withPlaceholder = valueLength === 0;\n const [lastFocusedChipOptionIndex, setLastFocusedChipOptionIndex] = React.useState(0);\n\n const resetChipOptionFocusToInputEl = (inputEl: HTMLInputElement) => {\n setLastFocusedChipOptionIndex(0);\n inputEl.focus();\n };\n\n const moveFocusToChipOption = (\n currentIndex: number,\n navigateTo: NavigateTo,\n listboxEl: HTMLElement,\n ) => {\n const index = getNextChipOptionIndexByNavigateToProp(currentIndex, navigateTo, valueLength);\n // eslint-disable-next-line no-restricted-properties\n const foundEl = listboxEl.querySelector<HTMLElement>(`[data-index=\"${index}\"]`);\n\n if (foundEl) {\n setLastFocusedChipOptionIndex(index);\n foundEl.focus();\n }\n };\n\n const removeChipOption = (o: O | ChipOptionValue, index: number) => {\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!inputRef.current || !listboxRef.current) {\n return;\n }\n\n if (valueLength > 1) {\n if (index === valueLength - 1) {\n moveFocusToChipOption(index, 'prev', listboxRef.current);\n } else {\n moveFocusToChipOption(index, 'next', listboxRef.current);\n }\n } else {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n\n onRemoveChipOptionProp(o);\n };\n\n const handleListboxKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const targetEl = event.target;\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (event.defaultPrevented || !listboxRef.current || !isHTMLElement(targetEl)) {\n return;\n }\n\n switch (event.key) {\n case Keys.ENTER: {\n if (\n !readOnly &&\n checkTargetIsInputEl(targetEl, inputRef.current) &&\n inputRef.current &&\n !isInputValueEmpty(inputRef.current)\n ) {\n event.preventDefault();\n onAddChipOption(inputRef.current.value);\n }\n break;\n }\n case Keys.DELETE:\n case Keys.BACKSPACE: {\n if (!readOnly && valueLength > 0) {\n if (!checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n removeChipOption(\n getChipOptionValueByHTMLElement(targetEl),\n getChipOptionIndexByHTMLElement(targetEl),\n );\n } else if (event.key === Keys.BACKSPACE && isInputValueEmpty(inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n 'last',\n listboxRef.current,\n );\n }\n }\n break;\n }\n case Keys.HOME:\n case Keys.END:\n case Keys.ARROW_UP:\n case Keys.ARROW_LEFT:\n case Keys.ARROW_DOWN:\n case Keys.ARROW_RIGHT: {\n if (valueLength !== 0 && !checkTargetIsInputEl(targetEl, inputRef.current)) {\n event.preventDefault();\n moveFocusToChipOption(\n getChipOptionIndexByHTMLElement(targetEl),\n getHorizontalFocusGoTo(event.key),\n listboxRef.current,\n );\n }\n break;\n }\n }\n };\n\n const handleInputBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlur) {\n onBlur(event);\n }\n\n if (addOnBlur && !event.defaultPrevented && inputRef.current) {\n onAddChipOption(inputRef.current.value);\n }\n };\n\n const handleChipRemove = (event: React.MouseEvent, v: ChipOptionValue) => {\n event.preventDefault();\n event.stopPropagation();\n removeChipOption(v, getChipOptionIndexByValueProp(v, value));\n };\n\n const handleRootClick = (event: React.MouseEvent<HTMLDivElement>) => {\n const activeElement = getActiveElementByAnotherElement(event.currentTarget);\n if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {\n return;\n }\n\n if (inputRef.current) {\n inputRef.current.focus();\n }\n };\n\n const handleClear = React.useCallback(() => {\n if (inputRef.current) {\n resetChipOptionFocusToInputEl(inputRef.current);\n }\n onClear();\n }, [inputRef, onClear]);\n\n const clearButton = React.useMemo(() => {\n if (clearButtonShown) {\n return (\n <ClearButton onClick={handleClear} disabled={disabled} data-testid={clearButtonTestId} />\n );\n }\n return undefined;\n }, [ClearButton, clearButtonShown, clearButtonTestId, disabled, handleClear]);\n\n const afterItems = React.useMemo(() => {\n if (clearButton || after) {\n return (\n <>\n {clearButton}\n {after}\n </>\n );\n }\n return undefined;\n }, [after, clearButton]);\n\n const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;\n\n const handleRootMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n // Если клик был в один из чипов, то preventDefault делать не нужно, так как не будет срабатывать выделение текста\n if (\n isHTMLElement(e.target) &&\n contains(listboxRef.current, e.target) &&\n listboxRef.current !== e.target\n ) {\n return;\n }\n const activeElement = getActiveElementByAnotherElement(e.currentTarget);\n // Когда выделен текст чипа не нужно делать preventDefault, чтобы сбросить выделение\n if (contains(listboxRef.current, activeElement)) {\n return;\n }\n // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста\n if (e.target === inputRef.current) {\n return;\n }\n // Делаем preventDefault, чтобы при клике в поле, вне инпута, высота поля не скакала от того,\n // что фокус сначала пропадает из инпута, а потом возвращается\n e.preventDefault();\n };\n\n return (\n <FormField\n Component=\"div\"\n getRootRef={getRootRef}\n // role=\"group\" добавлена, чтобы этот блок можно было найти с помощью стрелочек при использовании NVDA\n // Если убрать, то aria-label не будет читаться\n role=\"group\"\n aria-label={ariaLabel}\n style={style}\n disabled={disabled}\n before={before}\n after={afterItems}\n status={status}\n mode={mode}\n className={className}\n maxHeight={maxHeight}\n onClick={disabled ? undefined : handleRootClick}\n onMouseDown={handleRootMouseDown}\n >\n <div\n className={classNames(\n styles.host,\n sizeY !== 'regular' && sizeYClassNames[sizeY],\n withPlaceholder && styles.hasPlaceholder,\n inputValue && styles.hasInputValue,\n )}\n ref={containerRef}\n onKeyDown={disabled ? undefined : handleListboxKeyDown}\n >\n <div\n className={styles.listBox}\n // для a11y\n ref={listboxRef}\n role=\"listbox\"\n aria-orientation=\"horizontal\"\n aria-disabled={disabled}\n aria-readonly={readOnly}\n aria-label={chipsListLabel}\n >\n {value.map((option, index) => (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderChip(\n {\n 'Component': 'div',\n 'value': option.value,\n 'label': option.label,\n 'disabled': option.disabled || disabled,\n 'readOnly': option.readOnly || readOnly,\n 'className': styles.chip,\n 'onRemove': handleChipRemove,\n // чтобы можно было легче найти этот чип в DOM\n 'data-index': index,\n 'data-value': option.value,\n 'data-value-type': typeof option.value,\n // для a11y\n 'tabIndex': lastFocusedChipOptionIndex === index ? 0 : -1,\n 'role': 'option',\n 'aria-selected': true,\n 'aria-posinset': index + 1,\n 'aria-setsize': valueLength,\n 'aria-description': 'Для удаления используйте Backspace или Delete',\n },\n option,\n )}\n </React.Fragment>\n ))}\n </div>\n <Text\n autoCapitalize=\"none\"\n autoComplete=\"off\"\n autoCorrect=\"off\"\n spellCheck={false}\n {...restProps}\n aria-label={ariaLabel}\n Component=\"input\"\n type=\"text\"\n id={inputId}\n getRootRef={inputRef}\n className={styles.el}\n disabled={disabled}\n readOnly={readOnly}\n placeholder={withPlaceholder ? placeholder : undefined}\n value={inputValue}\n onChange={onInputChange}\n onBlur={handleInputBlur}\n />\n </div>\n </FormField>\n );\n};\n"],"names":["React","classNames","isHTMLElement","useAdaptivity","useExternRef","getHorizontalFocusGoTo","Keys","contains","checkTargetIsInputEl","getActiveElementByAnotherElement","FormField","FormFieldClearButton","Text","DEFAULT_INPUT_VALUE","DEFAULT_VALUE","renderChipDefault","getChipOptionIndexByHTMLElement","getChipOptionIndexByValueProp","getChipOptionValueByHTMLElement","getNextChipOptionIndexByNavigateToProp","isInputValueEmpty","styles","sizeYClassNames","none","sizeYNone","compact","sizeYCompact","ChipsInputBase","getRootRef","style","className","before","after","status","mode","maxHeight","value","onAddChipOption","onRemoveChipOptionProp","renderChip","getRef","idProp","inputValue","placeholder","disabled","readOnly","addOnBlur","onBlur","onInputChange","ClearButton","clearButtonShown","clearButtonTestId","onClear","chipsListLabel","ariaLabel","restProps","sizeY","idGenerated","useId","inputRef","containerRef","useRef","listboxRef","valueLength","length","withPlaceholder","lastFocusedChipOptionIndex","setLastFocusedChipOptionIndex","useState","resetChipOptionFocusToInputEl","inputEl","focus","moveFocusToChipOption","currentIndex","navigateTo","listboxEl","index","foundEl","querySelector","removeChipOption","o","current","handleListboxKeyDown","event","targetEl","target","defaultPrevented","key","ENTER","preventDefault","DELETE","BACKSPACE","HOME","END","ARROW_UP","ARROW_LEFT","ARROW_DOWN","ARROW_RIGHT","handleInputBlur","handleChipRemove","v","stopPropagation","handleRootClick","activeElement","currentTarget","handleClear","useCallback","clearButton","useMemo","onClick","data-testid","undefined","afterItems","inputId","handleRootMouseDown","e","Component","role","aria-label","onMouseDown","div","host","hasPlaceholder","hasInputValue","ref","onKeyDown","listBox","aria-orientation","aria-disabled","aria-readonly","map","option","Fragment","label","chip","autoCapitalize","autoComplete","autoCorrect","spellCheck","type","id","el","onChange"],"mappings":"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"}
@@ -222,10 +222,8 @@ chipsListLabel, ...restProps })=>{
222
222
  ]);
223
223
  useGlobalOnEventOutside('mousedown', handleClickOutside, opened ? rootRef : null, opened ? dropdownScrollBoxRef : null);
224
224
  const onDropdownIconClick = React.useCallback((e)=>{
225
- if (opened) {
226
- e.preventDefault();
227
- setOpened(false);
228
- }
225
+ e.preventDefault();
226
+ setOpened(!opened);
229
227
  }, [
230
228
  opened,
231
229
  setOpened
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/ChipsSelect/ChipsSelect.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { type MouseEventHandler } from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useGlobalOnEventOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { Keys } from '../../lib/accessibility';\nimport type { Placement } from '../../lib/floating';\nimport { defaultFilterFn } from '../../lib/select';\nimport { ChipsInputBase } from '../ChipsInputBase/ChipsInputBase';\nimport {\n getNewOptionDataDefault,\n getOptionLabelDefault,\n getOptionValueDefault,\n renderChipDefault,\n} from '../ChipsInputBase/constants';\nimport type { ChipOption, ChipsInputBaseProps } from '../ChipsInputBase/types';\nimport {\n CustomSelectDropdown,\n type CustomSelectDropdownProps,\n} from '../CustomSelectDropdown/CustomSelectDropdown';\nimport {\n CustomSelectOption,\n type CustomSelectOptionProps,\n} from '../CustomSelectOption/CustomSelectOption';\nimport { DropdownIcon } from '../DropdownIcon/DropdownIcon';\nimport type { FormFieldProps } from '../FormField/FormField';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport {\n DEFAULT_EMPTY_TEXT,\n DEFAULT_SELECTED_BEHAVIOR,\n FOCUS_ACTION_NEXT,\n FOCUS_ACTION_PREV,\n isCreateNewOptionPreset,\n isEmptyOptionPreset,\n isNotServicePreset,\n renderOptionDefault,\n} from './constants';\nimport type { FocusActionType, OptionPreset } from './types';\nimport { useChipsSelect, type UseChipsSelectProps } from './useChipsSelect';\nimport styles from './ChipsSelect.module.css';\n\nconst findIndexAfter = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n startIndex = -1,\n) => {\n if (startIndex >= options.length - 1) {\n return -1;\n }\n return options.findIndex(\n (option, i) => i > startIndex && (!isNotServicePreset(option) || !option.disabled),\n );\n};\n\nconst findIndexBefore = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n endIndex: number = options.length,\n) => {\n let result = -1;\n if (endIndex <= 0) {\n return result;\n }\n for (let i = endIndex - 1; i >= 0; i--) {\n let option = options[i];\n\n if (!isNotServicePreset(option) || !option.disabled) {\n result = i;\n break;\n }\n }\n return result;\n};\n\nexport interface ChipsSelectProps<O extends ChipOption>\n extends ChipsInputBaseProps<O>,\n UseChipsSelectProps<O>,\n Pick<FormFieldProps, 'status' | 'mode' | 'before'>,\n Pick<CustomSelectDropdownProps, 'overscrollBehavior'> {\n /**\n * Расположение выпадающего списка.\n */\n placement?: 'top' | 'bottom';\n /**\n * Отрисовка Spinner вместо списка опций в выпадающем списке.\n */\n fetching?: boolean;\n /**\n * Закрытие выпадающего списка после выбора элемента.\n */\n closeAfterSelect?: boolean;\n /**\n * Ширина раскрывающегося списка зависит от контента.\n */\n dropdownAutoWidth?: boolean;\n /**\n * Принудительно использовать портал.\n */\n forceDropdownPortal?: boolean;\n /**\n * Передает атрибут `data-testid` для дропдауна.\n */\n dropdownTestId?: string;\n /**\n * Иконка раскрывающегося списка.\n */\n icon?: React.ReactNode;\n /**\n * Добавляет значение в список на событие `onBlur` (использовать вместе с `creatable`).\n */\n addOnBlur?: boolean;\n /**\n * Отключает максимальную высоту по умолчанию.\n */\n noMaxHeight?: boolean;\n /**\n * Функция для отрисовки кастомной опции в выпадающем списке.\n */\n renderOption?: (props: CustomSelectOptionProps, option: O) => React.ReactNode;\n /**\n * Рендер-проп для кастомного рендера содержимого дропдауна.\n * В `defaultDropdownContent` содержится список опций.\n */\n renderDropdown?: ({\n defaultDropdownContent,\n }: {\n defaultDropdownContent: React.ReactNode;\n }) => React.ReactNode;\n /**\n * Событие срабатывающее перед `onChange`.\n */\n onChangeStart?: (event: React.MouseEvent | React.KeyboardEvent, option: O) => void;\n\n /**\n * Отступ от выпадающего списка.\n */\n dropdownOffsetDistance?: number;\n\n /**\n * Если `true`, то справа будет отображаться кнопка для очистки значения.\n */\n allowClearButton?: boolean;\n}\n\n/**\n * @see https://vkui.io/components/chips-select\n */\nexport const ChipsSelect = <Option extends ChipOption>({\n // FormFieldProps\n id: labelledbyId,\n getRootRef,\n className,\n status = 'default',\n icon: dropdownIconProp,\n onChangeStart,\n\n // CustomSelectDropdownProps\n options: optionsProp,\n placement: placementProp = 'bottom',\n closeAfterSelect = true,\n selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,\n emptyText = DEFAULT_EMPTY_TEXT,\n creatable = false,\n fetching = false,\n dropdownAutoWidth,\n forceDropdownPortal,\n noMaxHeight = false,\n filterFn = defaultFilterFn,\n sortFn = false,\n dropdownTestId,\n onClose,\n onOpen,\n overscrollBehavior,\n renderDropdown,\n\n // ChipsInputProps\n getRef,\n value: valueProp,\n defaultValue,\n inputValue: inputValueProp,\n defaultInputValue,\n disabled,\n readOnly,\n getOptionValue = getOptionValueDefault,\n getOptionLabel = getOptionLabelDefault,\n getNewOptionData = getNewOptionDataDefault,\n renderChip = renderChipDefault,\n renderOption = renderOptionDefault,\n onChange,\n onFocus: onFocusProp,\n onInputChange: onInputChangeProp,\n onBlur: onBlurProp,\n onKeyDown: onKeyDownProp,\n dropdownOffsetDistance = 0,\n allowClearButton,\n clearButtonTestId,\n delimiter,\n\n // a11y\n chipsListLabel,\n ...restProps\n}: ChipsSelectProps<Option>): React.ReactNode => {\n const {\n // Связано с ChipsInputProps\n // option\n value,\n addOptionFromInput,\n addOption,\n removeOption,\n clearOptions,\n // input\n inputRef: inputRefHook,\n inputValue,\n clearInput,\n onInputChange,\n\n // Связано с CustomSelectDropdownProps\n options,\n opened,\n setOpened,\n focusedOption,\n focusedOptionIndex,\n setFocusedOption,\n setFocusedOptionIndex,\n } = useChipsSelect({\n // option\n value: valueProp,\n defaultValue,\n onChange,\n getOptionValue,\n getOptionLabel,\n getNewOptionData,\n\n // input\n inputValue: inputValueProp,\n defaultInputValue,\n onInputChange: onInputChangeProp,\n\n // dropdown\n options: optionsProp,\n emptyText,\n creatable,\n filterFn,\n sortFn,\n selectedBehavior,\n onClose,\n onOpen,\n\n // other\n disabled,\n delimiter,\n });\n\n // Связано с ChipsInputProps\n const rootRef = useExternRef(getRootRef);\n const inputRef = useExternRef(getRef, inputRefHook);\n\n // Связано с CustomSelectDropdownProps\n const [dropdownVerticalPlacement, setDropdownVerticalPlacement] = React.useState<\n 'top' | 'bottom'\n >(placementProp);\n\n const onDropdownPlacementChange = React.useCallback((placement: Placement) => {\n if (placement.startsWith('top')) {\n setDropdownVerticalPlacement('top');\n } else if (placement.startsWith('bottom')) {\n setDropdownVerticalPlacement('bottom');\n }\n }, []);\n\n const dropdownId = React.useId();\n const dropdownCurrentItemId =\n focusedOptionIndex !== null ? `${dropdownId}-${focusedOptionIndex}` : undefined;\n const dropdownScrollBoxRef = React.useRef<HTMLDivElement>(null);\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onFocusProp) {\n onFocusProp(event);\n }\n\n if (!readOnly) {\n setOpened(true);\n setFocusedOptionIndex(null);\n }\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlurProp) {\n onBlurProp(event);\n }\n\n // Не добавляем значение, если его нужно выбрать строго из списка\n if (!readOnly && !event.defaultPrevented && !creatable) {\n event.preventDefault();\n }\n };\n\n const chipsSelectOptions = React.useRef<HTMLElement[]>([]).current;\n\n const scrollToElement = (index: number, center = false) => {\n const dropdown = dropdownScrollBoxRef.current;\n const item = chipsSelectOptions[index];\n\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!item || !dropdown) {\n return;\n }\n\n const dropdownHeight = dropdown.offsetHeight;\n const scrollTop = dropdown.scrollTop;\n const itemTop = item.offsetTop;\n const itemHeight = item.offsetHeight;\n\n /* istanbul ignore next: нет представления как воспроизвести */\n if (center) {\n dropdown.scrollTop = itemTop - dropdownHeight / 2 + itemHeight / 2;\n } else if (itemTop + itemHeight > dropdownHeight + scrollTop) {\n dropdown.scrollTop = itemTop - dropdownHeight + itemHeight;\n } else if (itemTop < scrollTop) {\n dropdown.scrollTop = itemTop;\n }\n };\n\n const focusOptionByIndex = (index: number, oldIndex: number | null) => {\n if (index === oldIndex) {\n /* istanbul ignore next: нет представления как воспроизвести */\n return;\n }\n\n const option = options[index];\n\n if (isNotServicePreset(option) && option.disabled) {\n return;\n }\n\n scrollToElement(index);\n setFocusedOptionIndex(index);\n };\n\n const focusOption = (nextIndex: number | null, type: FocusActionType) => {\n let index = nextIndex === null ? -1 : nextIndex;\n\n if (type === FOCUS_ACTION_NEXT) {\n const nextIndex = findIndexAfter(options, index);\n index = nextIndex === -1 ? findIndexAfter(options) : nextIndex; // Следующий за index или первый валидный до index\n } else if (type === FOCUS_ACTION_PREV) {\n const beforeIndex = findIndexBefore(options, index);\n index = beforeIndex === -1 ? findIndexBefore(options) : beforeIndex; // Предшествующий index или последний валидный после index\n }\n\n focusOptionByIndex(index, focusedOptionIndex);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (onKeyDownProp) {\n onKeyDownProp(event);\n }\n\n if (event.defaultPrevented || readOnly) {\n return;\n }\n\n switch (event.key) {\n case Keys.ARROW_UP:\n case Keys.ARROW_DOWN:\n event.preventDefault();\n\n if (!opened) {\n setOpened(true);\n focusOption(null, FOCUS_ACTION_NEXT);\n } else {\n focusOption(\n focusedOptionIndex,\n event.key === Keys.ARROW_UP ? FOCUS_ACTION_PREV : FOCUS_ACTION_NEXT,\n );\n }\n break;\n case Keys.ENTER: {\n if (!opened) {\n break;\n }\n if (focusedOptionIndex != null) {\n const foundOption = options[focusedOptionIndex];\n if (foundOption && isNotServicePreset(foundOption)) {\n event.preventDefault();\n\n if (onChangeStart) {\n onChangeStart(event, foundOption);\n }\n\n addOption(foundOption);\n setFocusedOptionIndex(null);\n clearInput();\n if (closeAfterSelect) {\n setOpened(false);\n }\n\n break;\n }\n }\n\n if (!creatable) {\n event.preventDefault();\n }\n break;\n }\n case Keys.ESCAPE:\n case Keys.TAB:\n if (opened) {\n setOpened(false);\n }\n }\n };\n\n React.useEffect(() => {\n if (focusedOptionIndex === null) {\n setFocusedOption(null);\n } else {\n const foundFocusedOptionIndex = options[focusedOptionIndex];\n\n if (foundFocusedOptionIndex && isNotServicePreset(foundFocusedOptionIndex)) {\n setFocusedOption(foundFocusedOptionIndex);\n }\n }\n }, [options, focusedOptionIndex, setFocusedOption]);\n\n const onDropdownMouseLeave = React.useCallback(() => {\n setFocusedOptionIndex(null);\n }, [setFocusedOptionIndex]);\n\n const handleClickOutside = React.useCallback(() => {\n setOpened(false);\n }, [setOpened]);\n\n useGlobalOnEventOutside(\n 'mousedown', // см. https://github.com/VKCOM/VKUI/pull/8582\n handleClickOutside,\n opened ? rootRef : null,\n opened ? dropdownScrollBoxRef : null,\n );\n\n const onDropdownIconClick: MouseEventHandler<SVGSVGElement> = React.useCallback(\n (e) => {\n if (opened) {\n e.preventDefault();\n setOpened(false);\n }\n },\n [opened, setOpened],\n );\n\n const dropdownContent = React.useMemo(() => {\n const defaultDropdownContent = options.map((option, index) => {\n const dropdownItemId = `${dropdownId}-${index}`;\n\n if (isEmptyOptionPreset(option)) {\n return (\n <Footnote key=\"empty-text\" className={styles.empty}>\n {option.placeholder}\n </Footnote>\n );\n }\n if (isCreateNewOptionPreset(option)) {\n return (\n <CustomSelectOption\n key=\"create-new-option\"\n id={dropdownItemId}\n hovered={focusedOptionIndex === index}\n onMouseDown={() => addOptionFromInput(inputValue)}\n onMouseEnter={() => setFocusedOptionIndex(index)}\n >\n {option.actionText}\n </CustomSelectOption>\n );\n }\n return (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderOption(\n {\n id: dropdownItemId,\n disabled: option.disabled,\n hovered: focusedOption\n ? getOptionValue(option) === getOptionValue(focusedOption)\n : false,\n children: option.label,\n selected: !!value.find(\n (selectedOption: Option) =>\n getOptionValue(selectedOption) === getOptionValue(option),\n ),\n getRootRef(node) {\n if (node) {\n chipsSelectOptions[index] = node;\n }\n },\n onMouseDown(event: React.MouseEvent<HTMLDivElement>) {\n if (option.disabled) {\n return;\n }\n if (onChangeStart) {\n onChangeStart(event, option);\n }\n\n if (!event.defaultPrevented) {\n closeAfterSelect && setOpened(false);\n addOption(option);\n clearInput();\n }\n },\n onMouseEnter() {\n setFocusedOptionIndex(index);\n },\n },\n option,\n )}\n </React.Fragment>\n );\n });\n\n if (renderDropdown) {\n return renderDropdown({\n defaultDropdownContent,\n });\n }\n return defaultDropdownContent;\n }, [\n addOption,\n addOptionFromInput,\n chipsSelectOptions,\n clearInput,\n closeAfterSelect,\n dropdownId,\n focusedOption,\n focusedOptionIndex,\n getOptionValue,\n inputValue,\n onChangeStart,\n options,\n renderDropdown,\n renderOption,\n setFocusedOptionIndex,\n setOpened,\n value,\n ]);\n\n const openedClassNames = React.useMemo(\n () =>\n (opened &&\n dropdownOffsetDistance === 0 &&\n (dropdownVerticalPlacement.includes('top') ? styles.popUp : styles.popDown)) ||\n undefined,\n [dropdownOffsetDistance, opened, dropdownVerticalPlacement],\n );\n\n const clearButtonShown = allowClearButton && (!!value.length || !!inputValue.length);\n\n return (\n <>\n <ChipsInputBase\n {...restProps}\n disabled={disabled}\n readOnly={readOnly}\n clearButtonShown={clearButtonShown}\n clearButtonTestId={clearButtonTestId}\n // FormFieldProps\n id={labelledbyId}\n getRootRef={rootRef}\n className={classNames(styles.host, openedClassNames, className)}\n status={status}\n after={\n dropdownIconProp || (\n <DropdownIcon\n opened={opened}\n onClick={onDropdownIconClick}\n className={classNames(\n styles.dropdownIcon,\n clearButtonShown && styles.dropdownIconWithOffset,\n )}\n />\n )\n }\n // option\n value={value}\n onAddChipOption={addOptionFromInput}\n onRemoveChipOption={removeOption}\n renderChip={renderChip}\n onClear={clearOptions}\n // input\n getRef={inputRef}\n inputValue={inputValue}\n onInputChange={onInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n // a11y\n role=\"combobox\"\n aria-expanded={opened}\n aria-autocomplete=\"list\"\n aria-activedescendant={opened ? dropdownCurrentItemId : undefined}\n aria-haspopup=\"listbox\"\n chipsListLabel={chipsListLabel}\n />\n {opened && (\n <CustomSelectDropdown\n data-testid={dropdownTestId}\n targetRef={rootRef}\n placement={dropdownVerticalPlacement}\n scrollBoxRef={dropdownScrollBoxRef}\n onPlacementChange={onDropdownPlacementChange}\n onMouseLeave={onDropdownMouseLeave}\n fetching={fetching}\n autoWidth={dropdownAutoWidth}\n forcePortal={forceDropdownPortal}\n noMaxHeight={noMaxHeight}\n offsetDistance={dropdownOffsetDistance}\n overscrollBehavior={overscrollBehavior}\n // a11y\n id={dropdownId}\n role=\"listbox\"\n aria-labelledby={labelledbyId}\n >\n {dropdownContent}\n </CustomSelectDropdown>\n )}\n </>\n );\n};\n"],"names":["React","classNames","useExternRef","useGlobalOnEventOutside","Keys","defaultFilterFn","ChipsInputBase","getNewOptionDataDefault","getOptionLabelDefault","getOptionValueDefault","renderChipDefault","CustomSelectDropdown","CustomSelectOption","DropdownIcon","Footnote","DEFAULT_EMPTY_TEXT","DEFAULT_SELECTED_BEHAVIOR","FOCUS_ACTION_NEXT","FOCUS_ACTION_PREV","isCreateNewOptionPreset","isEmptyOptionPreset","isNotServicePreset","renderOptionDefault","useChipsSelect","styles","findIndexAfter","options","startIndex","length","findIndex","option","i","disabled","findIndexBefore","endIndex","result","ChipsSelect","id","labelledbyId","getRootRef","className","status","icon","dropdownIconProp","onChangeStart","optionsProp","placement","placementProp","closeAfterSelect","selectedBehavior","emptyText","creatable","fetching","dropdownAutoWidth","forceDropdownPortal","noMaxHeight","filterFn","sortFn","dropdownTestId","onClose","onOpen","overscrollBehavior","renderDropdown","getRef","value","valueProp","defaultValue","inputValue","inputValueProp","defaultInputValue","readOnly","getOptionValue","getOptionLabel","getNewOptionData","renderChip","renderOption","onChange","onFocus","onFocusProp","onInputChange","onInputChangeProp","onBlur","onBlurProp","onKeyDown","onKeyDownProp","dropdownOffsetDistance","allowClearButton","clearButtonTestId","delimiter","chipsListLabel","restProps","addOptionFromInput","addOption","removeOption","clearOptions","inputRef","inputRefHook","clearInput","opened","setOpened","focusedOption","focusedOptionIndex","setFocusedOption","setFocusedOptionIndex","rootRef","dropdownVerticalPlacement","setDropdownVerticalPlacement","useState","onDropdownPlacementChange","useCallback","startsWith","dropdownId","useId","dropdownCurrentItemId","undefined","dropdownScrollBoxRef","useRef","handleFocus","event","handleBlur","defaultPrevented","preventDefault","chipsSelectOptions","current","scrollToElement","index","center","dropdown","item","dropdownHeight","offsetHeight","scrollTop","itemTop","offsetTop","itemHeight","focusOptionByIndex","oldIndex","focusOption","nextIndex","type","beforeIndex","handleKeyDown","key","ARROW_UP","ARROW_DOWN","ENTER","foundOption","ESCAPE","TAB","useEffect","foundFocusedOptionIndex","onDropdownMouseLeave","handleClickOutside","onDropdownIconClick","e","dropdownContent","useMemo","defaultDropdownContent","map","dropdownItemId","empty","placeholder","hovered","onMouseDown","onMouseEnter","actionText","Fragment","children","label","selected","find","selectedOption","node","openedClassNames","includes","popUp","popDown","clearButtonShown","host","after","onClick","dropdownIcon","dropdownIconWithOffset","onAddChipOption","onRemoveChipOption","onClear","role","aria-expanded","aria-autocomplete","aria-activedescendant","aria-haspopup","data-testid","targetRef","scrollBoxRef","onPlacementChange","onMouseLeave","autoWidth","forcePortal","offsetDistance","aria-labelledby"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/components/ChipsSelect/ChipsSelect.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { type MouseEventHandler } from 'react';\nimport { classNames } from '@vkontakte/vkjs';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useGlobalOnEventOutside } from '../../hooks/useGlobalOnClickOutside';\nimport { Keys } from '../../lib/accessibility';\nimport type { Placement } from '../../lib/floating';\nimport { defaultFilterFn } from '../../lib/select';\nimport { ChipsInputBase } from '../ChipsInputBase/ChipsInputBase';\nimport {\n getNewOptionDataDefault,\n getOptionLabelDefault,\n getOptionValueDefault,\n renderChipDefault,\n} from '../ChipsInputBase/constants';\nimport type { ChipOption, ChipsInputBaseProps } from '../ChipsInputBase/types';\nimport {\n CustomSelectDropdown,\n type CustomSelectDropdownProps,\n} from '../CustomSelectDropdown/CustomSelectDropdown';\nimport {\n CustomSelectOption,\n type CustomSelectOptionProps,\n} from '../CustomSelectOption/CustomSelectOption';\nimport { DropdownIcon } from '../DropdownIcon/DropdownIcon';\nimport type { FormFieldProps } from '../FormField/FormField';\nimport { Footnote } from '../Typography/Footnote/Footnote';\nimport {\n DEFAULT_EMPTY_TEXT,\n DEFAULT_SELECTED_BEHAVIOR,\n FOCUS_ACTION_NEXT,\n FOCUS_ACTION_PREV,\n isCreateNewOptionPreset,\n isEmptyOptionPreset,\n isNotServicePreset,\n renderOptionDefault,\n} from './constants';\nimport type { FocusActionType, OptionPreset } from './types';\nimport { useChipsSelect, type UseChipsSelectProps } from './useChipsSelect';\nimport styles from './ChipsSelect.module.css';\n\nconst findIndexAfter = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n startIndex = -1,\n) => {\n if (startIndex >= options.length - 1) {\n return -1;\n }\n return options.findIndex(\n (option, i) => i > startIndex && (!isNotServicePreset(option) || !option.disabled),\n );\n};\n\nconst findIndexBefore = <O extends ChipOption>(\n options: Array<OptionPreset<O>> = [],\n endIndex: number = options.length,\n) => {\n let result = -1;\n if (endIndex <= 0) {\n return result;\n }\n for (let i = endIndex - 1; i >= 0; i--) {\n let option = options[i];\n\n if (!isNotServicePreset(option) || !option.disabled) {\n result = i;\n break;\n }\n }\n return result;\n};\n\nexport interface ChipsSelectProps<O extends ChipOption>\n extends ChipsInputBaseProps<O>,\n UseChipsSelectProps<O>,\n Pick<FormFieldProps, 'status' | 'mode' | 'before'>,\n Pick<CustomSelectDropdownProps, 'overscrollBehavior'> {\n /**\n * Расположение выпадающего списка.\n */\n placement?: 'top' | 'bottom';\n /**\n * Отрисовка Spinner вместо списка опций в выпадающем списке.\n */\n fetching?: boolean;\n /**\n * Закрытие выпадающего списка после выбора элемента.\n */\n closeAfterSelect?: boolean;\n /**\n * Ширина раскрывающегося списка зависит от контента.\n */\n dropdownAutoWidth?: boolean;\n /**\n * Принудительно использовать портал.\n */\n forceDropdownPortal?: boolean;\n /**\n * Передает атрибут `data-testid` для дропдауна.\n */\n dropdownTestId?: string;\n /**\n * Иконка раскрывающегося списка.\n */\n icon?: React.ReactNode;\n /**\n * Добавляет значение в список на событие `onBlur` (использовать вместе с `creatable`).\n */\n addOnBlur?: boolean;\n /**\n * Отключает максимальную высоту по умолчанию.\n */\n noMaxHeight?: boolean;\n /**\n * Функция для отрисовки кастомной опции в выпадающем списке.\n */\n renderOption?: (props: CustomSelectOptionProps, option: O) => React.ReactNode;\n /**\n * Рендер-проп для кастомного рендера содержимого дропдауна.\n * В `defaultDropdownContent` содержится список опций.\n */\n renderDropdown?: ({\n defaultDropdownContent,\n }: {\n defaultDropdownContent: React.ReactNode;\n }) => React.ReactNode;\n /**\n * Событие срабатывающее перед `onChange`.\n */\n onChangeStart?: (event: React.MouseEvent | React.KeyboardEvent, option: O) => void;\n\n /**\n * Отступ от выпадающего списка.\n */\n dropdownOffsetDistance?: number;\n\n /**\n * Если `true`, то справа будет отображаться кнопка для очистки значения.\n */\n allowClearButton?: boolean;\n}\n\n/**\n * @see https://vkui.io/components/chips-select\n */\nexport const ChipsSelect = <Option extends ChipOption>({\n // FormFieldProps\n id: labelledbyId,\n getRootRef,\n className,\n status = 'default',\n icon: dropdownIconProp,\n onChangeStart,\n\n // CustomSelectDropdownProps\n options: optionsProp,\n placement: placementProp = 'bottom',\n closeAfterSelect = true,\n selectedBehavior = DEFAULT_SELECTED_BEHAVIOR,\n emptyText = DEFAULT_EMPTY_TEXT,\n creatable = false,\n fetching = false,\n dropdownAutoWidth,\n forceDropdownPortal,\n noMaxHeight = false,\n filterFn = defaultFilterFn,\n sortFn = false,\n dropdownTestId,\n onClose,\n onOpen,\n overscrollBehavior,\n renderDropdown,\n\n // ChipsInputProps\n getRef,\n value: valueProp,\n defaultValue,\n inputValue: inputValueProp,\n defaultInputValue,\n disabled,\n readOnly,\n getOptionValue = getOptionValueDefault,\n getOptionLabel = getOptionLabelDefault,\n getNewOptionData = getNewOptionDataDefault,\n renderChip = renderChipDefault,\n renderOption = renderOptionDefault,\n onChange,\n onFocus: onFocusProp,\n onInputChange: onInputChangeProp,\n onBlur: onBlurProp,\n onKeyDown: onKeyDownProp,\n dropdownOffsetDistance = 0,\n allowClearButton,\n clearButtonTestId,\n delimiter,\n\n // a11y\n chipsListLabel,\n ...restProps\n}: ChipsSelectProps<Option>): React.ReactNode => {\n const {\n // Связано с ChipsInputProps\n // option\n value,\n addOptionFromInput,\n addOption,\n removeOption,\n clearOptions,\n // input\n inputRef: inputRefHook,\n inputValue,\n clearInput,\n onInputChange,\n\n // Связано с CustomSelectDropdownProps\n options,\n opened,\n setOpened,\n focusedOption,\n focusedOptionIndex,\n setFocusedOption,\n setFocusedOptionIndex,\n } = useChipsSelect({\n // option\n value: valueProp,\n defaultValue,\n onChange,\n getOptionValue,\n getOptionLabel,\n getNewOptionData,\n\n // input\n inputValue: inputValueProp,\n defaultInputValue,\n onInputChange: onInputChangeProp,\n\n // dropdown\n options: optionsProp,\n emptyText,\n creatable,\n filterFn,\n sortFn,\n selectedBehavior,\n onClose,\n onOpen,\n\n // other\n disabled,\n delimiter,\n });\n\n // Связано с ChipsInputProps\n const rootRef = useExternRef(getRootRef);\n const inputRef = useExternRef(getRef, inputRefHook);\n\n // Связано с CustomSelectDropdownProps\n const [dropdownVerticalPlacement, setDropdownVerticalPlacement] = React.useState<\n 'top' | 'bottom'\n >(placementProp);\n\n const onDropdownPlacementChange = React.useCallback((placement: Placement) => {\n if (placement.startsWith('top')) {\n setDropdownVerticalPlacement('top');\n } else if (placement.startsWith('bottom')) {\n setDropdownVerticalPlacement('bottom');\n }\n }, []);\n\n const dropdownId = React.useId();\n const dropdownCurrentItemId =\n focusedOptionIndex !== null ? `${dropdownId}-${focusedOptionIndex}` : undefined;\n const dropdownScrollBoxRef = React.useRef<HTMLDivElement>(null);\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onFocusProp) {\n onFocusProp(event);\n }\n\n if (!readOnly) {\n setOpened(true);\n setFocusedOptionIndex(null);\n }\n };\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n if (onBlurProp) {\n onBlurProp(event);\n }\n\n // Не добавляем значение, если его нужно выбрать строго из списка\n if (!readOnly && !event.defaultPrevented && !creatable) {\n event.preventDefault();\n }\n };\n\n const chipsSelectOptions = React.useRef<HTMLElement[]>([]).current;\n\n const scrollToElement = (index: number, center = false) => {\n const dropdown = dropdownScrollBoxRef.current;\n const item = chipsSelectOptions[index];\n\n /* istanbul ignore if: невозможный кейс (в SSR вызова этой функции не будет) */\n if (!item || !dropdown) {\n return;\n }\n\n const dropdownHeight = dropdown.offsetHeight;\n const scrollTop = dropdown.scrollTop;\n const itemTop = item.offsetTop;\n const itemHeight = item.offsetHeight;\n\n /* istanbul ignore next: нет представления как воспроизвести */\n if (center) {\n dropdown.scrollTop = itemTop - dropdownHeight / 2 + itemHeight / 2;\n } else if (itemTop + itemHeight > dropdownHeight + scrollTop) {\n dropdown.scrollTop = itemTop - dropdownHeight + itemHeight;\n } else if (itemTop < scrollTop) {\n dropdown.scrollTop = itemTop;\n }\n };\n\n const focusOptionByIndex = (index: number, oldIndex: number | null) => {\n if (index === oldIndex) {\n /* istanbul ignore next: нет представления как воспроизвести */\n return;\n }\n\n const option = options[index];\n\n if (isNotServicePreset(option) && option.disabled) {\n return;\n }\n\n scrollToElement(index);\n setFocusedOptionIndex(index);\n };\n\n const focusOption = (nextIndex: number | null, type: FocusActionType) => {\n let index = nextIndex === null ? -1 : nextIndex;\n\n if (type === FOCUS_ACTION_NEXT) {\n const nextIndex = findIndexAfter(options, index);\n index = nextIndex === -1 ? findIndexAfter(options) : nextIndex; // Следующий за index или первый валидный до index\n } else if (type === FOCUS_ACTION_PREV) {\n const beforeIndex = findIndexBefore(options, index);\n index = beforeIndex === -1 ? findIndexBefore(options) : beforeIndex; // Предшествующий index или последний валидный после index\n }\n\n focusOptionByIndex(index, focusedOptionIndex);\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {\n if (onKeyDownProp) {\n onKeyDownProp(event);\n }\n\n if (event.defaultPrevented || readOnly) {\n return;\n }\n\n switch (event.key) {\n case Keys.ARROW_UP:\n case Keys.ARROW_DOWN:\n event.preventDefault();\n\n if (!opened) {\n setOpened(true);\n focusOption(null, FOCUS_ACTION_NEXT);\n } else {\n focusOption(\n focusedOptionIndex,\n event.key === Keys.ARROW_UP ? FOCUS_ACTION_PREV : FOCUS_ACTION_NEXT,\n );\n }\n break;\n case Keys.ENTER: {\n if (!opened) {\n break;\n }\n if (focusedOptionIndex != null) {\n const foundOption = options[focusedOptionIndex];\n if (foundOption && isNotServicePreset(foundOption)) {\n event.preventDefault();\n\n if (onChangeStart) {\n onChangeStart(event, foundOption);\n }\n\n addOption(foundOption);\n setFocusedOptionIndex(null);\n clearInput();\n if (closeAfterSelect) {\n setOpened(false);\n }\n\n break;\n }\n }\n\n if (!creatable) {\n event.preventDefault();\n }\n break;\n }\n case Keys.ESCAPE:\n case Keys.TAB:\n if (opened) {\n setOpened(false);\n }\n }\n };\n\n React.useEffect(() => {\n if (focusedOptionIndex === null) {\n setFocusedOption(null);\n } else {\n const foundFocusedOptionIndex = options[focusedOptionIndex];\n\n if (foundFocusedOptionIndex && isNotServicePreset(foundFocusedOptionIndex)) {\n setFocusedOption(foundFocusedOptionIndex);\n }\n }\n }, [options, focusedOptionIndex, setFocusedOption]);\n\n const onDropdownMouseLeave = React.useCallback(() => {\n setFocusedOptionIndex(null);\n }, [setFocusedOptionIndex]);\n\n const handleClickOutside = React.useCallback(() => {\n setOpened(false);\n }, [setOpened]);\n\n useGlobalOnEventOutside(\n 'mousedown', // см. https://github.com/VKCOM/VKUI/pull/8582\n handleClickOutside,\n opened ? rootRef : null,\n opened ? dropdownScrollBoxRef : null,\n );\n\n const onDropdownIconClick: MouseEventHandler<SVGSVGElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n setOpened(!opened);\n },\n [opened, setOpened],\n );\n\n const dropdownContent = React.useMemo(() => {\n const defaultDropdownContent = options.map((option, index) => {\n const dropdownItemId = `${dropdownId}-${index}`;\n\n if (isEmptyOptionPreset(option)) {\n return (\n <Footnote key=\"empty-text\" className={styles.empty}>\n {option.placeholder}\n </Footnote>\n );\n }\n if (isCreateNewOptionPreset(option)) {\n return (\n <CustomSelectOption\n key=\"create-new-option\"\n id={dropdownItemId}\n hovered={focusedOptionIndex === index}\n onMouseDown={() => addOptionFromInput(inputValue)}\n onMouseEnter={() => setFocusedOptionIndex(index)}\n >\n {option.actionText}\n </CustomSelectOption>\n );\n }\n return (\n <React.Fragment key={`${typeof option.value}-${option.value}`}>\n {renderOption(\n {\n id: dropdownItemId,\n disabled: option.disabled,\n hovered: focusedOption\n ? getOptionValue(option) === getOptionValue(focusedOption)\n : false,\n children: option.label,\n selected: !!value.find(\n (selectedOption: Option) =>\n getOptionValue(selectedOption) === getOptionValue(option),\n ),\n getRootRef(node) {\n if (node) {\n chipsSelectOptions[index] = node;\n }\n },\n onMouseDown(event: React.MouseEvent<HTMLDivElement>) {\n if (option.disabled) {\n return;\n }\n if (onChangeStart) {\n onChangeStart(event, option);\n }\n\n if (!event.defaultPrevented) {\n closeAfterSelect && setOpened(false);\n addOption(option);\n clearInput();\n }\n },\n onMouseEnter() {\n setFocusedOptionIndex(index);\n },\n },\n option,\n )}\n </React.Fragment>\n );\n });\n\n if (renderDropdown) {\n return renderDropdown({\n defaultDropdownContent,\n });\n }\n return defaultDropdownContent;\n }, [\n addOption,\n addOptionFromInput,\n chipsSelectOptions,\n clearInput,\n closeAfterSelect,\n dropdownId,\n focusedOption,\n focusedOptionIndex,\n getOptionValue,\n inputValue,\n onChangeStart,\n options,\n renderDropdown,\n renderOption,\n setFocusedOptionIndex,\n setOpened,\n value,\n ]);\n\n const openedClassNames = React.useMemo(\n () =>\n (opened &&\n dropdownOffsetDistance === 0 &&\n (dropdownVerticalPlacement.includes('top') ? styles.popUp : styles.popDown)) ||\n undefined,\n [dropdownOffsetDistance, opened, dropdownVerticalPlacement],\n );\n\n const clearButtonShown = allowClearButton && (!!value.length || !!inputValue.length);\n\n return (\n <>\n <ChipsInputBase\n {...restProps}\n disabled={disabled}\n readOnly={readOnly}\n clearButtonShown={clearButtonShown}\n clearButtonTestId={clearButtonTestId}\n // FormFieldProps\n id={labelledbyId}\n getRootRef={rootRef}\n className={classNames(styles.host, openedClassNames, className)}\n status={status}\n after={\n dropdownIconProp || (\n <DropdownIcon\n opened={opened}\n onClick={onDropdownIconClick}\n className={classNames(\n styles.dropdownIcon,\n clearButtonShown && styles.dropdownIconWithOffset,\n )}\n />\n )\n }\n // option\n value={value}\n onAddChipOption={addOptionFromInput}\n onRemoveChipOption={removeOption}\n renderChip={renderChip}\n onClear={clearOptions}\n // input\n getRef={inputRef}\n inputValue={inputValue}\n onInputChange={onInputChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onKeyDown={handleKeyDown}\n // a11y\n role=\"combobox\"\n aria-expanded={opened}\n aria-autocomplete=\"list\"\n aria-activedescendant={opened ? dropdownCurrentItemId : undefined}\n aria-haspopup=\"listbox\"\n chipsListLabel={chipsListLabel}\n />\n {opened && (\n <CustomSelectDropdown\n data-testid={dropdownTestId}\n targetRef={rootRef}\n placement={dropdownVerticalPlacement}\n scrollBoxRef={dropdownScrollBoxRef}\n onPlacementChange={onDropdownPlacementChange}\n onMouseLeave={onDropdownMouseLeave}\n fetching={fetching}\n autoWidth={dropdownAutoWidth}\n forcePortal={forceDropdownPortal}\n noMaxHeight={noMaxHeight}\n offsetDistance={dropdownOffsetDistance}\n overscrollBehavior={overscrollBehavior}\n // a11y\n id={dropdownId}\n role=\"listbox\"\n aria-labelledby={labelledbyId}\n >\n {dropdownContent}\n </CustomSelectDropdown>\n )}\n </>\n );\n};\n"],"names":["React","classNames","useExternRef","useGlobalOnEventOutside","Keys","defaultFilterFn","ChipsInputBase","getNewOptionDataDefault","getOptionLabelDefault","getOptionValueDefault","renderChipDefault","CustomSelectDropdown","CustomSelectOption","DropdownIcon","Footnote","DEFAULT_EMPTY_TEXT","DEFAULT_SELECTED_BEHAVIOR","FOCUS_ACTION_NEXT","FOCUS_ACTION_PREV","isCreateNewOptionPreset","isEmptyOptionPreset","isNotServicePreset","renderOptionDefault","useChipsSelect","styles","findIndexAfter","options","startIndex","length","findIndex","option","i","disabled","findIndexBefore","endIndex","result","ChipsSelect","id","labelledbyId","getRootRef","className","status","icon","dropdownIconProp","onChangeStart","optionsProp","placement","placementProp","closeAfterSelect","selectedBehavior","emptyText","creatable","fetching","dropdownAutoWidth","forceDropdownPortal","noMaxHeight","filterFn","sortFn","dropdownTestId","onClose","onOpen","overscrollBehavior","renderDropdown","getRef","value","valueProp","defaultValue","inputValue","inputValueProp","defaultInputValue","readOnly","getOptionValue","getOptionLabel","getNewOptionData","renderChip","renderOption","onChange","onFocus","onFocusProp","onInputChange","onInputChangeProp","onBlur","onBlurProp","onKeyDown","onKeyDownProp","dropdownOffsetDistance","allowClearButton","clearButtonTestId","delimiter","chipsListLabel","restProps","addOptionFromInput","addOption","removeOption","clearOptions","inputRef","inputRefHook","clearInput","opened","setOpened","focusedOption","focusedOptionIndex","setFocusedOption","setFocusedOptionIndex","rootRef","dropdownVerticalPlacement","setDropdownVerticalPlacement","useState","onDropdownPlacementChange","useCallback","startsWith","dropdownId","useId","dropdownCurrentItemId","undefined","dropdownScrollBoxRef","useRef","handleFocus","event","handleBlur","defaultPrevented","preventDefault","chipsSelectOptions","current","scrollToElement","index","center","dropdown","item","dropdownHeight","offsetHeight","scrollTop","itemTop","offsetTop","itemHeight","focusOptionByIndex","oldIndex","focusOption","nextIndex","type","beforeIndex","handleKeyDown","key","ARROW_UP","ARROW_DOWN","ENTER","foundOption","ESCAPE","TAB","useEffect","foundFocusedOptionIndex","onDropdownMouseLeave","handleClickOutside","onDropdownIconClick","e","dropdownContent","useMemo","defaultDropdownContent","map","dropdownItemId","empty","placeholder","hovered","onMouseDown","onMouseEnter","actionText","Fragment","children","label","selected","find","selectedOption","node","openedClassNames","includes","popUp","popDown","clearButtonShown","host","after","onClick","dropdownIcon","dropdownIconWithOffset","onAddChipOption","onRemoveChipOption","onClear","role","aria-expanded","aria-autocomplete","aria-activedescendant","aria-haspopup","data-testid","targetRef","scrollBoxRef","onPlacementChange","onMouseLeave","autoWidth","forcePortal","offsetDistance","aria-labelledby"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "module",
3
- "version": "7.5.3",
3
+ "version": "7.5.4",
4
4
  "name": "@vkontakte/vkui",
5
5
  "description": "VKUI library",
6
6
  "module": "./dist/index.js",
@@ -194,10 +194,8 @@ export const ChipsInputBase = <O extends ChipOption>({
194
194
  };
195
195
 
196
196
  const handleRootClick = (event: React.MouseEvent<HTMLDivElement>) => {
197
- if (
198
- event.defaultPrevented ||
199
- contains(event.currentTarget, getActiveElementByAnotherElement(event.currentTarget))
200
- ) {
197
+ const activeElement = getActiveElementByAnotherElement(event.currentTarget);
198
+ if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {
201
199
  return;
202
200
  }
203
201
 
@@ -236,6 +234,29 @@ export const ChipsInputBase = <O extends ChipOption>({
236
234
 
237
235
  const inputId = idProp || `chips-input-base-generated-id-${idGenerated}`;
238
236
 
237
+ const handleRootMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
238
+ // Если клик был в один из чипов, то preventDefault делать не нужно, так как не будет срабатывать выделение текста
239
+ if (
240
+ isHTMLElement(e.target) &&
241
+ contains(listboxRef.current, e.target) &&
242
+ listboxRef.current !== e.target
243
+ ) {
244
+ return;
245
+ }
246
+ const activeElement = getActiveElementByAnotherElement(e.currentTarget);
247
+ // Когда выделен текст чипа не нужно делать preventDefault, чтобы сбросить выделение
248
+ if (contains(listboxRef.current, activeElement)) {
249
+ return;
250
+ }
251
+ // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста
252
+ if (e.target === inputRef.current) {
253
+ return;
254
+ }
255
+ // Делаем preventDefault, чтобы при клике в поле, вне инпута, высота поля не скакала от того,
256
+ // что фокус сначала пропадает из инпута, а потом возвращается
257
+ e.preventDefault();
258
+ };
259
+
239
260
  return (
240
261
  <FormField
241
262
  Component="div"
@@ -253,6 +274,7 @@ export const ChipsInputBase = <O extends ChipOption>({
253
274
  className={className}
254
275
  maxHeight={maxHeight}
255
276
  onClick={disabled ? undefined : handleRootClick}
277
+ onMouseDown={handleRootMouseDown}
256
278
  >
257
279
  <div
258
280
  className={classNames(
@@ -441,10 +441,8 @@ export const ChipsSelect = <Option extends ChipOption>({
441
441
 
442
442
  const onDropdownIconClick: MouseEventHandler<SVGSVGElement> = React.useCallback(
443
443
  (e) => {
444
- if (opened) {
445
- e.preventDefault();
446
- setOpened(false);
447
- }
444
+ e.preventDefault();
445
+ setOpened(!opened);
448
446
  },
449
447
  [opened, setOpened],
450
448
  );