'use client'; import * as React from 'react'; import { classNames } from '@vkontakte/vkjs'; import { useAdaptivity } from '../../hooks/useAdaptivity'; import { useExternRef } from '../../hooks/useExternRef'; import { useMergeProps } from '../../hooks/useMergeProps'; import { usePlatform } from '../../hooks/usePlatform'; import { useResizeObserver } from '../../hooks/useResizeObserver'; import { callMultiple } from '../../lib/callMultiple'; import { useDOM } from '../../lib/dom'; import { warnOnce } from '../../lib/warnOnce'; import type { HasAlign, HasDataAttribute, HasRootRef } from '../../types'; import { FormField, type FormFieldProps } from '../FormField/FormField'; import { UnstyledTextField } from '../UnstyledTextField/UnstyledTextField'; import { useResizeTextarea } from './useResizeTextarea'; import styles from './Textarea.module.css'; const warn = warnOnce('Textarea'); const densityClassNames = { none: styles.densityNone, compact: styles.densityCompact, }; export interface TextareaProps extends Pick< React.TextareaHTMLAttributes, | 'autoComplete' | 'autoCapitalize' | 'autoCorrect' | 'cols' | 'dirName' | 'disabled' | 'maxLength' | 'minLength' | 'name' | 'placeholder' | 'readOnly' | 'required' | 'rows' | 'value' | 'wrap' | 'form' | 'onChange' | 'onFocus' | 'onBlur' >, Omit, 'onChange' | 'onFocus' | 'onBlur'>, HasRootRef, HasAlign, FormFieldProps { /** * @deprecated Since 7.9.0. Вместо этого используйте `slotProps={ textArea: { getRootRef: ... } }`. */ getRef?: React.Ref | undefined; /** * Свойства, которые можно прокинуть внутрь компонента: * - `root`: свойства для прокидывания в корень компонента; * - `textArea`: свойства для прокидывания в поле ввода. */ slotProps?: | { root?: | (React.HTMLAttributes & HasRootRef & HasDataAttribute) | undefined; textArea?: React.TextareaHTMLAttributes & HasRootRef & HasDataAttribute; } | undefined; /** * Свойство управляющее автоматическим изменением высоты компонента. */ grow?: boolean | undefined; /** * Обработчик, срабатывающий при изменении размера компонента. */ onResize?: ((el: HTMLTextAreaElement) => void) | undefined; /** * Значение по умолчанию. */ defaultValue?: string | undefined; } /** * @see https://vkui.io/components/textarea */ export const Textarea = ({ // FormFieldProps status, mode, after, before, afterAlign, beforeAlign, maxHeight, // TextareaProps grow = true, onResize, align, getRef, // textarea props autoComplete, autoCapitalize, autoCorrect, cols, dirName, disabled, maxLength, minLength, name, placeholder, readOnly, required, value: valueProp, wrap, rows = 2, form, onChange: onChangeProp, onFocus, onBlur, id, inputMode, defaultValue, autoFocus, tabIndex, spellCheck, slotProps, ...restProps }: TextareaProps): React.ReactNode => { /* istanbul ignore if: не проверяем в тестах */ if (process.env.NODE_ENV === 'development' && getRef) { warn('Свойство `getRef` устаревшее, используйте `slotProps={ textArea: { getRootRef: ... } }`'); } const { density = 'none' } = useAdaptivity(); const platform = usePlatform(); const { window } = useDOM(); const { className, ...rootProps } = useMergeProps(restProps, slotProps?.root); const { onChange, getRootRef: getTextAreaRef, value, ...textAreaRest } = useMergeProps( { className: styles.el, getRootRef: getRef, autoComplete, autoCapitalize, autoCorrect, cols, dirName, disabled, maxLength, minLength, name, placeholder, readOnly, required, value: valueProp, wrap, rows, form, onChange: onChangeProp, onFocus, onBlur, id, inputMode, defaultValue, autoFocus, tabIndex, spellCheck, }, slotProps?.textArea, ); const [refResizeTextarea, resize] = useResizeTextarea(onResize, grow); const elementRef = useExternRef(getTextAreaRef, refResizeTextarea); React.useEffect(resize, [resize, density, platform, value]); useResizeObserver(window, resize); return ( ); };