"use client"; import { useState, useRef, useCallback, KeyboardEvent } from "react"; import { Send, LayoutTemplate } from "lucide-react"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; import { ReplyQuote } from "./reply-quote"; interface ReplyDraft { /** Internal UUID of the message being replied to — sent back through onSend. */ id: string; authorLabel: string; preview: string; } interface MessageComposerProps { conversationId: string; sessionExpired: boolean; onSend: (text: string, replyToId?: string) => void; onOpenTemplates: () => void; replyTo?: ReplyDraft | null; onClearReply?: () => void; } export function MessageComposer({ conversationId, sessionExpired, onSend, onOpenTemplates, replyTo, onClearReply, }: MessageComposerProps) { const [text, setText] = useState(""); const [sending, setSending] = useState(false); const textareaRef = useRef(null); const adjustHeight = useCallback(() => { const el = textareaRef.current; if (!el) return; el.style.height = "auto"; // Max 4 lines (~96px) el.style.height = `${Math.min(el.scrollHeight, 96)}px`; }, []); const handleSend = useCallback(async () => { const trimmed = text.trim(); if (!trimmed || sending || sessionExpired) return; setSending(true); try { onSend(trimmed, replyTo?.id); setText(""); if (textareaRef.current) { textareaRef.current.style.height = "auto"; } } finally { setSending(false); } }, [text, sending, sessionExpired, onSend, replyTo?.id]); const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleSend(); } }, [handleSend] ); const handleChange = useCallback( (e: React.ChangeEvent) => { setText(e.target.value); adjustHeight(); }, [adjustHeight] ); return (
{replyTo && (
)} {sessionExpired && (

24-hour session expired. Use a template to re-engage.

)}