Files
zopu-code/repos/web/hooks/chat/use-chat-composer.ts
-Puter cc47007fa9 Slice 1 polish: archive dormant code, merge work-os into primitives, add futures
- Archive dormant apps (daemon, desktop, native, tui) and superseded
  packages/server into repos/ for reference
- Archive 21 dead web components (chat page shell, work-os cluster, strays)
  into repos/web/; keep reused message-rendering primitives in components/chat
- Merge @code/work-os into @code/primitives; work.ts absorbed via ./work
  subpath and barrel export; update all four importers
- Add docs/futures.md tracking audio/video (blocked at Flue + provider),
  web layout cleanup, and message rendering quality
- Repoint dev:zopu script to @code/agents (the live Flue server)
- Note repos/ reference-code convention in AGENTS.md
2026-07-27 16:34:17 +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,
};
};