Files
Genarrative/src/components/custom-world-agent/CustomWorldAgentComposer.tsx
2026-04-18 13:05:29 +08:00

75 lines
2.2 KiB
TypeScript

import type { RefObject } from 'react';
import { useState } from 'react';
import type { SendCustomWorldAgentMessageRequest } from '../../../packages/shared/src/contracts/customWorldAgent';
type CustomWorldAgentComposerProps = {
disabled: boolean;
onSubmit: (payload: SendCustomWorldAgentMessageRequest) => void;
textareaRef?: RefObject<HTMLTextAreaElement | null>;
};
function createClientMessageId() {
if (
typeof crypto !== 'undefined' &&
typeof crypto.randomUUID === 'function'
) {
return crypto.randomUUID();
}
return `client-message-${Date.now()}`;
}
export function CustomWorldAgentComposer({
disabled,
onSubmit,
textareaRef,
}: CustomWorldAgentComposerProps) {
const [text, setText] = useState('');
const submit = () => {
const nextText = text.trim();
if (!nextText || disabled) {
return;
}
onSubmit({
clientMessageId: createClientMessageId(),
text: nextText,
focusCardId: null,
selectedCardIds: [],
});
setText('');
};
return (
<div className="shrink-0 rounded-[1.75rem] border border-white/10 bg-[#111318]/95 p-4">
<div className="relative">
<textarea
ref={textareaRef}
value={text}
onChange={(event) => setText(event.target.value)}
onKeyDown={(event) => {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
submit();
}
}}
rows={3}
disabled={disabled}
placeholder="输入消息"
className="w-full resize-none rounded-[1.35rem] border border-white/10 bg-black/30 px-4 pb-12 pr-20 pt-3 text-sm leading-6 text-white outline-none transition focus:border-emerald-300/35 disabled:cursor-not-allowed disabled:opacity-60"
/>
<button
type="button"
onClick={submit}
disabled={disabled || !text.trim()}
className="absolute bottom-3 right-3 rounded-full border border-emerald-300/20 bg-emerald-500/10 px-4 py-2 text-sm font-medium text-emerald-100 transition hover:text-white disabled:cursor-not-allowed disabled:opacity-45"
>
</button>
</div>
</div>
);
}