UNPKG

@ant-design/x

Version:

Craft AI-driven interfaces effortlessly

159 lines (153 loc) 4.44 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import pickAttrs from '@rc-component/util/lib/pickAttrs'; import getValue from '@rc-component/util/lib/utils/get'; import { Input } from 'antd'; import { clsx } from 'clsx'; import React from 'react'; import { SenderContext } from "../context"; function getComponent(components, path, defaultComponent) { return getValue(components, path) || defaultComponent; } const TextArea = /*#__PURE__*/React.forwardRef((_, ref) => { const { value, onChange, onKeyUp, onKeyDown, onPaste, onPasteFile, disabled, readOnly, submitType = 'enter', prefixCls, styles = {}, classNames = {}, autoSize, components, triggerSend, placeholder, onFocus, onBlur, ...restProps } = React.useContext(SenderContext); const inputRef = React.useRef(null); const insert = (insertValue, positions = 'cursor') => { const textArea = inputRef.current?.resizableTextArea?.textArea; // 获取当前文本内容 const currentText = textArea.value; let startPos = currentText.length; let endPos = currentText.length; if (positions === 'cursor') { startPos = textArea?.selectionStart; endPos = textArea?.selectionEnd; } if (positions === 'start') { startPos = 0; endPos = 0; } // 在光标位置插入新文本 textArea.value = currentText.substring(0, startPos) + insertValue + currentText.substring(endPos, currentText.length); // 设置新的光标位置 textArea.selectionStart = startPos + insertValue.length; textArea.selectionEnd = startPos + insertValue.length; // 重新聚焦到textarea textArea.focus(); onChange?.(textArea.value); }; const clear = () => { onChange?.(''); }; const getValue = () => { return { value: value || '', slotConfig: [] }; }; React.useImperativeHandle(ref, () => { return { nativeElement: inputRef.current?.resizableTextArea?.textArea, focus: inputRef.current?.focus, blur: inputRef.current?.blur, insert, clear, getValue }; }); // ============================ Submit ============================ const isCompositionRef = React.useRef(false); const onInternalCompositionStart = () => { isCompositionRef.current = true; }; const onInternalCompositionEnd = () => { isCompositionRef.current = false; }; const onInternalKeyDown = e => { const eventRes = onKeyDown?.(e); const { key, shiftKey, ctrlKey, altKey, metaKey } = e; if (isCompositionRef.current || key !== 'Enter' || eventRes === false) { return; } // 处理Enter键提交 if (key === 'Enter') { const isModifierPressed = ctrlKey || altKey || metaKey; const shouldSubmit = submitType === 'enter' && !shiftKey && !isModifierPressed || submitType === 'shiftEnter' && shiftKey && !isModifierPressed; if (shouldSubmit) { e.preventDefault(); triggerSend?.(); return; } } }; // ============================ Paste ============================= const onInternalPaste = e => { // Get files const files = e.clipboardData?.files; const text = e.clipboardData?.getData('text/plain'); if (!text && files?.length && onPasteFile) { onPasteFile(files); e.preventDefault(); } onPaste?.(e); }; const InputTextArea = getComponent(components, ['input'], Input.TextArea); const domProps = pickAttrs(restProps, { attr: true, aria: true, data: true }); const inputProps = { ...domProps, ref: inputRef }; const mergeOnChange = event => { onChange?.(event.target.value, event); }; return /*#__PURE__*/React.createElement(InputTextArea, _extends({}, inputProps, { disabled: disabled, style: styles.input, className: clsx(`${prefixCls}-input`, classNames.input), autoSize: autoSize, value: value, onChange: mergeOnChange, onKeyUp: onKeyUp, onCompositionStart: onInternalCompositionStart, onCompositionEnd: onInternalCompositionEnd, onKeyDown: onInternalKeyDown, onPaste: onInternalPaste, variant: "borderless", readOnly: readOnly, placeholder: placeholder, onFocus: onFocus, onBlur: onBlur })); }); if (process.env.NODE_ENV !== 'production') { TextArea.displayName = 'TextArea'; } export default TextArea;