@vkontakte/vkui 7.3.8 → 7.3.9

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.
@@ -51,9 +51,13 @@ export interface SearchProps extends React.InputHTMLAttributes<HTMLInputElement>
51
51
  * Передает атрибут `data-testid` для кнопки поиска.
52
52
  */
53
53
  findButtonTestId?: string;
54
+ /**
55
+ * Скрывает кнопку очистки.
56
+ */
57
+ hideClearButton?: boolean;
54
58
  }
55
59
  /**
56
60
  * @see https://vkcom.github.io/VKUI/#/Search
57
61
  */
58
- export declare const Search: ({ id: idProp, before, className, placeholder, after, getRef, icon: iconProp, onIconClick, style, autoComplete, onChange, iconLabel, clearLabel, clearButtonTestId, noPadding, getRootRef, findButtonText, findButtonTestId, onFindButtonClick, ...inputProps }: SearchProps) => React.ReactNode;
62
+ export declare const Search: ({ id: idProp, before, className, placeholder, after, getRef, icon: iconProp, onIconClick, style, autoComplete, onChange, iconLabel, clearLabel, clearButtonTestId, noPadding, getRootRef, findButtonText, findButtonTestId, onFindButtonClick, hideClearButton, ...inputProps }: SearchProps) => React.ReactNode;
59
63
  //# sourceMappingURL=Search.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Search.d.ts","sourceRoot":"","sources":["../../../src/components/Search/Search.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAa/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAK5E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,IAAI,EAAE,KAAK,CAAC,SAAS,EACrB,KAAK,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,gBAAgB,KAChD,KAAK,CAAC,YAAY,CAAC;AAExB,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EACjD,UAAU,CAAC,cAAc,CAAC,EAC1B,MAAM,CAAC,gBAAgB,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,EAAE,kBAAkB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7E;;OAEG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACrD;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzD;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,GAAI,gQAqBpB,WAAW,KAAG,KAAK,CAAC,SAkLtB,CAAC"}
1
+ {"version":3,"file":"Search.d.ts","sourceRoot":"","sources":["../../../src/components/Search/Search.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAa/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAExE,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAK5E,MAAM,MAAM,kBAAkB,GAAG,CAC/B,IAAI,EAAE,KAAK,CAAC,SAAS,EACrB,KAAK,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,gBAAgB,KAChD,KAAK,CAAC,YAAY,CAAC;AAExB,MAAM,WAAW,WACf,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EACjD,UAAU,CAAC,cAAc,CAAC,EAC1B,MAAM,CAAC,gBAAgB,CAAC;IAC1B;;OAEG;IACH,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB;;OAEG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB;;OAEG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,QAAQ,EAAE,kBAAkB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7E;;OAEG;IACH,WAAW,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;IACrD;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,iBAAiB,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACzD;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,GAAI,iRAsBpB,WAAW,KAAG,KAAK,CAAC,SA0LtB,CAAC"}
@@ -23,7 +23,7 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
23
23
  /**
24
24
  * @see https://vkcom.github.io/VKUI/#/Search
25
25
  */ export const Search = (_param)=>{
26
- var { id: idProp, before = /*#__PURE__*/ _jsx(Icon16SearchOutline, {}), className, placeholder = 'Поиск', after = 'Отмена', getRef, icon: iconProp, onIconClick, style, autoComplete = 'off', onChange, iconLabel, clearLabel = 'Очистить', clearButtonTestId, noPadding, getRootRef, findButtonText = 'Найти', findButtonTestId, onFindButtonClick } = _param, inputProps = _object_without_properties(_param, [
26
+ var { id: idProp, before = /*#__PURE__*/ _jsx(Icon16SearchOutline, {}), className, placeholder = 'Поиск', after = 'Отмена', getRef, icon: iconProp, onIconClick, style, autoComplete = 'off', onChange, iconLabel, clearLabel = 'Очистить', clearButtonTestId, noPadding, getRootRef, findButtonText = 'Найти', findButtonTestId, onFindButtonClick, hideClearButton } = _param, inputProps = _object_without_properties(_param, [
27
27
  "id",
28
28
  "before",
29
29
  "className",
@@ -42,7 +42,8 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
42
42
  "getRootRef",
43
43
  "findButtonText",
44
44
  "findButtonTestId",
45
- "onFindButtonClick"
45
+ "onFindButtonClick",
46
+ "hideClearButton"
46
47
  ]);
47
48
  const direction = useConfigDirection();
48
49
  const isRtl = direction === 'rtl';
@@ -115,6 +116,7 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
115
116
  icon
116
117
  ]
117
118
  }));
119
+ const showControls = Boolean(iconProp || !hideClearButton || adaptiveSizeY.compact && onFindButtonClick);
118
120
  return /*#__PURE__*/ _jsxs("div", {
119
121
  className: classNames('vkuiInternalSearch', "vkuiSearch__host", sizeY === 'none' && "vkuiSearch__sizeYNone", sizeY === 'compact' && "vkuiSearch__sizeYCompact", isFocused && "vkuiSearch__focused", hasValue && "vkuiSearch__hasValue", hasAfter && "vkuiSearch__hasAfter", iconProp && "vkuiSearch__hasIcon", inputProps.disabled && "vkuiSearch__disabled", !noPadding && "vkuiSearch__withPadding", isRtl && "vkuiSearch__rtl", className),
120
122
  ref: getRootRef,
@@ -149,11 +151,11 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
149
151
  }))
150
152
  ]
151
153
  }),
152
- /*#__PURE__*/ _jsxs("div", {
154
+ showControls && /*#__PURE__*/ _jsxs("div", {
153
155
  className: "vkuiSearch__controls",
154
156
  children: [
155
157
  iconProp && (typeof iconProp === 'function' ? iconProp(renderIconButton) : renderIconButton(iconProp)),
156
- /*#__PURE__*/ _jsxs(IconButton, {
158
+ !hideClearButton && /*#__PURE__*/ _jsxs(IconButton, {
157
159
  hoverMode: "opacity",
158
160
  onPointerDown: onIconCancelClickStart,
159
161
  onClick: onCancel,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAdaptivityConditionalRender } from '../../hooks/useAdaptivityConditionalRender';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useConfigDirection } from '../../hooks/useConfigDirection';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useNativeFormResetListener } from '../../hooks/useNativeFormResetListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { callMultiple } from '../../lib/callMultiple';\nimport { touchEnabled } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasDataAttribute, HasRef, HasRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton, type IconButtonProps } from '../IconButton/IconButton';\nimport { Headline } from '../Typography/Headline/Headline';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Search.module.css';\n\nexport type RenderIconButtonFn = (\n icon: React.ReactNode,\n props?: Partial<IconButtonProps> & HasDataAttribute,\n) => React.ReactElement;\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLInputElement> {\n /**\n * Only iOS. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n /**\n * Контент, отображаемый перед полем ввода.\n */\n before?: React.ReactNode;\n /**\n * Иконка поиска. Может быть React-элементом или функцией, возвращающей элемент.\n */\n icon?: React.ReactNode | ((renderFn: RenderIconButtonFn) => React.ReactNode);\n /**\n * Обработчик нажатия на иконку поиска.\n */\n onIconClick?: React.PointerEventHandler<HTMLElement>;\n /**\n * Значение поля ввода по умолчанию.\n */\n defaultValue?: string;\n /**\n * Текст для скринридеров, описывающий иконку поиска.\n */\n iconLabel?: string;\n /**\n * Текст для скринридеров, описывающий кнопку очистки.\n */\n clearLabel?: string;\n /**\n * Передает атрибут `data-testid` для кнопки очистки.\n */\n clearButtonTestId?: string;\n /**\n * Удаляет отступы у компонента.\n */\n noPadding?: boolean;\n /**\n * Текст для кнопки Найти.\n */\n findButtonText?: string;\n /**\n * Обработчик, при нажатии на кнопку \"Найти\".\n */\n onFindButtonClick?: React.MouseEventHandler<HTMLElement>;\n /**\n * Передает атрибут `data-testid` для кнопки поиска.\n */\n findButtonTestId?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n id: idProp,\n before = <Icon16SearchOutline />,\n className,\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon: iconProp,\n onIconClick,\n style,\n autoComplete = 'off',\n onChange,\n iconLabel,\n clearLabel = 'Очистить',\n clearButtonTestId,\n noPadding,\n getRootRef,\n findButtonText = 'Найти',\n findButtonTestId,\n onFindButtonClick,\n ...inputProps\n}: SearchProps): React.ReactNode => {\n const direction = useConfigDirection();\n const isRtl = direction === 'rtl';\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n const generatedId = React.useId();\n const inputId = idProp ? idProp : `search-${generatedId}`;\n\n const [hasValue, setHasValue] = React.useState<boolean>(() =>\n Boolean(inputProps.value || inputProps.defaultValue),\n );\n const checkHasValue: React.ChangeEventHandler<HTMLInputElement> = (e) =>\n setHasValue(Boolean(e.currentTarget.value));\n\n const { sizeY = 'none' } = useAdaptivity();\n const { sizeY: adaptiveSizeY } = useAdaptivityConditionalRender();\n const platform = usePlatform();\n\n const hasAfter = platform === 'ios' && hasReactNode(after);\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => onIconClick?.(e),\n [onIconClick],\n );\n\n const onIconCancelClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n inputRef.current?.focus();\n if (touchEnabled()) {\n onCancel();\n }\n },\n [inputRef, onCancel],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (inputProps.value !== undefined) {\n setHasValue(Boolean(inputProps.value));\n }\n }, [inputProps.value]);\n\n useNativeFormResetListener(inputRef, () => {\n setHasValue(Boolean(inputProps.defaultValue));\n });\n\n const renderIconButton: RenderIconButtonFn = (icon, props = {}) => (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconClickStart}\n className={styles.icon}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n onClick={noop}\n {...props}\n >\n <VisuallyHidden>{iconLabel}</VisuallyHidden>\n {icon}\n </IconButton>\n );\n\n return (\n <div\n className={classNames(\n 'vkuiInternalSearch',\n styles.host,\n sizeY === 'none' && styles.sizeYNone,\n sizeY === 'compact' && styles.sizeYCompact,\n isFocused && styles.focused,\n hasValue && styles.hasValue,\n hasAfter && styles.hasAfter,\n iconProp && styles.hasIcon,\n inputProps.disabled && styles.disabled,\n !noPadding && styles.withPadding,\n isRtl && styles.rtl,\n className,\n )}\n ref={getRootRef}\n style={style}\n >\n <div className={styles.field}>\n <label htmlFor={inputId} className={styles.label}>\n {placeholder}\n </label>\n <div className={styles.input}>\n {before}\n <Headline\n Component=\"input\"\n type=\"search\"\n level=\"1\"\n weight=\"3\"\n {...inputProps}\n id={inputId}\n placeholder={placeholder}\n autoComplete={autoComplete}\n getRootRef={inputRef}\n className={styles.nativeInput}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={callMultiple(onChange, checkHasValue)}\n />\n </div>\n <div className={styles.controls}>\n {iconProp &&\n (typeof iconProp === 'function'\n ? iconProp(renderIconButton)\n : renderIconButton(iconProp))}\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconCancelClickStart}\n onClick={onCancel}\n className={styles.icon}\n tabIndex={hasValue ? undefined : -1}\n disabled={inputProps.disabled}\n data-testid={clearButtonTestId}\n >\n <VisuallyHidden>{clearLabel}</VisuallyHidden>\n {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}\n </IconButton>\n {adaptiveSizeY.compact && onFindButtonClick && (\n <Button\n mode=\"primary\"\n size=\"m\"\n className={classNames(styles.findButton, adaptiveSizeY.compact.className)}\n focusVisibleMode=\"inside\"\n onClick={onFindButtonClick}\n tabIndex={hasValue ? undefined : -1}\n data-testid={findButtonTestId}\n >\n {findButtonText}\n </Button>\n )}\n </div>\n </div>\n {hasAfter && (\n <div className={styles.after}>\n <Button\n mode=\"tertiary\"\n size=\"m\"\n focusVisibleMode=\"inside\"\n hoverMode=\"opacity\"\n activeMode=\"opacity\"\n onClick={onCancel}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n >\n <span className={styles.afterTextClip}>{after}</span>\n </Button>\n </div>\n )}\n </div>\n );\n};\n"],"names":["React","Icon16Clear","Icon16SearchOutline","Icon24Cancel","classNames","hasReactNode","noop","useAdaptivity","useAdaptivityConditionalRender","useBooleanState","useConfigDirection","useExternRef","useNativeFormResetListener","usePlatform","callMultiple","touchEnabled","useIsomorphicLayoutEffect","Button","IconButton","Headline","VisuallyHidden","Search","id","idProp","before","className","placeholder","after","getRef","icon","iconProp","onIconClick","style","autoComplete","onChange","iconLabel","clearLabel","clearButtonTestId","noPadding","getRootRef","findButtonText","findButtonTestId","onFindButtonClick","inputProps","direction","isRtl","inputRef","value","isFocused","setTrue","setFocusedTrue","setFalse","setFocusedFalse","generatedId","useId","inputId","hasValue","setHasValue","useState","Boolean","defaultValue","checkHasValue","e","currentTarget","sizeY","adaptiveSizeY","platform","hasAfter","onFocus","onBlur","onCancel","useCallback","Object","nativeInputValueSetter","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","current","ev2","Event","bubbles","dispatchEvent","onIconClickStart","onIconCancelClickStart","preventDefault","focus","undefined","renderIconButton","props","hoverMode","onPointerDown","onClick","div","disabled","ref","label","htmlFor","Component","type","level","weight","tabIndex","data-testid","compact","mode","size","focusVisibleMode","activeMode","span"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/Search/Search.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAdaptivityConditionalRender } from '../../hooks/useAdaptivityConditionalRender';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useConfigDirection } from '../../hooks/useConfigDirection';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useNativeFormResetListener } from '../../hooks/useNativeFormResetListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { callMultiple } from '../../lib/callMultiple';\nimport { touchEnabled } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasDataAttribute, HasRef, HasRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton, type IconButtonProps } from '../IconButton/IconButton';\nimport { Headline } from '../Typography/Headline/Headline';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Search.module.css';\n\nexport type RenderIconButtonFn = (\n icon: React.ReactNode,\n props?: Partial<IconButtonProps> & HasDataAttribute,\n) => React.ReactElement;\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLInputElement> {\n /**\n * Only iOS. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n /**\n * Контент, отображаемый перед полем ввода.\n */\n before?: React.ReactNode;\n /**\n * Иконка поиска. Может быть React-элементом или функцией, возвращающей элемент.\n */\n icon?: React.ReactNode | ((renderFn: RenderIconButtonFn) => React.ReactNode);\n /**\n * Обработчик нажатия на иконку поиска.\n */\n onIconClick?: React.PointerEventHandler<HTMLElement>;\n /**\n * Значение поля ввода по умолчанию.\n */\n defaultValue?: string;\n /**\n * Текст для скринридеров, описывающий иконку поиска.\n */\n iconLabel?: string;\n /**\n * Текст для скринридеров, описывающий кнопку очистки.\n */\n clearLabel?: string;\n /**\n * Передает атрибут `data-testid` для кнопки очистки.\n */\n clearButtonTestId?: string;\n /**\n * Удаляет отступы у компонента.\n */\n noPadding?: boolean;\n /**\n * Текст для кнопки Найти.\n */\n findButtonText?: string;\n /**\n * Обработчик, при нажатии на кнопку \"Найти\".\n */\n onFindButtonClick?: React.MouseEventHandler<HTMLElement>;\n /**\n * Передает атрибут `data-testid` для кнопки поиска.\n */\n findButtonTestId?: string;\n /**\n * Скрывает кнопку очистки.\n */\n hideClearButton?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n id: idProp,\n before = <Icon16SearchOutline />,\n className,\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon: iconProp,\n onIconClick,\n style,\n autoComplete = 'off',\n onChange,\n iconLabel,\n clearLabel = 'Очистить',\n clearButtonTestId,\n noPadding,\n getRootRef,\n findButtonText = 'Найти',\n findButtonTestId,\n onFindButtonClick,\n hideClearButton,\n ...inputProps\n}: SearchProps): React.ReactNode => {\n const direction = useConfigDirection();\n const isRtl = direction === 'rtl';\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n const generatedId = React.useId();\n const inputId = idProp ? idProp : `search-${generatedId}`;\n\n const [hasValue, setHasValue] = React.useState<boolean>(() =>\n Boolean(inputProps.value || inputProps.defaultValue),\n );\n const checkHasValue: React.ChangeEventHandler<HTMLInputElement> = (e) =>\n setHasValue(Boolean(e.currentTarget.value));\n\n const { sizeY = 'none' } = useAdaptivity();\n const { sizeY: adaptiveSizeY } = useAdaptivityConditionalRender();\n const platform = usePlatform();\n\n const hasAfter = platform === 'ios' && hasReactNode(after);\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => onIconClick?.(e),\n [onIconClick],\n );\n\n const onIconCancelClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n inputRef.current?.focus();\n if (touchEnabled()) {\n onCancel();\n }\n },\n [inputRef, onCancel],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (inputProps.value !== undefined) {\n setHasValue(Boolean(inputProps.value));\n }\n }, [inputProps.value]);\n\n useNativeFormResetListener(inputRef, () => {\n setHasValue(Boolean(inputProps.defaultValue));\n });\n\n const renderIconButton: RenderIconButtonFn = (icon, props = {}) => (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconClickStart}\n className={styles.icon}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n onClick={noop}\n {...props}\n >\n <VisuallyHidden>{iconLabel}</VisuallyHidden>\n {icon}\n </IconButton>\n );\n\n const showControls = Boolean(\n iconProp || !hideClearButton || (adaptiveSizeY.compact && onFindButtonClick),\n );\n\n return (\n <div\n className={classNames(\n 'vkuiInternalSearch',\n styles.host,\n sizeY === 'none' && styles.sizeYNone,\n sizeY === 'compact' && styles.sizeYCompact,\n isFocused && styles.focused,\n hasValue && styles.hasValue,\n hasAfter && styles.hasAfter,\n iconProp && styles.hasIcon,\n inputProps.disabled && styles.disabled,\n !noPadding && styles.withPadding,\n isRtl && styles.rtl,\n className,\n )}\n ref={getRootRef}\n style={style}\n >\n <div className={styles.field}>\n <label htmlFor={inputId} className={styles.label}>\n {placeholder}\n </label>\n <div className={styles.input}>\n {before}\n <Headline\n Component=\"input\"\n type=\"search\"\n level=\"1\"\n weight=\"3\"\n {...inputProps}\n id={inputId}\n placeholder={placeholder}\n autoComplete={autoComplete}\n getRootRef={inputRef}\n className={styles.nativeInput}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={callMultiple(onChange, checkHasValue)}\n />\n </div>\n {showControls && (\n <div className={styles.controls}>\n {iconProp &&\n (typeof iconProp === 'function'\n ? iconProp(renderIconButton)\n : renderIconButton(iconProp))}\n {!hideClearButton && (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconCancelClickStart}\n onClick={onCancel}\n className={styles.icon}\n tabIndex={hasValue ? undefined : -1}\n disabled={inputProps.disabled}\n data-testid={clearButtonTestId}\n >\n <VisuallyHidden>{clearLabel}</VisuallyHidden>\n {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}\n </IconButton>\n )}\n {adaptiveSizeY.compact && onFindButtonClick && (\n <Button\n mode=\"primary\"\n size=\"m\"\n className={classNames(styles.findButton, adaptiveSizeY.compact.className)}\n focusVisibleMode=\"inside\"\n onClick={onFindButtonClick}\n tabIndex={hasValue ? undefined : -1}\n data-testid={findButtonTestId}\n >\n {findButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n {hasAfter && (\n <div className={styles.after}>\n <Button\n mode=\"tertiary\"\n size=\"m\"\n focusVisibleMode=\"inside\"\n hoverMode=\"opacity\"\n activeMode=\"opacity\"\n onClick={onCancel}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n >\n <span className={styles.afterTextClip}>{after}</span>\n </Button>\n </div>\n )}\n </div>\n );\n};\n"],"names":["React","Icon16Clear","Icon16SearchOutline","Icon24Cancel","classNames","hasReactNode","noop","useAdaptivity","useAdaptivityConditionalRender","useBooleanState","useConfigDirection","useExternRef","useNativeFormResetListener","usePlatform","callMultiple","touchEnabled","useIsomorphicLayoutEffect","Button","IconButton","Headline","VisuallyHidden","Search","id","idProp","before","className","placeholder","after","getRef","icon","iconProp","onIconClick","style","autoComplete","onChange","iconLabel","clearLabel","clearButtonTestId","noPadding","getRootRef","findButtonText","findButtonTestId","onFindButtonClick","hideClearButton","inputProps","direction","isRtl","inputRef","value","isFocused","setTrue","setFocusedTrue","setFalse","setFocusedFalse","generatedId","useId","inputId","hasValue","setHasValue","useState","Boolean","defaultValue","checkHasValue","e","currentTarget","sizeY","adaptiveSizeY","platform","hasAfter","onFocus","onBlur","onCancel","useCallback","Object","nativeInputValueSetter","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","current","ev2","Event","bubbles","dispatchEvent","onIconClickStart","onIconCancelClickStart","preventDefault","focus","undefined","renderIconButton","props","hoverMode","onPointerDown","onClick","showControls","compact","div","disabled","ref","label","htmlFor","Component","type","level","weight","tabIndex","data-testid","mode","size","focusVisibleMode","activeMode","span"],"mappings":"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"}
@@ -20,7 +20,7 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
20
20
  import styles from "./Search.module.css";
21
21
  /**
22
22
  * @see https://vkcom.github.io/VKUI/#/Search
23
- */ export const Search = ({ id: idProp, before = /*#__PURE__*/ _jsx(Icon16SearchOutline, {}), className, placeholder = 'Поиск', after = 'Отмена', getRef, icon: iconProp, onIconClick, style, autoComplete = 'off', onChange, iconLabel, clearLabel = 'Очистить', clearButtonTestId, noPadding, getRootRef, findButtonText = 'Найти', findButtonTestId, onFindButtonClick, ...inputProps })=>{
23
+ */ export const Search = ({ id: idProp, before = /*#__PURE__*/ _jsx(Icon16SearchOutline, {}), className, placeholder = 'Поиск', after = 'Отмена', getRef, icon: iconProp, onIconClick, style, autoComplete = 'off', onChange, iconLabel, clearLabel = 'Очистить', clearButtonTestId, noPadding, getRootRef, findButtonText = 'Найти', findButtonTestId, onFindButtonClick, hideClearButton, ...inputProps })=>{
24
24
  const direction = useConfigDirection();
25
25
  const isRtl = direction === 'rtl';
26
26
  const inputRef = useExternRef(getRef);
@@ -90,6 +90,7 @@ import styles from "./Search.module.css";
90
90
  icon
91
91
  ]
92
92
  });
93
+ const showControls = Boolean(iconProp || !hideClearButton || adaptiveSizeY.compact && onFindButtonClick);
93
94
  return /*#__PURE__*/ _jsxs("div", {
94
95
  className: classNames('vkuiInternalSearch', styles.host, sizeY === 'none' && styles.sizeYNone, sizeY === 'compact' && styles.sizeYCompact, isFocused && styles.focused, hasValue && styles.hasValue, hasAfter && styles.hasAfter, iconProp && styles.hasIcon, inputProps.disabled && styles.disabled, !noPadding && styles.withPadding, isRtl && styles.rtl, className),
95
96
  ref: getRootRef,
@@ -124,11 +125,11 @@ import styles from "./Search.module.css";
124
125
  })
125
126
  ]
126
127
  }),
127
- /*#__PURE__*/ _jsxs("div", {
128
+ showControls && /*#__PURE__*/ _jsxs("div", {
128
129
  className: styles.controls,
129
130
  children: [
130
131
  iconProp && (typeof iconProp === 'function' ? iconProp(renderIconButton) : renderIconButton(iconProp)),
131
- /*#__PURE__*/ _jsxs(IconButton, {
132
+ !hideClearButton && /*#__PURE__*/ _jsxs(IconButton, {
132
133
  hoverMode: "opacity",
133
134
  onPointerDown: onIconCancelClickStart,
134
135
  onClick: onCancel,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/components/Search/Search.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAdaptivityConditionalRender } from '../../hooks/useAdaptivityConditionalRender';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useConfigDirection } from '../../hooks/useConfigDirection';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useNativeFormResetListener } from '../../hooks/useNativeFormResetListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { callMultiple } from '../../lib/callMultiple';\nimport { touchEnabled } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasDataAttribute, HasRef, HasRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton, type IconButtonProps } from '../IconButton/IconButton';\nimport { Headline } from '../Typography/Headline/Headline';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Search.module.css';\n\nexport type RenderIconButtonFn = (\n icon: React.ReactNode,\n props?: Partial<IconButtonProps> & HasDataAttribute,\n) => React.ReactElement;\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLInputElement> {\n /**\n * Only iOS. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n /**\n * Контент, отображаемый перед полем ввода.\n */\n before?: React.ReactNode;\n /**\n * Иконка поиска. Может быть React-элементом или функцией, возвращающей элемент.\n */\n icon?: React.ReactNode | ((renderFn: RenderIconButtonFn) => React.ReactNode);\n /**\n * Обработчик нажатия на иконку поиска.\n */\n onIconClick?: React.PointerEventHandler<HTMLElement>;\n /**\n * Значение поля ввода по умолчанию.\n */\n defaultValue?: string;\n /**\n * Текст для скринридеров, описывающий иконку поиска.\n */\n iconLabel?: string;\n /**\n * Текст для скринридеров, описывающий кнопку очистки.\n */\n clearLabel?: string;\n /**\n * Передает атрибут `data-testid` для кнопки очистки.\n */\n clearButtonTestId?: string;\n /**\n * Удаляет отступы у компонента.\n */\n noPadding?: boolean;\n /**\n * Текст для кнопки Найти.\n */\n findButtonText?: string;\n /**\n * Обработчик, при нажатии на кнопку \"Найти\".\n */\n onFindButtonClick?: React.MouseEventHandler<HTMLElement>;\n /**\n * Передает атрибут `data-testid` для кнопки поиска.\n */\n findButtonTestId?: string;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n id: idProp,\n before = <Icon16SearchOutline />,\n className,\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon: iconProp,\n onIconClick,\n style,\n autoComplete = 'off',\n onChange,\n iconLabel,\n clearLabel = 'Очистить',\n clearButtonTestId,\n noPadding,\n getRootRef,\n findButtonText = 'Найти',\n findButtonTestId,\n onFindButtonClick,\n ...inputProps\n}: SearchProps): React.ReactNode => {\n const direction = useConfigDirection();\n const isRtl = direction === 'rtl';\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n const generatedId = React.useId();\n const inputId = idProp ? idProp : `search-${generatedId}`;\n\n const [hasValue, setHasValue] = React.useState<boolean>(() =>\n Boolean(inputProps.value || inputProps.defaultValue),\n );\n const checkHasValue: React.ChangeEventHandler<HTMLInputElement> = (e) =>\n setHasValue(Boolean(e.currentTarget.value));\n\n const { sizeY = 'none' } = useAdaptivity();\n const { sizeY: adaptiveSizeY } = useAdaptivityConditionalRender();\n const platform = usePlatform();\n\n const hasAfter = platform === 'ios' && hasReactNode(after);\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => onIconClick?.(e),\n [onIconClick],\n );\n\n const onIconCancelClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n inputRef.current?.focus();\n if (touchEnabled()) {\n onCancel();\n }\n },\n [inputRef, onCancel],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (inputProps.value !== undefined) {\n setHasValue(Boolean(inputProps.value));\n }\n }, [inputProps.value]);\n\n useNativeFormResetListener(inputRef, () => {\n setHasValue(Boolean(inputProps.defaultValue));\n });\n\n const renderIconButton: RenderIconButtonFn = (icon, props = {}) => (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconClickStart}\n className={styles.icon}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n onClick={noop}\n {...props}\n >\n <VisuallyHidden>{iconLabel}</VisuallyHidden>\n {icon}\n </IconButton>\n );\n\n return (\n <div\n className={classNames(\n 'vkuiInternalSearch',\n styles.host,\n sizeY === 'none' && styles.sizeYNone,\n sizeY === 'compact' && styles.sizeYCompact,\n isFocused && styles.focused,\n hasValue && styles.hasValue,\n hasAfter && styles.hasAfter,\n iconProp && styles.hasIcon,\n inputProps.disabled && styles.disabled,\n !noPadding && styles.withPadding,\n isRtl && styles.rtl,\n className,\n )}\n ref={getRootRef}\n style={style}\n >\n <div className={styles.field}>\n <label htmlFor={inputId} className={styles.label}>\n {placeholder}\n </label>\n <div className={styles.input}>\n {before}\n <Headline\n Component=\"input\"\n type=\"search\"\n level=\"1\"\n weight=\"3\"\n {...inputProps}\n id={inputId}\n placeholder={placeholder}\n autoComplete={autoComplete}\n getRootRef={inputRef}\n className={styles.nativeInput}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={callMultiple(onChange, checkHasValue)}\n />\n </div>\n <div className={styles.controls}>\n {iconProp &&\n (typeof iconProp === 'function'\n ? iconProp(renderIconButton)\n : renderIconButton(iconProp))}\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconCancelClickStart}\n onClick={onCancel}\n className={styles.icon}\n tabIndex={hasValue ? undefined : -1}\n disabled={inputProps.disabled}\n data-testid={clearButtonTestId}\n >\n <VisuallyHidden>{clearLabel}</VisuallyHidden>\n {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}\n </IconButton>\n {adaptiveSizeY.compact && onFindButtonClick && (\n <Button\n mode=\"primary\"\n size=\"m\"\n className={classNames(styles.findButton, adaptiveSizeY.compact.className)}\n focusVisibleMode=\"inside\"\n onClick={onFindButtonClick}\n tabIndex={hasValue ? undefined : -1}\n data-testid={findButtonTestId}\n >\n {findButtonText}\n </Button>\n )}\n </div>\n </div>\n {hasAfter && (\n <div className={styles.after}>\n <Button\n mode=\"tertiary\"\n size=\"m\"\n focusVisibleMode=\"inside\"\n hoverMode=\"opacity\"\n activeMode=\"opacity\"\n onClick={onCancel}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n >\n <span className={styles.afterTextClip}>{after}</span>\n </Button>\n </div>\n )}\n </div>\n );\n};\n"],"names":["React","Icon16Clear","Icon16SearchOutline","Icon24Cancel","classNames","hasReactNode","noop","useAdaptivity","useAdaptivityConditionalRender","useBooleanState","useConfigDirection","useExternRef","useNativeFormResetListener","usePlatform","callMultiple","touchEnabled","useIsomorphicLayoutEffect","Button","IconButton","Headline","VisuallyHidden","styles","Search","id","idProp","before","className","placeholder","after","getRef","icon","iconProp","onIconClick","style","autoComplete","onChange","iconLabel","clearLabel","clearButtonTestId","noPadding","getRootRef","findButtonText","findButtonTestId","onFindButtonClick","inputProps","direction","isRtl","inputRef","value","isFocused","setTrue","setFocusedTrue","setFalse","setFocusedFalse","generatedId","useId","inputId","hasValue","setHasValue","useState","Boolean","defaultValue","checkHasValue","e","currentTarget","sizeY","adaptiveSizeY","platform","hasAfter","onFocus","onBlur","onCancel","useCallback","nativeInputValueSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","current","ev2","Event","bubbles","dispatchEvent","onIconClickStart","onIconCancelClickStart","preventDefault","focus","undefined","renderIconButton","props","hoverMode","onPointerDown","onClick","div","host","sizeYNone","sizeYCompact","focused","hasIcon","disabled","withPadding","rtl","ref","field","label","htmlFor","input","Component","type","level","weight","nativeInput","controls","tabIndex","data-testid","compact","mode","size","findButton","focusVisibleMode","activeMode","span","afterTextClip"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/components/Search/Search.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Icon16Clear, Icon16SearchOutline, Icon24Cancel } from '@vkontakte/icons';\nimport { classNames, hasReactNode, noop } from '@vkontakte/vkjs';\nimport { useAdaptivity } from '../../hooks/useAdaptivity';\nimport { useAdaptivityConditionalRender } from '../../hooks/useAdaptivityConditionalRender';\nimport { useBooleanState } from '../../hooks/useBooleanState';\nimport { useConfigDirection } from '../../hooks/useConfigDirection';\nimport { useExternRef } from '../../hooks/useExternRef';\nimport { useNativeFormResetListener } from '../../hooks/useNativeFormResetListener';\nimport { usePlatform } from '../../hooks/usePlatform';\nimport { callMultiple } from '../../lib/callMultiple';\nimport { touchEnabled } from '../../lib/touch';\nimport { useIsomorphicLayoutEffect } from '../../lib/useIsomorphicLayoutEffect';\nimport type { HasDataAttribute, HasRef, HasRootRef } from '../../types';\nimport { Button } from '../Button/Button';\nimport { IconButton, type IconButtonProps } from '../IconButton/IconButton';\nimport { Headline } from '../Typography/Headline/Headline';\nimport { VisuallyHidden } from '../VisuallyHidden/VisuallyHidden';\nimport styles from './Search.module.css';\n\nexport type RenderIconButtonFn = (\n icon: React.ReactNode,\n props?: Partial<IconButtonProps> & HasDataAttribute,\n) => React.ReactElement;\n\nexport interface SearchProps\n extends React.InputHTMLAttributes<HTMLInputElement>,\n HasRootRef<HTMLDivElement>,\n HasRef<HTMLInputElement> {\n /**\n * Only iOS. Текст кнопки \"отмена\", которая чистит текстовое поле и убирает фокус.\n */\n after?: React.ReactNode;\n /**\n * Контент, отображаемый перед полем ввода.\n */\n before?: React.ReactNode;\n /**\n * Иконка поиска. Может быть React-элементом или функцией, возвращающей элемент.\n */\n icon?: React.ReactNode | ((renderFn: RenderIconButtonFn) => React.ReactNode);\n /**\n * Обработчик нажатия на иконку поиска.\n */\n onIconClick?: React.PointerEventHandler<HTMLElement>;\n /**\n * Значение поля ввода по умолчанию.\n */\n defaultValue?: string;\n /**\n * Текст для скринридеров, описывающий иконку поиска.\n */\n iconLabel?: string;\n /**\n * Текст для скринридеров, описывающий кнопку очистки.\n */\n clearLabel?: string;\n /**\n * Передает атрибут `data-testid` для кнопки очистки.\n */\n clearButtonTestId?: string;\n /**\n * Удаляет отступы у компонента.\n */\n noPadding?: boolean;\n /**\n * Текст для кнопки Найти.\n */\n findButtonText?: string;\n /**\n * Обработчик, при нажатии на кнопку \"Найти\".\n */\n onFindButtonClick?: React.MouseEventHandler<HTMLElement>;\n /**\n * Передает атрибут `data-testid` для кнопки поиска.\n */\n findButtonTestId?: string;\n /**\n * Скрывает кнопку очистки.\n */\n hideClearButton?: boolean;\n}\n\n/**\n * @see https://vkcom.github.io/VKUI/#/Search\n */\nexport const Search = ({\n id: idProp,\n before = <Icon16SearchOutline />,\n className,\n placeholder = 'Поиск',\n after = 'Отмена',\n getRef,\n icon: iconProp,\n onIconClick,\n style,\n autoComplete = 'off',\n onChange,\n iconLabel,\n clearLabel = 'Очистить',\n clearButtonTestId,\n noPadding,\n getRootRef,\n findButtonText = 'Найти',\n findButtonTestId,\n onFindButtonClick,\n hideClearButton,\n ...inputProps\n}: SearchProps): React.ReactNode => {\n const direction = useConfigDirection();\n const isRtl = direction === 'rtl';\n const inputRef = useExternRef(getRef);\n const {\n value: isFocused,\n setTrue: setFocusedTrue,\n setFalse: setFocusedFalse,\n } = useBooleanState(false);\n const generatedId = React.useId();\n const inputId = idProp ? idProp : `search-${generatedId}`;\n\n const [hasValue, setHasValue] = React.useState<boolean>(() =>\n Boolean(inputProps.value || inputProps.defaultValue),\n );\n const checkHasValue: React.ChangeEventHandler<HTMLInputElement> = (e) =>\n setHasValue(Boolean(e.currentTarget.value));\n\n const { sizeY = 'none' } = useAdaptivity();\n const { sizeY: adaptiveSizeY } = useAdaptivityConditionalRender();\n const platform = usePlatform();\n\n const hasAfter = platform === 'ios' && hasReactNode(after);\n\n const onFocus = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedTrue();\n inputProps.onFocus && inputProps.onFocus(e);\n };\n\n const onBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n setFocusedFalse();\n inputProps.onBlur && inputProps.onBlur(e);\n };\n\n const onCancel = React.useCallback(() => {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n const nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n HTMLInputElement.prototype,\n 'value',\n )?.set;\n nativeInputValueSetter?.call(inputRef.current, '');\n\n const ev2 = new Event('input', { bubbles: true });\n inputRef.current?.dispatchEvent(ev2);\n }, [inputRef]);\n\n const onIconClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => onIconClick?.(e),\n [onIconClick],\n );\n\n const onIconCancelClickStart: React.PointerEventHandler<HTMLElement> = React.useCallback(\n (e) => {\n e.preventDefault();\n inputRef.current?.focus();\n if (touchEnabled()) {\n onCancel();\n }\n },\n [inputRef, onCancel],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (inputProps.value !== undefined) {\n setHasValue(Boolean(inputProps.value));\n }\n }, [inputProps.value]);\n\n useNativeFormResetListener(inputRef, () => {\n setHasValue(Boolean(inputProps.defaultValue));\n });\n\n const renderIconButton: RenderIconButtonFn = (icon, props = {}) => (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconClickStart}\n className={styles.icon}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n onClick={noop}\n {...props}\n >\n <VisuallyHidden>{iconLabel}</VisuallyHidden>\n {icon}\n </IconButton>\n );\n\n const showControls = Boolean(\n iconProp || !hideClearButton || (adaptiveSizeY.compact && onFindButtonClick),\n );\n\n return (\n <div\n className={classNames(\n 'vkuiInternalSearch',\n styles.host,\n sizeY === 'none' && styles.sizeYNone,\n sizeY === 'compact' && styles.sizeYCompact,\n isFocused && styles.focused,\n hasValue && styles.hasValue,\n hasAfter && styles.hasAfter,\n iconProp && styles.hasIcon,\n inputProps.disabled && styles.disabled,\n !noPadding && styles.withPadding,\n isRtl && styles.rtl,\n className,\n )}\n ref={getRootRef}\n style={style}\n >\n <div className={styles.field}>\n <label htmlFor={inputId} className={styles.label}>\n {placeholder}\n </label>\n <div className={styles.input}>\n {before}\n <Headline\n Component=\"input\"\n type=\"search\"\n level=\"1\"\n weight=\"3\"\n {...inputProps}\n id={inputId}\n placeholder={placeholder}\n autoComplete={autoComplete}\n getRootRef={inputRef}\n className={styles.nativeInput}\n onFocus={onFocus}\n onBlur={onBlur}\n onChange={callMultiple(onChange, checkHasValue)}\n />\n </div>\n {showControls && (\n <div className={styles.controls}>\n {iconProp &&\n (typeof iconProp === 'function'\n ? iconProp(renderIconButton)\n : renderIconButton(iconProp))}\n {!hideClearButton && (\n <IconButton\n hoverMode=\"opacity\"\n onPointerDown={onIconCancelClickStart}\n onClick={onCancel}\n className={styles.icon}\n tabIndex={hasValue ? undefined : -1}\n disabled={inputProps.disabled}\n data-testid={clearButtonTestId}\n >\n <VisuallyHidden>{clearLabel}</VisuallyHidden>\n {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}\n </IconButton>\n )}\n {adaptiveSizeY.compact && onFindButtonClick && (\n <Button\n mode=\"primary\"\n size=\"m\"\n className={classNames(styles.findButton, adaptiveSizeY.compact.className)}\n focusVisibleMode=\"inside\"\n onClick={onFindButtonClick}\n tabIndex={hasValue ? undefined : -1}\n data-testid={findButtonTestId}\n >\n {findButtonText}\n </Button>\n )}\n </div>\n )}\n </div>\n {hasAfter && (\n <div className={styles.after}>\n <Button\n mode=\"tertiary\"\n size=\"m\"\n focusVisibleMode=\"inside\"\n hoverMode=\"opacity\"\n activeMode=\"opacity\"\n onClick={onCancel}\n onFocus={setFocusedTrue}\n onBlur={setFocusedFalse}\n >\n <span className={styles.afterTextClip}>{after}</span>\n </Button>\n </div>\n )}\n </div>\n );\n};\n"],"names":["React","Icon16Clear","Icon16SearchOutline","Icon24Cancel","classNames","hasReactNode","noop","useAdaptivity","useAdaptivityConditionalRender","useBooleanState","useConfigDirection","useExternRef","useNativeFormResetListener","usePlatform","callMultiple","touchEnabled","useIsomorphicLayoutEffect","Button","IconButton","Headline","VisuallyHidden","styles","Search","id","idProp","before","className","placeholder","after","getRef","icon","iconProp","onIconClick","style","autoComplete","onChange","iconLabel","clearLabel","clearButtonTestId","noPadding","getRootRef","findButtonText","findButtonTestId","onFindButtonClick","hideClearButton","inputProps","direction","isRtl","inputRef","value","isFocused","setTrue","setFocusedTrue","setFalse","setFocusedFalse","generatedId","useId","inputId","hasValue","setHasValue","useState","Boolean","defaultValue","checkHasValue","e","currentTarget","sizeY","adaptiveSizeY","platform","hasAfter","onFocus","onBlur","onCancel","useCallback","nativeInputValueSetter","Object","getOwnPropertyDescriptor","HTMLInputElement","prototype","set","call","current","ev2","Event","bubbles","dispatchEvent","onIconClickStart","onIconCancelClickStart","preventDefault","focus","undefined","renderIconButton","props","hoverMode","onPointerDown","onClick","showControls","compact","div","host","sizeYNone","sizeYCompact","focused","hasIcon","disabled","withPadding","rtl","ref","field","label","htmlFor","input","Component","type","level","weight","nativeInput","controls","tabIndex","data-testid","mode","size","findButton","focusVisibleMode","activeMode","span","afterTextClip"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "type": "module",
3
- "version": "7.3.8",
3
+ "version": "7.3.9",
4
4
  "name": "@vkontakte/vkui",
5
5
  "description": "VKUI library",
6
6
  "module": "./dist/index.js",
@@ -77,6 +77,10 @@ export interface SearchProps
77
77
  * Передает атрибут `data-testid` для кнопки поиска.
78
78
  */
79
79
  findButtonTestId?: string;
80
+ /**
81
+ * Скрывает кнопку очистки.
82
+ */
83
+ hideClearButton?: boolean;
80
84
  }
81
85
 
82
86
  /**
@@ -102,6 +106,7 @@ export const Search = ({
102
106
  findButtonText = 'Найти',
103
107
  findButtonTestId,
104
108
  onFindButtonClick,
109
+ hideClearButton,
105
110
  ...inputProps
106
111
  }: SearchProps): React.ReactNode => {
107
112
  const direction = useConfigDirection();
@@ -190,6 +195,10 @@ export const Search = ({
190
195
  </IconButton>
191
196
  );
192
197
 
198
+ const showControls = Boolean(
199
+ iconProp || !hideClearButton || (adaptiveSizeY.compact && onFindButtonClick),
200
+ );
201
+
193
202
  return (
194
203
  <div
195
204
  className={classNames(
@@ -231,37 +240,41 @@ export const Search = ({
231
240
  onChange={callMultiple(onChange, checkHasValue)}
232
241
  />
233
242
  </div>
234
- <div className={styles.controls}>
235
- {iconProp &&
236
- (typeof iconProp === 'function'
237
- ? iconProp(renderIconButton)
238
- : renderIconButton(iconProp))}
239
- <IconButton
240
- hoverMode="opacity"
241
- onPointerDown={onIconCancelClickStart}
242
- onClick={onCancel}
243
- className={styles.icon}
244
- tabIndex={hasValue ? undefined : -1}
245
- disabled={inputProps.disabled}
246
- data-testid={clearButtonTestId}
247
- >
248
- <VisuallyHidden>{clearLabel}</VisuallyHidden>
249
- {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}
250
- </IconButton>
251
- {adaptiveSizeY.compact && onFindButtonClick && (
252
- <Button
253
- mode="primary"
254
- size="m"
255
- className={classNames(styles.findButton, adaptiveSizeY.compact.className)}
256
- focusVisibleMode="inside"
257
- onClick={onFindButtonClick}
258
- tabIndex={hasValue ? undefined : -1}
259
- data-testid={findButtonTestId}
260
- >
261
- {findButtonText}
262
- </Button>
263
- )}
264
- </div>
243
+ {showControls && (
244
+ <div className={styles.controls}>
245
+ {iconProp &&
246
+ (typeof iconProp === 'function'
247
+ ? iconProp(renderIconButton)
248
+ : renderIconButton(iconProp))}
249
+ {!hideClearButton && (
250
+ <IconButton
251
+ hoverMode="opacity"
252
+ onPointerDown={onIconCancelClickStart}
253
+ onClick={onCancel}
254
+ className={styles.icon}
255
+ tabIndex={hasValue ? undefined : -1}
256
+ disabled={inputProps.disabled}
257
+ data-testid={clearButtonTestId}
258
+ >
259
+ <VisuallyHidden>{clearLabel}</VisuallyHidden>
260
+ {platform === 'ios' ? <Icon16Clear /> : <Icon24Cancel />}
261
+ </IconButton>
262
+ )}
263
+ {adaptiveSizeY.compact && onFindButtonClick && (
264
+ <Button
265
+ mode="primary"
266
+ size="m"
267
+ className={classNames(styles.findButton, adaptiveSizeY.compact.className)}
268
+ focusVisibleMode="inside"
269
+ onClick={onFindButtonClick}
270
+ tabIndex={hasValue ? undefined : -1}
271
+ data-testid={findButtonTestId}
272
+ >
273
+ {findButtonText}
274
+ </Button>
275
+ )}
276
+ </div>
277
+ )}
265
278
  </div>
266
279
  {hasAfter && (
267
280
  <div className={styles.after}>