@alauda/doom
Version:
Doctor Doom making docs.
55 lines (54 loc) • 2.56 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { clsx } from 'clsx';
import { useMemo, useState, } from 'react';
import stringWidth from 'string-width';
import SendIcon from '@alauda/doom/assets/send.svg?react';
import { useMemoizedFn, useTranslation } from '@alauda/doom/runtime';
import classes from '@alauda/doom/styles/resizable-user-input.module.scss';
export const ResizableUserInput = ({ value, loading, onChange, onSend, }) => {
const t = useTranslation();
const [innerValue, setInnerValue] = useState(value ?? '');
if (value != null && innerValue !== value) {
setInnerValue(value);
}
const maxCharsExceeded = innerValue.length > 2000;
const isSendDisabled = useMemo(() => loading || maxCharsExceeded || !innerValue.trim(), [loading, maxCharsExceeded, innerValue]);
const handleSend = useMemoizedFn(() => {
if (isSendDisabled) {
return;
}
const content = innerValue.trim();
if (!content) {
return;
}
onSend?.(content);
setInnerValue('');
});
const handleChange = useMemoizedFn((ev) => {
const value = ev.target.value;
onChange?.(value);
setInnerValue(value);
});
const onKeyDown = useMemoizedFn((ev) => {
ev.stopPropagation();
const event = ev.nativeEvent;
if (ev.key === 'Enter' &&
!event.isComposing &&
!ev.altKey &&
!ev.ctrlKey &&
!ev.metaKey &&
!ev.shiftKey) {
ev.preventDefault();
handleSend();
}
});
const textLines = useMemo(() => innerValue
.split(/\r?\n/)
.map((line) => Math.ceil(stringWidth(line) / /* 27 Chinese characters */ 54))
.reduce((acc, curr) => acc + curr, 0), [innerValue]);
const inputHeight = useMemo(() => Math.min(Math.max(textLines, 3), 8) * 20, [textLines]);
const inputStyle = useMemo(() => ({
minHeight: inputHeight,
}), [inputHeight]);
return (_jsxs("div", { className: clsx(classes.input, maxCharsExceeded && classes.error), children: [_jsx("textarea", { placeholder: t('ai_assistant_placeholder'), value: innerValue, onChange: handleChange, onKeyDown: onKeyDown, style: inputStyle }), _jsxs("div", { className: classes.actions, children: [_jsx(SendIcon, { className: clsx(classes.send, isSendDisabled && classes.disabled), onClick: handleSend }), maxCharsExceeded && (_jsx("span", { className: classes.errorTip, children: t('max_chars_exceeded_tip') }))] })] }));
};