Files
zopu-code/apps/web/src/hooks/chat/use-chat-composer.ts
T
-Puter 5347db578d Polish chat UI and wire flue agent env
- Add chat components (header, composer, conversation, message, thinking response, identity)
- Add chat hooks (use-chat-agent, use-chat-composer)
- Add chat lib (constants, transforms, types)
- Wire agent model config through env (provider, name, api, base url, key, context window, max tokens)
- Refresh web styling and routes
2026-07-19 19:33:41 +05:30

59 lines
1.4 KiB
TypeScript

import type { ChangeEvent, FormEvent, KeyboardEvent } from "react";
import { useRef, useState } from "react";
interface UseChatComposerOptions {
busy: boolean;
onSend: (message: string) => Promise<void>;
}
export const useChatComposer = ({ busy, onSend }: UseChatComposerOptions) => {
const [draft, setDraft] = useState("");
const [isFocused, setIsFocused] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const canSend = draft.trim().length > 0 && !busy;
const handleSubmit = async (event?: FormEvent) => {
event?.preventDefault();
const message = draft.trim();
if (!message || busy) {
return;
}
setDraft("");
try {
await onSend(message);
} finally {
textareaRef.current?.focus();
}
};
const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
if (
event.key === "Enter" &&
!event.shiftKey &&
!event.nativeEvent.isComposing
) {
event.preventDefault();
void handleSubmit();
}
};
const inputProps = {
onBlur: () => setIsFocused(false),
onChange: (event: ChangeEvent<HTMLTextAreaElement>) =>
setDraft(event.target.value),
onFocus: () => setIsFocused(true),
onKeyDown: handleKeyDown,
ref: textareaRef,
value: draft,
};
return {
canSend,
draft,
handleSubmit,
inputProps,
isFocused,
};
};