import cns from 'classnames' import RcTextarea, { AutoSizeType, TextAreaRef } from 'rc-textarea' import React, { ChangeEvent, Ref, TextareaHTMLAttributes, useCallback } from 'react' import { useFormInfo } from '../Form/defs' import { usePrefix } from '../ConfigProvider' import { concat, fillRef } from '../utils' import { useFocused, useValue } from '../utils/hooks' import { CommonProps, useInputStyle } from './input' import { WithRef } from '../utils/type' export type { AutoSizeType } export interface Props extends CommonProps { /** 最大字数限制,如有则会在右下角展示字数信息 */ maxCount?: number /** 自适应内容高度 */ autoSize?: boolean | AutoSizeType /** * 获取 textarea 引用 * * @deprecated use textareaProps.ref instead */ textareaRef?: Ref /** 需要传给 `textarea` 的属性 */ textareaProps?: WithRef, HTMLTextAreaElement> } export default function TextArea({ value: valueFromProps, defaultValue = '', onChange, placeholder, disabled = false, size, validateStatus, maxCount, autoSize = false, textareaRef, textareaProps, ...otherProps }: Props) { const textAreaClassName = usePrefix('text-area') const innerTextAreaClassName = concat(textAreaClassName, 'inner') const { focused, focusedHandlers } = useFocused(textareaProps, disabled) const { value, setValue } = useValue({ valueFromProps, defaultValue, onChange }) const formInfo = useFormInfo() const className = cns( textAreaClassName, concat(textAreaClassName, 'size', size ?? formInfo.size), otherProps.className ) const inputStyle = useInputStyle({ focused, validateStatus, size, disabled }) const innerClassName = cns(inputStyle, innerTextAreaClassName) const count = getTextCount(value) const countView = maxCount != null && ( {count}/{maxCount} ) const rcTextareaRef = useCallback((rcTextarea: TextAreaRef | null) => { if (textareaRef != null) { fillRef(textareaRef, rcTextarea?.resizableTextArea.textArea) } if (textareaProps?.ref) { fillRef(textareaProps?.ref, rcTextarea?.resizableTextArea.textArea) } }, [textareaProps?.ref, textareaRef]) const handleChange = useCallback((e: ChangeEvent) => { textareaProps?.onChange?.(e) setValue(e.target.value) }, [textareaProps, setValue]) return (
{countView}
) } // 获取 unicode 字符数 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#unicode export function getTextCount(str: string) { // The string iterator that is used here iterates over characters, // not mere code units return [...(str as any)].length }